import { NextResponse, type NextRequest } from "next/server"; import { z } from "zod"; import { prisma } from "@/lib/prisma"; import { verifyPassword } from "@/lib/password"; import { createSession } from "@/lib/session"; import { audit } from "@/lib/audit"; import { clientIp, userAgent } from "@/lib/request"; const Body = z.object({ email: z.string().email(), password: z.string().min(1), }); export async function POST(req: NextRequest) { const parsed = Body.safeParse(await req.json().catch(() => ({}))); if (!parsed.success) { return NextResponse.json({ error: "Invalid email or password" }, { status: 400 }); } const { email, password } = parsed.data; const user = await prisma.user.findUnique({ where: { email } }); const ip = clientIp(req); const ua = userAgent(req); if (!user || user.role !== "admin" || !user.active || !user.passwordHash) { await audit({ action: "login_failed", entity: "User", entityId: user?.id, ipAddress: ip }); return NextResponse.json({ error: "Invalid email or password" }, { status: 401 }); } const ok = await verifyPassword(password, user.passwordHash); if (!ok) { await audit({ action: "login_failed", entity: "User", entityId: user.id, ipAddress: ip }); return NextResponse.json({ error: "Invalid email or password" }, { status: 401 }); } await createSession({ userId: user.id, role: "admin", userAgent: ua, ipAddress: ip, }); await prisma.user.update({ where: { id: user.id }, data: { lastLoginAt: new Date(), failedAttempts: 0, lockedUntil: null }, }); await audit({ actorId: user.id, action: "login", entity: "User", entityId: user.id, ipAddress: ip }); return NextResponse.json({ ok: true, redirect: "/admin" }); }