import { createHash } from "crypto"; import { sql } from "@/lib/db"; import { issueSession, toProfile } from "@/lib/users"; const hashCode = (email: string, code: string): string => createHash("sha256").update(`${email}:${code}`).digest("hex"); export async function POST(req: Request) { const { email, code } = await req.json(); if (!email?.trim() || !/^\d{6}$/.test(code ?? "")) { return Response.json( { error: "Email and a 6-digit code are required." }, { status: 400 }, ); } const normalized = email.trim().toLowerCase(); try { const rows = await sql<{ id: string; name: string; email: string; role: string | null; }>` UPDATE users SET email_verified = TRUE WHERE email = ${normalized} AND EXISTS ( SELECT 1 FROM email_verification_codes WHERE email = ${normalized} AND code_hash = ${hashCode(normalized, code)} AND expires_at > CURRENT_TIMESTAMP ) RETURNING id, name, email, role `; const user = rows[0]; if (!user) { await sql` UPDATE email_verification_codes SET attempts = attempts + 1 WHERE email = ${normalized} `; return Response.json( { error: "Invalid or expired verification code." }, { status: 400 }, ); } await sql`DELETE FROM email_verification_codes WHERE email = ${normalized}`; const session = issueSession(user); return Response.json({ data: { token: session.token, user: toProfile(user) }, }); } catch (error) { console.error("[VERIFY]: ", error); return Response.json({ error: "Internal Server Error" }, { status: 500 }); } }