Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Connexion sans mot de passe : envoi d'un lien magique (jeton usage unique,3// 15 minutes) par courriel. Réponse identique que le compte existe ou non,4// pour ne pas permettre l'énumération des adresses.5import crypto from "crypto";6import { NextRequest, NextResponse } from "next/server";7import { findUserByEmail, createAuthToken } from "@/lib/db";8import { BASE_URL, safeNext } from "@/lib/auth";9import { sendEmail, magicLinkEmail } from "@/lib/email";1011const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;1213export async function POST(req: NextRequest) {14 let body: { email?: string; next?: string };15 try {16 body = await req.json();17 } catch {18 return NextResponse.json({ error: "Requête invalide." }, { status: 400 });19 }20 const email = (body.email ?? "").trim().toLowerCase();21 if (!EMAIL_RE.test(email))22 return NextResponse.json(23 { error: "Entrez d'abord votre adresse courriel." },24 { status: 400 },25 );2627 const user = findUserByEmail(email);28 if (user) {29 const raw = crypto.randomBytes(32).toString("hex");30 createAuthToken({31 email,32 userId: user.id,33 purpose: "magic-link",34 raw,35 ttlMinutes: 15,36 payload: { next: safeNext(body.next) },37 });38 try {39 await sendEmail({40 to: email,41 ...magicLinkEmail(user.name, `${BASE_URL}/api/auth/magic/verify?token=${raw}`),42 });43 } catch (err) {44 console.error("magic: envoi Resend échoué", err);45 return NextResponse.json(46 { error: "Impossible d'envoyer le courriel — réessayez dans un instant." },47 { status: 502 },48 );49 }50 }51 return NextResponse.json({ ok: true, sent: true, email });52}53