SPB Git forge

spb/toveli

Public
14commits 1branches 0releases
1.1 MBsize
maindefault branch
5 h agolast push
TypeScript 50.6% JavaScript 46.1% SQL 2.1% Shell 0.6% CSS 0.5%
1.8 KB · 25 lines typescript
Raw Blame History
1import { NextRequest, NextResponse } from "next/server";2import { z } from "zod";3import { cookies } from "next/headers";4import { verifyCode } from "@/lib/auth/otp";5import { assertSameOrigin, clientIp, createSession, cookieOptions, COOKIE, userAgent } from "@/lib/auth/session";6import { handle, parseBody } from "@/lib/api";7import { hit } from "@/lib/auth/ratelimit";8import { ipHash } from "@/lib/auth/crypto";9export const dynamic = "force-dynamic";10const Body = z.object({ challengeId: z.string().uuid(), code: z.string().regex(/^\d{6}$/), acceptTerms: z.boolean().optional().default(false) });11const MSG: Record<string, string> = { invalid: "Code invalide.", expired: "Ce code a expiré. Demandez-en un nouveau.", too_many_attempts: "Trop d'essais. Demandez un nouveau code.", not_found: "Demande introuvable. Recommencez.", terms_required: "Nouveau compte : acceptez les conditions puis confirmez le code." };12export async function POST(req: NextRequest) {13  try {14    await assertSameOrigin();15    const { challengeId, code, acceptTerms } = await parseBody(req, Body);16    const ip = await clientIp();17    const rl = await hit(`otp:verify:${ipHash(ip)}`, 30, 600); if (!rl.ok) return NextResponse.json({ error: { code: "rate_limited", message: "Trop de tentatives. Réessayez plus tard." } }, { status: 429 });18    const r = await verifyCode(challengeId, code, ip, acceptTerms);19    if (!r.ok) return NextResponse.json({ error: { code: r.reason, message: MSG[r.reason] } }, { status: r.reason === "terms_required" ? 409 : 400 });20    const s = await createSession(r.userId, { ip, device: await userAgent() });21    (await cookies()).set(COOKIE, s.token, cookieOptions(s.expiresAt));22    return NextResponse.json({ ok: true, created: r.created, user: { id: r.userId, email: r.email } });23  } catch (e) { return handle(e); }24}25