'use node'; import { ConvexError, v } from 'convex/values'; import { internal } from './_generated/api'; import { action } from './_generated/server'; import { normalizeBoxPassword } from './boxPassword'; import { decryptSecret, encryptSecret } from './secretCrypto'; import { assertWorkerToken } from './workerAuth'; /** Authed: store (or clear, with null/'') the caller's box password. */ export const setBoxPassword = action({ args: { password: v.union(v.string(), v.null()) }, handler: async (ctx, args): Promise<{ hasPassword: boolean }> => { const normalized = normalizeBoxPassword(args.password); if (!normalized.ok) throw new ConvexError(normalized.error); const { ownerId, username } = await ctx.runQuery( internal.boxSettings.resolveOwnerInternal, {}, ); await ctx.runMutation(internal.boxSettings.upsertMineInternal, { ownerId, username, boxPasswordEncrypted: normalized.value == null ? undefined : encryptSecret(normalized.value), }); return { hasPassword: normalized.value != null }; }, }); /** Worker-facing: the stored password (decrypted) for a box username. */ export const getBoxPasswordForWorker = action({ args: { workerToken: v.string(), username: v.string() }, handler: async (ctx, args): Promise<{ password: string | null }> => { assertWorkerToken(args.workerToken); const row = await ctx.runQuery(internal.boxSettings.getByUsernameInternal, { username: args.username, }); return { password: row?.boxPasswordEncrypted ? decryptSecret(row.boxPasswordEncrypted) : null, }; }, });