export const runtime = "nodejs"; import { NextResponse } from "next/server"; import { eq } from "drizzle-orm"; import { requireSession } from "@/lib/auth/require"; import { db } from "@/lib/db/client"; import { users } from "@/lib/db/schema"; import { generateTotpSecret, encryptTotpSecret, buildTotpQrCode } from "@/lib/auth/totp"; /** * Starts (or restarts) 2FA setup — generates a fresh secret and stores it * encrypted, but leaves totpEnabled false until /confirm proves the user * actually scanned it (see users.totpEnabled comment in schema.ts). Safe to * call again if the user abandons setup partway — it just overwrites the * unconfirmed secret with a new one. */ export async function POST() { const { session, response } = await requireSession(); if (!session) return response; const user = await db.query.users.findFirst({ where: eq(users.id, session.user.id) }); if (!user) return NextResponse.json({ error: "User not found" }, { status: 404 }); const secret = generateTotpSecret(); await db.update(users).set({ totpSecret: encryptTotpSecret(secret), totpEnabled: false }).where(eq(users.id, user.id)); const qrDataUrl = await buildTotpQrCode(secret, user.email); return NextResponse.json({ secret, qrDataUrl }); }