Files
cve-dashboard/backend/middleware/auth.js

105 lines
3.3 KiB
JavaScript
Raw Normal View History

// Authentication Middleware
const pool = require('../db');
const { teamToIvanti } = require('../helpers/teams');
// Require authenticated user — no parameters needed, pool is imported directly
function requireAuth() {
return async (req, res, next) => {
const sessionId = req.cookies?.session_id;
if (!sessionId) {
return res.status(401).json({ error: 'Authentication required' });
}
try {
const { rows } = await pool.query(
`SELECT s.*, u.id as user_id, u.username, u.email, u.role, u.user_group, u.bu_teams, u.is_active
FROM sessions s
JOIN users u ON s.user_id = u.id
WHERE s.session_id = $1 AND s.expires_at > NOW()`,
[sessionId]
);
const session = rows[0];
if (!session) {
return res.status(401).json({ error: 'Session expired or invalid' });
}
if (!session.is_active) {
return res.status(401).json({ error: 'Account is disabled' });
}
// Attach user to request
req.user = {
id: session.user_id,
username: session.username,
email: session.email,
role: session.role,
group: session.user_group,
teams: session.bu_teams ? session.bu_teams.split(',').filter(Boolean) : []
};
next();
} catch (err) {
console.error('Auth middleware error:', err);
return res.status(500).json({ error: 'Authentication error' });
}
};
}
// Require specific group(s)
function requireGroup(...allowedGroups) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}
if (!allowedGroups.includes(req.user.group)) {
return res.status(403).json({
error: 'Insufficient permissions',
required: allowedGroups,
current: req.user.group
});
}
next();
};
}
// Require team assignment — enforces team-scoped data access.
// Admin group bypasses (req.teamScope = null means "no filter").
// Non-admin users without teams get 403.
// Non-admin users with teams get req.teamScope = { short: [...], ivanti: [...] }.
function requireTeam() {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}
// Admin bypass — full access to all teams
if (req.user.group === 'Admin') {
req.teamScope = null;
return next();
}
// No teams assigned — block access
if (!req.user.teams || req.user.teams.length === 0) {
return res.status(403).json({
error: 'No team assignment. Contact an administrator to assign BU teams to your account.',
code: 'NO_TEAM_ASSIGNMENT'
});
}
// Build scope with both naming conventions
req.teamScope = {
short: req.user.teams,
ivanti: req.user.teams.map(t => teamToIvanti(t))
};
next();
};
}
module.exports = { requireAuth, requireGroup, requireTeam };