Spaces:
Running
Running
File size: 1,542 Bytes
6e13570 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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 };
|