import { NextRequest, NextResponse } from 'next/server'; import { db } from '@/lib/db'; import { loginSchema, getClientIp } from '@/lib/validation'; import { verifyPassword, createSession, SESSION_COOKIE_NAME, } from '@/lib/auth'; import { authRateLimit } from '@/lib/rate-limit'; import { logActivity } from '@/lib/activity'; export async function POST(request: NextRequest) { try { // ── Rate Limit ──────────────────────────────────────────────────── const ip = getClientIp(request); const { allowed, retryAfterMs } = await authRateLimit(`auth:${ip}`); if (!allowed) { return NextResponse.json( { error: 'Too many login attempts. Please try again later.' }, { status: 429, headers: { 'Retry-After': String(Math.ceil(retryAfterMs / 1000)) }, } ); } // ── Parse & Validate Body ───────────────────────────────────────── const body = await request.json(); const parsed = loginSchema.safeParse(body); if (!parsed.success) { return NextResponse.json( { error: parsed.error.issues[0].message }, { status: 400 } ); } const { email, password } = parsed.data; // ── Find User ───────────────────────────────────────────────────── const user = await db.user.findUnique({ where: { email } }); if (!user) { return NextResponse.json( { error: 'Invalid email or password' }, { status: 401 } ); } // ── Verify Password ─────────────────────────────────────────────── const valid = await verifyPassword(password, user.password); if (!valid) { return NextResponse.json( { error: 'Invalid email or password' }, { status: 401 } ); } // ── Create Session ──────────────────────────────────────────────── const token = await createSession(user.id); // ── Set Cookie & Respond ────────────────────────────────────────── const response = NextResponse.json({ user: { id: user.id, email: user.email, name: user.name, plan: user.plan, createdAt: user.createdAt, }, }); response.cookies.set(SESSION_COOKIE_NAME, token, { httpOnly: true, secure: true, sameSite: 'lax', path: '/', maxAge: 7 * 24 * 60 * 60, // 7 days }); logActivity(user.id, 'login', 'Logged in', 'Signed in successfully'); return response; } catch (error) { console.error('[LOGIN_ERROR]', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }