import bcryptjs from "bcryptjs"; import { SignJWT } from "jose"; import { NextResponse } from "next/server"; import { env } from "@utils/env"; import { prisma } from "@utils/prisma"; import { passwordStrengthCheck } from "@utils/validation"; export async function POST(req: Request) { try { const { email, password, name } = await req.json(); const foundUser = await prisma.user.findUnique({ where: { email: email, }, }); if (foundUser) { return NextResponse.json({ message: "Sorry, this email is already in use" }, { status: 409 }); } const passwordCheckResult = await passwordStrengthCheck(password); if (passwordCheckResult === "short") { return NextResponse.json({ message: "Your password is shorter than 8 characters" }, { status: 400 }); } else if (passwordCheckResult === "long") { return NextResponse.json({ message: "Your password is longer than 16 characters" }, { status: 400 }); } else if (passwordCheckResult === "no lower") { return NextResponse.json({ message: "Your password must contain a lowercase letters" }, { status: 400 }); } else if (passwordCheckResult === "no upper") { return NextResponse.json({ message: "Your password must contain a uppercase letters" }, { status: 400 }); } else if (passwordCheckResult === "no digit") { return NextResponse.json({ message: "Your password must contain a number" }, { status: 400 }); } else if (passwordCheckResult === "no special") { return NextResponse.json({ message: "Your password must contain a special character (!@#$%^&*)" }, { status: 400 }); } else if (passwordCheckResult === "end of function") { return NextResponse.json({ message: "Password check script failure" }, { status: 500 }); } else { try { const newUser = await prisma.user.create({ data: { name, email, passwordHash: await bcryptjs.hash(password, 10), }, }); // Link orders with matching email to the new user await prisma.order.updateMany({ where: { email: email, userId: null, // Only update orders not already linked to a user }, data: { userId: newUser.id, }, }); const user = await prisma.user.findUnique({ where: { id: newUser.id }, include: { earthquakes: true, observatories: true, artefacts: true, purchasedOrders: true, requests: true, scientist: { include: { superior: true, subordinates: true, }, }, }, }); const { passwordHash, ...userSansHash } = user!; const secret = new TextEncoder().encode(env.JWT_SECRET_KEY); const token = await new SignJWT({ userId: user!.id }) .setProtectedHeader({ alg: "HS256" }) .setExpirationTime("2w") .sign(secret); const response = NextResponse.json({ message: "Account Created", user: userSansHash }, { status: 201 }); response.cookies.set("jwt", token, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "strict", maxAge: 3600 * 168 * 2, // 2 weeks path: "/", }); return response; } catch (error) { console.error("Error creating user:", error); return NextResponse.json({ message: "Internal Server Error" }, { status: 500 }); } } } catch (error) { console.error("Error in signup endpoint:", error); return NextResponse.json({ message: "Internal Server Error" }, { status: 500 }); } }