/** * This is a user authentication API route demo. * Handle user registration, login, token management, etc. */ import { Router, type Request, type Response } from 'express' import bcrypt from 'bcryptjs' import { z } from 'zod' import { signToken, toPublicUser } from '../auth.js' import { createUser, findUserByUsername } from '../db.js' import { requireAuth } from '../middleware/requireAuth.js' import type { AuthedRequest } from '../middleware/requireAuth.js' import type { Role } from '../../shared/types.js' const router = Router() /** * User Login * POST /api/auth/register */ const registerSchema = z.object({ username: z.string().min(3).max(32), password: z.string().min(6).max(64), email: z.string().email().optional(), }) router.post('/register', async (req: Request, res: Response): Promise => { const parsed = registerSchema.safeParse(req.body) if (!parsed.success) { res.status(400).json({ success: false, error: 'BAD_REQUEST' }) return } const existed = await findUserByUsername(parsed.data.username) if (existed) { res.status(409).json({ success: false, error: 'USERNAME_TAKEN' }) return } const user = await createUser({ username: parsed.data.username, password: parsed.data.password, role: 'sales', email: parsed.data.email, }) const token = signToken(user) res.json({ success: true, data: { token, user } }) }) /** * User Login * POST /api/auth/login */ const loginSchema = z.object({ username: z.string().min(1), password: z.string().min(1), }) router.post('/login', async (req: Request, res: Response): Promise => { const parsed = loginSchema.safeParse(req.body) if (!parsed.success) { res.status(400).json({ success: false, error: 'BAD_REQUEST' }) return } const user = await findUserByUsername(parsed.data.username) if (!user || user.status !== 'active') { res.status(401).json({ success: false, error: 'INVALID_CREDENTIALS' }) return } const ok = await bcrypt.compare(parsed.data.password, user.passwordHash) if (!ok) { res.status(401).json({ success: false, error: 'INVALID_CREDENTIALS' }) return } const pub = toPublicUser(user) const token = signToken(pub) res.json({ success: true, data: { token, user: pub } }) }) /** * User Logout * POST /api/auth/logout */ router.post('/logout', async (_req: Request, res: Response): Promise => { res.json({ success: true }) }) router.get('/me', requireAuth, async (req: Request, res: Response): Promise => { const user = (req as AuthedRequest).user res.json({ success: true, data: user }) }) export default router