Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Deuxième étape du login mot de passe : validation du code à 6 chiffres3// envoyé par courriel, puis ouverture de la session.4import { NextRequest, NextResponse } from "next/server";5import { consumeLoginCode, findUserById, touchLastLogin } from "@/lib/db";6import {7 mintSessionToken,8 SESSION_COOKIE,9 sessionCookieOptions,10} from "@/lib/auth";1112export async function POST(req: NextRequest) {13 let body: { email?: string; code?: string };14 try {15 body = await req.json();16 } catch {17 return NextResponse.json({ error: "Requête invalide." }, { status: 400 });18 }19 const email = (body.email ?? "").trim().toLowerCase();20 const code = (body.code ?? "").trim();21 if (!email || !/^\d{6}$/.test(code))22 return NextResponse.json(23 { error: "Entrez le code à 6 chiffres reçu par courriel." },24 { status: 400 },25 );2627 const result = consumeLoginCode(email, code);28 if (!result.ok || !result.userId) {29 const msg =30 result.reason === "tentatives"31 ? "Trop d'essais — reconnectez-vous pour recevoir un nouveau code."32 : result.reason === "expire"33 ? "Ce code a expiré — reconnectez-vous pour en recevoir un nouveau."34 : "Code incorrect — vérifiez le courriel reçu.";35 return NextResponse.json({ error: msg }, { status: 401 });36 }37 const user = findUserById(result.userId);38 if (!user)39 return NextResponse.json({ error: "Compte introuvable." }, { status: 401 });4041 touchLastLogin(user.id);42 const res = NextResponse.json({ ok: true });43 res.cookies.set(44 SESSION_COOKIE,45 await mintSessionToken(user.id),46 sessionCookieOptions,47 );48 return res;49}50