const jwt = require('jsonwebtoken'); const config = require('../config/config'); const { User } = require('../models'); /** * Middleware to verify JWT token */ exports.verifyToken = async (req, res, next) => { try { // Get token from header const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ success: false, message: 'No token provided. Authorization header must be in format: Bearer ' }); } // Extract token const token = authHeader.substring(7); // Remove 'Bearer ' prefix // Verify token const decoded = jwt.verify(token, config.jwt.secret); // Attach user info to request req.user = decoded; next(); } catch (error) { if (error.name === 'TokenExpiredError') { return res.status(401).json({ success: false, message: 'Token expired. Please login again.' }); } else if (error.name === 'JsonWebTokenError') { return res.status(401).json({ success: false, message: 'Invalid token. Please login again.' }); } else { return res.status(500).json({ success: false, message: 'Error verifying token', error: error.message }); } } }; /** * Middleware to check if user is admin */ exports.isAdmin = async (req, res, next) => { try { // Verify token first (should be called after verifyToken) if (!req.user) { return res.status(401).json({ success: false, message: 'Authentication required' }); } // Check if user has admin role if (req.user.role !== 'admin') { return res.status(403).json({ success: false, message: 'Access denied. Admin privileges required.' }); } next(); } catch (error) { return res.status(500).json({ success: false, message: 'Error checking admin privileges', error: error.message }); } }; /** * Middleware to check if user owns the resource or is admin */ exports.isOwnerOrAdmin = async (req, res, next) => { try { // Verify token first (should be called after verifyToken) if (!req.user) { return res.status(401).json({ success: false, message: 'Authentication required' }); } const resourceUserId = req.params.userId || req.body.userId; // Allow if admin or if user owns the resource if (req.user.role === 'admin' || req.user.userId === resourceUserId) { next(); } else { return res.status(403).json({ success: false, message: 'Access denied. You can only access your own resources.' }); } } catch (error) { return res.status(500).json({ success: false, message: 'Error checking resource ownership', error: error.message }); } }; /** * Optional auth middleware - attaches user if token present, but doesn't fail if missing */ exports.optionalAuth = async (req, res, next) => { try { const authHeader = req.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.substring(7); try { const decoded = jwt.verify(token, config.jwt.secret); req.user = decoded; } catch (error) { // Token invalid or expired - continue as guest req.user = null; } } next(); } catch (error) { // Any error - continue as guest next(); } };