import type { Handler } from 'hono'; import { mkdir } from 'node:fs/promises'; import { join } from 'node:path'; import { getUserByEmail, getPasskeysByUserIdAndOrigin } from 'officerdb'; import { sign } from '@@/jwt'; import { getClaudeDir } from '@@/data-path'; import argon2 from 'argon2'; import * as errors from '@@/custom-errors'; import { isLockdown, triggerLockdown } from './distress'; const TEST_USERS: number[] = []; const { DISTRESS_PASSWORD } = process.env; export const signinHandler: Handler = async function (ctx) { const { email, password } = ctx.get('body'); // Duress: if lockdown is active, refuse everyone (looks like a normal failed login). If the distress // password was entered, trip the lockdown now and then fail the same way, giving nothing away. if (isLockdown()) throw errors.UNAUTHORIZED(); if (DISTRESS_PASSWORD && typeof password === 'string' && password === DISTRESS_PASSWORD) { triggerLockdown(); throw errors.UNAUTHORIZED(); } const origin = ctx.get('origin'); const dbUser = await getUserByEmail(email); if (!dbUser) throw errors.UNAUTHORIZED(); const passkeys = await getPasskeysByUserIdAndOrigin(dbUser.id, origin); if (!dbUser.password) throw errors.UNAUTHORIZED(); const { status } = dbUser; if (status !== 'Active') throw errors.UNAUTHORIZED(); const isValidPassword = TEST_USERS.includes(dbUser.id) || (await argon2.verify(dbUser.password, password)); if (!isValidPassword) throw errors.UNAUTHORIZED(); const { id, name, username, role } = dbUser; mkdir(join(getClaudeDir(email), 'archived'), { recursive: true }).catch(() => {}); const tokenUser = { id, email, name, username, role, passkeys: passkeys.length }; if (passkeys.length > 0 && !origin.startsWith('chrome-extension://') && !TEST_USERS.includes(dbUser.id)) { return ctx.json({ user: tokenUser }); } const token = await sign(tokenUser); if (origin.startsWith('chrome-extension://')) { // console.log('token', token); } return ctx.json({ token, user: tokenUser }); };