feat(agent): self-heal rustdesk remote access

This commit is contained in:
Esdras Renan 2025-11-11 17:50:09 -03:00
parent 308f7b5712
commit 115d4a62e8
5 changed files with 391 additions and 71 deletions

View file

@ -183,7 +183,16 @@ function hashToken(token: string) {
return toHex(sha256(token))
}
const REMOTE_ACCESS_TOKEN_GRACE_MS = 5 * 60 * 1000
function getRemoteAccessTokenGraceMs() {
const fallback = 15 * 60 * 1000
const raw = process.env["REMOTE_ACCESS_TOKEN_GRACE_MS"]
if (!raw) return fallback
const parsed = Number(raw)
if (!Number.isFinite(parsed) || parsed <= 0) return fallback
return parsed
}
const REMOTE_ACCESS_TOKEN_GRACE_MS = getRemoteAccessTokenGraceMs()
async function getTokenRecord(
ctx: MutationCtx | QueryCtx,
@ -777,6 +786,10 @@ export const heartbeat = mutation({
if (args.metadata && typeof args.metadata === "object") {
Object.assign(metadataPatch, args.metadata as Record<string, unknown>)
}
const remoteAccessSnapshot = metadataPatch["remoteAccessSnapshot"]
if (remoteAccessSnapshot !== undefined) {
delete metadataPatch["remoteAccessSnapshot"]
}
if (args.inventory && typeof args.inventory === "object") {
metadataPatch.inventory = mergeInventory(metadataPatch.inventory, args.inventory as Record<string, unknown>)
}
@ -800,6 +813,10 @@ export const heartbeat = mutation({
metadata: mergedMetadata,
})
if (remoteAccessSnapshot) {
await upsertRemoteAccessSnapshotFromHeartbeat(ctx, machine, remoteAccessSnapshot, now)
}
await ctx.db.patch(token._id, {
lastUsedAt: now,
usageCount: (token.usageCount ?? 0) + 1,
@ -2149,6 +2166,55 @@ function normalizeRemoteAccessList(raw: unknown): RemoteAccessEntry[] {
return entries
}
async function upsertRemoteAccessSnapshotFromHeartbeat(
ctx: MutationCtx,
machine: Doc<"machines">,
snapshot: unknown,
timestamp: number
) {
const normalized = normalizeRemoteAccessEntry(snapshot)
if (!normalized) return
const provider = (normalized.provider ?? "Remote").trim()
const identifier = (normalized.identifier ?? "").trim()
if (!identifier) return
const existingEntries = normalizeRemoteAccessList(machine.remoteAccess)
const idx = existingEntries.findIndex(
(entry) => entry.provider.toLowerCase() === provider.toLowerCase() && entry.identifier.toLowerCase() === identifier.toLowerCase()
)
const entryId = idx >= 0 ? existingEntries[idx].id : createRemoteAccessId()
const metadata = {
...(normalized.metadata ?? {}),
snapshotSource: "heartbeat",
provider,
identifier,
lastVerifiedAt: timestamp,
}
const updatedEntry: RemoteAccessEntry = {
id: entryId,
provider,
identifier,
url: normalized.url ?? null,
username: normalized.username ?? null,
password: normalized.password ?? null,
notes: normalized.notes ?? null,
lastVerifiedAt: timestamp,
metadata,
}
const nextEntries =
idx >= 0
? existingEntries.map((entry, index) => (index === idx ? updatedEntry : entry))
: [...existingEntries, updatedEntry]
await ctx.db.patch(machine._id, {
remoteAccess: nextEntries,
updatedAt: timestamp,
})
}
export const updateRemoteAccess = mutation({
args: {
machineId: v.id("machines"),