// eslint-disable-next-line @typescript-eslint/no-var-requires const bcrypt = require("bcryptjs"); import { createUser, getUserByEmail, getUserById, updateUser, updateUserPassword } from "./db"; export function requireAuth(req: any, res: any, next: any) { if (!(req.session as any)?.userId) { return res.status(401).json({ error: "Not authenticated" }); } next(); } export function registerAuthRoutes(app: any) { // POST /api/auth/register app.post("/api/auth/register", async (req: any, res: any) => { const { name, email, password } = req.body; if (!name || !email || !password || password.length < 6) { return res.status(400).json({ error: "Name, email, and password (min 6 chars) are required" }); } const existing = await getUserByEmail(email.toLowerCase()); if (existing) { return res.status(409).json({ error: "Email already in use" }); } const hash = await bcrypt.hash(password, 10); const user = await createUser({ name, email: email.toLowerCase(), passwordHash: hash }); (req.session as any).userId = user.id; res.status(201).json({ id: user.id, name: user.name, email: user.email }); }); // POST /api/auth/login app.post("/api/auth/login", async (req: any, res: any) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: "Email and password are required" }); } const user = await getUserByEmail(email.toLowerCase()); if (!user) { return res.status(401).json({ error: "Invalid email or password" }); } const valid = await bcrypt.compare(password, user.passwordHash); if (!valid) { return res.status(401).json({ error: "Invalid email or password" }); } (req.session as any).userId = user.id; res.json({ id: user.id, name: user.name, email: user.email }); }); // POST /api/auth/logout app.post("/api/auth/logout", (req: any, res: any) => { req.session.destroy(() => { res.json({ ok: true }); }); }); // GET /api/auth/me app.get("/api/auth/me", requireAuth, async (req: any, res: any) => { const user = await getUserById((req.session as any).userId); if (!user) { req.session.destroy(); return res.status(401).json({ error: "Not authenticated" }); } res.json({ id: user.id, name: user.name, email: user.email }); }); // PUT /api/auth/profile app.put("/api/auth/profile", requireAuth, async (req: any, res: any) => { const { name, email } = req.body; const updates: any = {}; if (name) updates.name = name; if (email) { const existing = await getUserByEmail(email.toLowerCase()); if (existing && existing.id !== (req.session as any).userId) { return res.status(409).json({ error: "Email already in use" }); } updates.email = email.toLowerCase(); } const user = await updateUser((req.session as any).userId, updates); res.json({ id: user.id, name: user.name, email: user.email }); }); // PUT /api/auth/password app.put("/api/auth/password", requireAuth, async (req: any, res: any) => { const { currentPassword, newPassword } = req.body; if (!currentPassword || !newPassword || newPassword.length < 6) { return res.status(400).json({ error: "Current password and new password (min 6 chars) required" }); } const user = await getUserById((req.session as any).userId); if (!user) return res.status(401).json({ error: "Not authenticated" }); const valid = await bcrypt.compare(currentPassword, user.passwordHash); if (!valid) return res.status(401).json({ error: "Current password is incorrect" }); const hash = await bcrypt.hash(newPassword, 10); await updateUserPassword(user.id, hash); res.json({ ok: true }); }); // POST /api/auth/request-reset (stub) app.post("/api/auth/request-reset", async (req: any, res: any) => { const { email } = req.body; if (!email) return res.status(400).json({ error: "Email is required" }); res.json({ ok: true, message: "If an account exists, a reset link would be sent" }); }); }