Files
spoon/packages/backend/convex/boxSettingsNode.ts
T

46 lines
1.6 KiB
TypeScript

'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,
};
},
});