const { verifyAccessToken } = require("../utils/jwt"); const User = require("../models/User"); /** * Requires a valid, non-expired access token in the Authorization header. * Attaches the full (fresh) user document to req.user so downstream * handlers always see current role/lock/tokenVersion state rather than * trusting stale claims baked into the JWT. */ async function requireAuth(req, res, next) { try { const header = req.headers.authorization || ""; const [scheme, token] = header.split(" "); if (scheme !== "Bearer" || !token) { return res.status(401).json({ error: "Authentication required." }); } const payload = verifyAccessToken(token); const user = await User.findById(payload.sub); if (!user || !user.isActive) { return res.status(401).json({ error: "Account not found or disabled." }); } if (user.tokenVersion !== payload.tokenVersion) { // Token was issued before a password change / forced logout. return res.status(401).json({ error: "Session expired, please log in again." }); } req.user = user; next(); } catch (err) { return res.status(401).json({ error: "Invalid or expired token." }); } } function requireRole(...roles) { return (req, res, next) => { if (!req.user || !roles.includes(req.user.role)) { return res.status(403).json({ error: "You do not have permission to perform this action." }); } next(); }; } module.exports = { requireAuth, requireRole };