// backend/middleware/auth.ts import logger from '../utils/logger'; import { Request, Response, NextFunction } from 'express'; import jwt, { JwtPayload } from 'jsonwebtoken'; import { Pool } from 'mysql2/promise'; // Extend Request to include a user property declare module 'express-serve-static-core' { interface Request { user?: { id: number; username: string; role: string } | null; } } export const authMiddleware = (pool: Pool) => async (req: Request, res: Response, next: NextFunction) => { try { logger.info("Auth middleware triggered"); const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { logger.warn("Authorization header missing or invalid:", { authHeader }); return res.status(401).json({ message: 'Authorization header missing or invalid' }); } const token = authHeader.split(' ')[1]; const jwtSecret = process.env.JWT_SECRET; if (!jwtSecret) { throw new Error("JWT_SECRET is not set in environment variables"); } let decoded: JwtPayload; try { decoded = jwt.verify(token, jwtSecret) as JwtPayload; } catch (error: unknown) { logger.error("JWT verification failed:", error); if (error instanceof jwt.TokenExpiredError) { return res.status(401).json({ message: 'Access token expired', code: 'TOKEN_EXPIRED', }); } return res.status(401).json({ message: 'Invalid token', code: 'INVALID_TOKEN' }); } const userId = decoded.userId; if (!userId || typeof userId !== 'number') { logger.warn("Invalid or missing userId in token payload:", { decoded }); return res.status(401).json({ message: 'Invalid token payload' }); } try { const [rows] = await pool.execute( 'SELECT id, username, role FROM users WHERE id = ? AND status = "active"', [userId] ); const users = Array.isArray(rows) ? rows : []; if (users.length === 0) { logger.warn("User not found or inactive:", { userId }); return res.status(401).json({ message: 'User not found or inactive' }); } req.user = users[0] as { id: number; username: string; role: string }; next(); } catch (dbError) { logger.error("Database query failed:", dbError); return res.status(500).json({ message: 'Database query error' }); } } catch (error: unknown) { logger.error('Error in authMiddleware:', error); res.status(500).json({ message: 'Internal server error' }); } };