import type { Handler } from 'hono'; import type { User } from 'types'; import { getUserById, updateUser } from 'officerdb'; import { verify as verifyJwt, sign } from '@@/jwt'; import argon2 from 'argon2'; import * as errors from '@@/custom-errors'; import { validatePassword } from './validate-password'; export const verifyHandler: Handler = async function (ctx) { const { verificationCode, name, username, password, confirmPassword } = ctx.get('body'); const userInfo = (await verifyJwt(verificationCode)) as User; if (!userInfo) throw errors.BAD_REQUEST(); const user = await getUserById(userInfo.id); if (!user) throw errors.NOT_FOUND('User not found'); const updates: Record = { status: 'Active' }; if (name) { if (typeof name !== 'string' || !name.trim() || name.length > 128) { throw errors.BAD_REQUEST('Name must be between 1 and 128 characters'); } updates.name = name.trim(); } if (username && typeof username === 'string' && username.trim()) { updates.username = username.trim(); } if (password) { validatePassword(password); if (password !== confirmPassword) { throw errors.BAD_REQUEST('Passwords do not match'); } updates.password = await argon2.hash(password); } await updateUser(userInfo.id, updates); // Re-fetch user to get final values after update const finalUser = await getUserById(userInfo.id); if (!finalUser) throw errors.NOT_FOUND('User not found'); // Issue a token so the user is logged in immediately const token = await sign({ id: finalUser.id, email: finalUser.email, name: finalUser.name, username: finalUser.username, role: finalUser.role, }); return ctx.json({ ok: true, token }); };