const { verifyToken } = require("../utils/jwt.util"); const { getEffectivePermissions } = require("../services/permission.service"); const db = require("../models"); const authenticate = async (req, res, next) => { try { const token = req.cookies?.access_token || (req.headers.authorization?.startsWith("Bearer ") ? req.headers.authorization.slice(7) : null); if (!token) return res.status(401).json({ success: false, error: { code: "UNAUTHORIZED", message: "Authentication required" } }); const decoded = verifyToken(token); if (!decoded.sub || !decoded.sid || !Number.isInteger(decoded.tokenVersion)) throw new Error("Required claims missing"); const [user, session] = await Promise.all([ db.User.findByPk(decoded.sub), db.AuthSession.findByPk(decoded.sid), ]); if (!user || user.accountStatus !== "ACTIVE" || user.tokenVersion !== decoded.tokenVersion || !session || session.user_id !== user.id || session.revoked_at || session.expires_at <= new Date() || session.token_version !== user.tokenVersion) { return res.status(401).json({ success: false, error: { code: "SESSION_INVALID", message: "Session is no longer valid" } }); } req.user = { id: user.id, sessionId: session.id, firstName: user.firstName, lastName: user.lastName, email: user.email, accountType: user.accountType, accountStatus: user.accountStatus, permissions: await getEffectivePermissions(user.id) }; next(); } catch (error) { res.clearCookie("access_token"); return res.status(401).json({ success: false, error: { code: "UNAUTHORIZED", message: "Invalid or expired access token" } }); } }; module.exports = { authenticate, requireAuth: authenticate };