import { NextResponse } from "next/server" import { z } from "zod" import bcrypt from "bcryptjs" import { prisma } from "@/lib/prisma" import { rateLimit } from "@/lib/rate-limit" const registerSchema = z.object({ name: z .string() .min(1, "Name is required") .max(100, "Name must be 100 characters or less"), email: z .string() .min(1, "Email is required") .email("Invalid email address"), password: z .string() .min(10, "Password must be at least 10 characters") .max(128, "Password must be 128 characters or less") .regex(/[a-z]/, "Password must contain at least one lowercase letter") .regex(/[A-Z]/, "Password must contain at least one uppercase letter") .regex(/[0-9]/, "Password must contain at least one number"), }) export async function POST(request: Request) { try { // Rate limit: 5 registration attempts per IP per minute const forwarded = request.headers.get("x-forwarded-for") const ip = forwarded?.split(",")[0]?.trim() ?? "unknown" const rl = rateLimit(`register:${ip}`, 5, 60 * 1000) if (!rl.success) { return NextResponse.json( { error: "Too many registration attempts. Please try again later." }, { status: 429 } ) } const body = await request.json() const result = registerSchema.safeParse(body) if (!result.success) { const errors = result.error.flatten().fieldErrors return NextResponse.json( { error: "Validation failed", details: errors }, { status: 400 } ) } const { name, email, password } = result.data const existingUser = await prisma.user.findUnique({ where: { email } }) if (existingUser) { return NextResponse.json( { error: "An account with this email already exists" }, { status: 409 } ) } const hashedPassword = await bcrypt.hash(password, 10) const user = await prisma.user.create({ data: { name, email, password: hashedPassword, emailVerified: new Date(), }, }) return NextResponse.json( { id: user.id, name: user.name, email: user.email }, { status: 201 } ) } catch { return NextResponse.json( { error: "Something went wrong. Please try again." }, { status: 500 } ) } }