import { NextRequest, NextResponse } from 'next/server'; import { db } from '@/lib/db'; import { signupSchema, getClientIp } from '@/lib/validation'; import { hashPassword, createSession, generateApiKey, 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 signup 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 = signupSchema.safeParse(body); if (!parsed.success) { return NextResponse.json( { error: parsed.error.issues[0].message }, { status: 400 } ); } const { name, email, password } = parsed.data; // ── Check if Email Exists ───────────────────────────────────────── const existing = await db.user.findUnique({ where: { email } }); if (existing) { return NextResponse.json( { error: 'An account with this email already exists' }, { status: 409 } ); } // ── Hash Password & Generate API Key ────────────────────────────── const [hashedPassword, apiKey] = await Promise.all([ hashPassword(password), generateApiKey(), ]); // ── Create User ─────────────────────────────────────────────────── const user = await db.user.create({ data: { name, email, password: hashedPassword, apiKey, plan: 'free', }, }); // ── Create Session ──────────────────────────────────────────────── const token = await createSession(user.id); // ── Determine if behind HTTPS proxy ─────────────────────────────── const forwardedProto = request.headers.get('x-forwarded-proto'); const isSecure = forwardedProto === 'https' || process.env.NODE_ENV === 'production'; // ── 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: isSecure, sameSite: 'lax', path: '/', maxAge: 7 * 24 * 60 * 60, // 7 days }); logActivity(user.id, 'signup', 'Account created', user.email); return response; } catch (error) { console.error('[SIGNUP_ERROR]', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }