// server/services/credentials.ts import { eq } from "drizzle-orm"; import { db, schema } from "../db/client.js"; interface EncPair { encPassword: string | null; encSudoPassword: string | null; } /** Résout la source des secrets : machine_credentials prioritaire, sinon legacy machines (fonction pure). */ export function resolveCreds(legacy: EncPair, creds: EncPair | null): EncPair { if (creds && creds.encPassword) return { encPassword: creds.encPassword, encSudoPassword: creds.encSudoPassword }; return { encPassword: legacy.encPassword, encSudoPassword: legacy.encSudoPassword }; } /** Écrit (insert/replace) la ligne machine_credentials pour une machine (secrets déjà chiffrés). */ export function writeCredentials(input: { machineId: string; encPassword: string | null; encSudoPassword: string | null; }): void { const now = new Date().toISOString(); db.insert(schema.machineCredentials) .values({ machineId: input.machineId, authMethod: "password", encPassword: input.encPassword, encSudoPassword: input.encSudoPassword, sudoMode: input.encSudoPassword ? "separate" : "same_as_ssh", createdAt: now, updatedAt: now, status: "unknown", }) .onConflictDoUpdate({ target: schema.machineCredentials.machineId, set: { encPassword: input.encPassword, encSudoPassword: input.encSudoPassword, updatedAt: now }, }) .run(); } /** Lit la ligne machine_credentials (ou null). */ export function readCredentials(machineId: string): EncPair | null { const row = db.select().from(schema.machineCredentials) .where(eq(schema.machineCredentials.machineId, machineId)).get(); return row ? { encPassword: row.encPassword, encSudoPassword: row.encSudoPassword } : null; } /** Backfill idempotent : crée une ligne machine_credentials pour chaque machine qui n'en a pas. */ export function backfillCredentials(): number { const machines = db.select().from(schema.machines).all(); let created = 0; for (const m of machines) { if (readCredentials(m.id)) continue; writeCredentials({ machineId: m.id, encPassword: m.encPassword, encSudoPassword: m.encSudoPassword }); created++; } return created; }