diff --git a/src/app/api/signup/route.ts b/src/app/api/signup/route.ts index e0f6ad9..65ce3fd 100644 --- a/src/app/api/signup/route.ts +++ b/src/app/api/signup/route.ts @@ -1,14 +1,11 @@ import bcryptjs from "bcryptjs"; +import { validatePassword } from "@utils/validation"; import { SignJWT } from "jose"; import { NextResponse } from "next/server"; import { env } from "@utils/env"; import { prisma } from "@utils/prisma"; -import { passwordStrengthCheck } from "@utils/validation"; - -// todo check email doesn't already exist - export async function POST(req: Request) { try { const { email, password, name } = await req.json(); @@ -23,80 +20,67 @@ export async function POST(req: Request) { return NextResponse.json({ message: "Sorry, this email is already in use" }, { status: 409 }); } - const passwordCheckResult = await passwordStrengthCheck(password); + const passwordCheckResult = validatePassword(password); + if ("message" in passwordCheckResult) { + return NextResponse.json({ message: passwordCheckResult.message }, { status: passwordCheckResult.status }); + } - 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), - }, - }); + 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, - }, - }); + // 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 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 { 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 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 }); - } + 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); diff --git a/src/app/api/update-user/route.ts b/src/app/api/update-user/route.ts index 46b4059..51b11fd 100644 --- a/src/app/api/update-user/route.ts +++ b/src/app/api/update-user/route.ts @@ -5,7 +5,7 @@ import { env } from "@utils/env"; import { prisma } from "@utils/prisma"; import { apiAuthMiddleware } from "@utils/apiAuthMiddleware"; -import { passwordStrengthCheck } from "@utils/validation"; +import { validatePassword } from "@utils/validation"; export async function POST(req: Request) { try { @@ -34,25 +34,12 @@ export async function POST(req: Request) { } } - // todo move to dedicated function // Validate password strength if provided let passwordHash = user.passwordHash; if (password) { - const passwordCheckResult = await passwordStrengthCheck(password); - if (passwordCheckResult === "short") { - return NextResponse.json({ message: "Password is shorter than 8 characters" }, { status: 400 }); - } else if (passwordCheckResult === "long") { - return NextResponse.json({ message: "Password is longer than 16 characters" }, { status: 400 }); - } else if (passwordCheckResult === "no lower") { - return NextResponse.json({ message: "Password must contain lowercase letters" }, { status: 400 }); - } else if (passwordCheckResult === "no upper") { - return NextResponse.json({ message: "Password must contain uppercase letters" }, { status: 400 }); - } else if (passwordCheckResult === "no digit") { - return NextResponse.json({ message: "Password must contain a number" }, { status: 400 }); - } else if (passwordCheckResult === "no special") { - return NextResponse.json({ message: "Password must contain a special character (!@#$%^&*)" }, { status: 400 }); - } else if (passwordCheckResult === "end of function") { - return NextResponse.json({ message: "Password check script failure" }, { status: 500 }); + const passwordCheckResult = validatePassword(password); + if ("message" in passwordCheckResult) { + return NextResponse.json({ message: passwordCheckResult.message }, { status: passwordCheckResult.status }); } passwordHash = await bcryptjs.hash(password, 10); } diff --git a/src/utils/validation.ts b/src/utils/validation.ts index 4c8c9aa..7745127 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -1,4 +1,4 @@ -export async function passwordStrengthCheck(password: string): Promise { +export function passwordStrengthCheck(password: string): string { if (password.length < 8) { return "short"; } else if (password.length > 16) { @@ -21,3 +21,24 @@ export async function passwordStrengthCheck(password: string): Promise { } return "end of function"; } + +export function validatePassword(password: string) { + const result = passwordStrengthCheck(password); + + switch (result) { + case "short": + return { message: "Password is shorter than 8 characters", status: 400 }; + case "long": + return { message: "Password is longer than 16 characters", status: 400 }; + case "no lower": + return { message: "Password must contain lowercase letters", status: 400 }; + case "no upper": + return { message: "Password must contain uppercase letters", status: 400 }; + case "no digit": + return { message: "Password must contain a number", status: 400 }; + case "no special": + return { message: "Password must contain a special character (!@#$%^&*)", status: 400 }; + default: + return {}; + } +}