Update auth, users, settings page, and prisma schema

This commit is contained in:
2026-02-24 00:24:15 -05:00
parent 27e6e6a4a0
commit 6e31681438
9 changed files with 324 additions and 43 deletions

View File

@@ -44,14 +44,16 @@ router.post(
const hashedPassword = await hashPassword(req.body.password);
const user = await storage.createUser({
...req.body,
username: req.body.username,
password: hashedPassword,
role: "USER",
});
// Generate a JWT token for the user after successful registration
const token = generateToken(user);
const { password, ...safeUser } = user;
const { password, ...rest } = user;
const safeUser = { ...rest, role: rest.role ?? "USER" };
return res.status(201).json({ user: safeUser, token });
} catch (error) {
console.error("Registration error:", error);
@@ -77,12 +79,13 @@ router.post(
);
if (!isPasswordMatch) {
return res.status(401).json({ error: "Invalid password or password" });
return res.status(401).json({ error: "Invalid username or password" });
}
// Generate a JWT token for the user after successful login
const token = generateToken(user);
const { password, ...safeUser } = user;
const { password, ...rest } = user;
const safeUser = { ...rest, role: rest.role ?? "USER" };
return res.status(200).json({ user: safeUser, token });
} catch (error) {
return res.status(500).json({ error: "Internal server error" });

View File

@@ -3,8 +3,7 @@ import type { Request, Response } from "express";
import { storage } from "../storage";
import { z } from "zod";
import { UserUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas";
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import bcrypt from "bcrypt";
const router = Router();
@@ -25,15 +24,33 @@ router.get("/", async (req: Request, res: Response): Promise<any> => {
const user = await storage.getUser(userId);
if (!user) return res.status(404).send("User not found");
const { password, ...safeUser } = user;
res.json(safeUser);
const { password, ...rest } = user;
res.json({ ...rest, role: rest.role ?? "USER" });
} catch (error) {
console.error(error);
res.status(500).send("Failed to fetch user");
}
});
// GET: List all users (for admin/settings; no passwords)
router.get("/list", async (req: Request, res: Response): Promise<any> => {
try {
if (!req.user?.id) return res.status(401).send("Unauthorized");
const limit = Math.min(Number(req.query.limit) || 100, 500);
const offset = Number(req.query.offset) || 0;
const users = await storage.getUsers(limit, offset);
const safe = users.map((u) => {
const { password: _p, ...rest } = u;
return { ...rest, role: rest.role ?? "USER" };
});
res.json(safe);
} catch (error) {
console.error(error);
res.status(500).send("Failed to fetch users");
}
});
// GET: User by ID
router.get("/:id", async (req: Request, res: Response): Promise<any> => {
try {
@@ -46,32 +63,36 @@ router.get("/:id", async (req: Request, res: Response): Promise<any> => {
const user = await storage.getUser(id);
if (!user) return res.status(404).send("User not found");
const { password, ...safeUser } = user;
res.json(safeUser);
const { password, ...rest } = user;
res.json({ ...rest, role: rest.role ?? "USER" });
} catch (error) {
console.error(error);
res.status(500).send("Failed to fetch user");
}
});
// POST: Create new user
// POST: Create new user (password is hashed)
router.post("/", async (req: Request, res: Response) => {
try {
const input = userCreateSchema.parse(req.body);
const newUser = await storage.createUser(input);
const { password, ...safeUser } = newUser;
res.status(201).json(safeUser);
const existing = await storage.getUserByUsername(input.username);
if (existing) {
return res.status(400).json({ error: "Username already exists" });
}
const hashed = await hashPassword(input.password);
const newUser = await storage.createUser({ ...input, password: hashed });
const { password: _p, ...rest } = newUser;
res.status(201).json({ ...rest, role: rest.role ?? "USER" });
} catch (err) {
console.error(err);
res.status(400).json({ error: "Invalid user data", details: err });
}
});
// Function to hash password using bcrypt
// Hash password using bcrypt (used for create and update)
async function hashPassword(password: string) {
const saltRounds = 10; // Salt rounds for bcrypt
const hashedPassword = await bcrypt.hash(password, saltRounds);
return hashedPassword;
const saltRounds = 10;
return bcrypt.hash(password, saltRounds);
}
// PUT: Update user
@@ -97,16 +118,16 @@ router.put("/:id", async (req: Request, res: Response):Promise<any> => {
const updatedUser = await storage.updateUser(id, updates);
if (!updatedUser) return res.status(404).send("User not found");
const { password, ...safeUser } = updatedUser;
res.json(safeUser);
const { password, ...rest } = updatedUser;
res.json({ ...rest, role: rest.role ?? "USER" });
} catch (err) {
console.error(err);
res.status(400).json({ error: "Invalid update data", details: err });
}
});
// DELETE: Delete user
router.delete("/:id", async (req: Request, res: Response):Promise<any> => {
// DELETE: Delete user (cannot delete current user)
router.delete("/:id", async (req: Request, res: Response): Promise<any> => {
try {
const idParam = req.params.id;
if (!idParam) return res.status(400).send("User ID is required");
@@ -114,6 +135,10 @@ router.delete("/:id", async (req: Request, res: Response):Promise<any> => {
const id = parseInt(idParam);
if (isNaN(id)) return res.status(400).send("Invalid user ID");
if (req.user?.id === id) {
return res.status(403).json({ error: "Cannot delete your own account" });
}
const success = await storage.deleteUser(id);
if (!success) return res.status(404).send("User not found");