From dee6a19e517efa5e4bb388c274a4ada5abd648f2 Mon Sep 17 00:00:00 2001 From: Kai Ritthaler Date: Wed, 14 May 2025 18:53:25 +0200 Subject: [PATCH] cleaned up errors --- .../backend/src/controllers/userController.ts | 49 +++++++++++++------ .../src/middleware/authenticateToken.ts | 16 +++++- code/backend/src/schemas/userSchemas.ts | 4 +- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/code/backend/src/controllers/userController.ts b/code/backend/src/controllers/userController.ts index 92c6279..5813f21 100644 --- a/code/backend/src/controllers/userController.ts +++ b/code/backend/src/controllers/userController.ts @@ -11,6 +11,7 @@ const prisma = new PrismaClient(); // load environment variables from .env file dotenv.config(); const JWT_SECRET: string = process.env.TOKEN_SECRET!; // this secret is used to sign the JWT token + // Generate a JWT token with the username as payload and a secret from the environment variables which expires in 1800 seconds (30 minutes) function generateAccessToken(username: string, userId: string) { return jwt.sign( @@ -19,15 +20,11 @@ function generateAccessToken(username: string, userId: string) { { expiresIn: "1800s", issuer: "VogelApi" } ); //TODO: change role to user role } + // Endpoint to register a new user export const registerUser = async (req: Request, res: Response) => { const { username, password, email } = await req.body; //gets the data from the request body - if (!username || !password || !email) { - // check if username, password and email are provided and - res - .status(400) - .json({ message: "Username, password and email are required" }); - } + const existingUser = await prisma.user.findUnique({ // check if the user already exists where: { @@ -36,12 +33,18 @@ export const registerUser = async (req: Request, res: Response) => { }); if (existingUser) { // if the user already exists, return an error message - res.status(400).json({ message: `User "${username}" already exists` }); + res.status(400).json({ + error: "Invalid data", + details: [{ message: `User "${username}" already exists` }], + }); } const hashedPassword = await bcrypt.hash(password, 10); // hash the password with bcrypt if (!hashedPassword) { // check if the password was hashed successfully - res.status(500).json({ message: "Server Error" }); + res.status(500).json({ + error: "Invalid data", + details: [{ message: "Server Error" }], + }); } const userData = { // create a new user object with the data from the request body and the hashed password @@ -52,20 +55,28 @@ export const registerUser = async (req: Request, res: Response) => { const user = await prisma.user.create({ data: userData }); // create a new user in the database if (!user) { // check if the user was created successfully - res.status(500).json({ message: "Server Error" }); + res.status(500).json({ + error: "Server error", + details: [{ message: "Server Error while creating user" }], + }); } - res.json({ message: "User registered successfully" }); + const token: string = generateAccessToken(user.username, user.id); // generate a JWT token with the username and userId as payload + res.set("Authorization", `Bearer ${token}`); // set the token in the response header res.status(201).json({ message: "user created", data: { username: username, email: email }, }); // return the user object with the username and email }; + // Endpoint to login a user (unfinished) export const loginUser = async (req: Request, res: Response) => { const { username, password } = req.body; // get the data from the request body if (!username || !password) { // check if username and password are provided - res.status(400).json({ message: "Username and password are required" }); + res.status(400).json({ + error: "Invalid data", + details: [{ message: "Username and password are required" }], + }); } const user = await prisma.user.findUnique({ // check if the user exists @@ -81,17 +92,24 @@ export const loginUser = async (req: Request, res: Response) => { const isPasswordValid = await bcrypt.compare(password, user.password); // compare the password with the hashed password in the database if (!isPasswordValid) { // if the password is not valid, return an error message - res.status(401).json({ message: "Invalid password" }); + res.status(401).json({ + error: "invalid credentials", + details: [{ message: "Invalid password" }], + }); } const token: string = generateAccessToken(user.username, user.id); // generate a JWT token with the username and userId as payload res.set("Authorization", `Bearer ${token}`); // set the token in the response header res.json({ message: "User logged in successfully" }); }; + // Endpoint to get user data export const getUser = async (req: Request, res: Response) => { const username: string = req.query.username as string; if (!username) { - res.status(400).json({ message: "Username is required" }); + res.status(400).json({ + error: "no username", + details: [{ message: "Username is required" }], + }); } const user = await prisma.user.findUnique({ where: { @@ -99,7 +117,10 @@ export const getUser = async (req: Request, res: Response) => { }, }); if (!user) { - res.status(404).json({ message: `User "${username}" not found` }); + res.status(404).json({ + error: "user not found", + details: [{ message: `User "${username}" not found` }], + }); return; } res.json({ diff --git a/code/backend/src/middleware/authenticateToken.ts b/code/backend/src/middleware/authenticateToken.ts index 9e8b276..a0d6eee 100644 --- a/code/backend/src/middleware/authenticateToken.ts +++ b/code/backend/src/middleware/authenticateToken.ts @@ -36,8 +36,20 @@ export function authenticateToken() { if (err) { if (err instanceof TokenExpiredError) // check if the error is expired and return 401 - res.status(401).json({ message: "Token expired" }); - else res.status(403).json({ message: "Invalid token" }); + res + .status(401) + .json({ + error: "Token expired", + details: [{ message: "Token expired" }], + }); + // if the token is invalid, return 403 Forbidden + else + res + .status(403) + .json({ + error: "Invalid token", + details: [{ message: "Invalid token" }], + }); } next(); }); diff --git a/code/backend/src/schemas/userSchemas.ts b/code/backend/src/schemas/userSchemas.ts index bdae1da..cc58ccc 100644 --- a/code/backend/src/schemas/userSchemas.ts +++ b/code/backend/src/schemas/userSchemas.ts @@ -3,8 +3,8 @@ import { z } from "zod"; export const userRegistrationSchema = z.object({ username: z.string().regex(/^\S*$/, "Username must not contain spaces"), // No whitespaces allowed, - email: z.string().email(), - password: z.string().min(8), + email: z.string().email("Invalid email address"), + password: z.string().min(8, "Password must be at least 8 characters long"), }); export const userLoginSchema = z.object({