import { createHash, randomInt } from "crypto"; import { sql } from "@/lib/db"; import { hashPassword } from "@/lib/password"; import { sendEmail } from "@/lib/mailer"; const normalizePhone = (raw: string): string => { const cleaned = raw.replace(/[^\d+]/g, ""); if (cleaned.startsWith("+")) return cleaned; return `+961${cleaned.replace(/^0+/, "")}`; }; const hashCode = (email: string, code: string): string => createHash("sha256").update(`${email}:${code}`).digest("hex"); export async function POST(req: Request) { const { name, email, phone, password } = await req.json(); if (!name?.trim() || !email?.trim() || !password) { return Response.json( { error: "Name, email and password are required." }, { status: 400 }, ); } if (typeof password !== "string" || password.length < 8) { return Response.json( { error: "Password must be at least 8 characters." }, { status: 400 }, ); } try { const existing = await sql<{ id: string; email_verified: boolean }>` SELECT id, email_verified FROM users WHERE email = ${email.trim().toLowerCase()} `; if (existing[0]?.email_verified) { return Response.json( { error: "An account with this email already exists. Please sign in." }, { status: 409 }, ); } // Unverified rows may be re-registered (e.g. the first mail never arrived). await sql` INSERT INTO users (name, email, phone, password_hash, email_verified) VALUES ( ${name.trim()}, ${email.trim().toLowerCase()}, ${phone ? normalizePhone(phone) : null}, ${hashPassword(password)}, FALSE ) ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name, phone = COALESCE(EXCLUDED.phone, users.phone), password_hash = EXCLUDED.password_hash `; const code = String(randomInt(0, 1_000_000)).padStart(6, "0"); await sql` INSERT INTO email_verification_codes (email, code_hash, expires_at) VALUES ( ${email.trim().toLowerCase()}, ${hashCode(email.trim().toLowerCase(), code)}, CURRENT_TIMESTAMP + INTERVAL '15 minutes' ) ON CONFLICT (email) DO UPDATE SET code_hash = EXCLUDED.code_hash, expires_at = EXCLUDED.expires_at, attempts = 0 `; await sendEmail( email.trim().toLowerCase(), "Your Waseel verification code", `Welcome to Waseel!\n\nYour verification code is: ${code}\n\nIt expires in 15 minutes.`, ); return Response.json({ data: { sent: true } }, { status: 201 }); } catch (error) { console.error("[REGISTER]: ", error); return Response.json({ error: "Internal Server Error" }, { status: 500 }); } }