Files
cve-dashboard/backend/middleware/auth.js
Jordan Ramos 2656df94d3 feat: add multi-BU tenancy with per-user team scoping (Option B)
- Add bu_teams column to users table (migration + fresh schema)
- Create shared KNOWN_TEAMS constant and validateTeams helper
- Expose user teams in auth middleware, login, and /me responses
- Add bu_teams CRUD to user management routes with audit logging
- Make Ivanti FINDINGS_FILTERS configurable via IVANTI_BU_FILTER env var
- Add query-time team filtering to GET /findings and /findings/counts
- Update AuthContext with teams helpers and admin scope toggle
- Create AdminScopeToggle component (My Teams / All BUs)
- Scope ReportingPage findings fetch by user teams
- Scope CompliancePage team selector by user teams
- Scope ExportsPage findings exports by user teams
- Add BU teams multi-select to UserManagement create/edit forms
- Display team badges in user list table
2026-05-05 11:04:53 -06:00

73 lines
2.2 KiB
JavaScript

// Authentication Middleware
// Require authenticated user
function requireAuth(db) {
return async (req, res, next) => {
const sessionId = req.cookies?.session_id;
if (!sessionId) {
return res.status(401).json({ error: 'Authentication required' });
}
try {
const session = await new Promise((resolve, reject) => {
db.get(
`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 = ? AND s.expires_at > datetime('now')`,
[sessionId],
(err, row) => {
if (err) reject(err);
else resolve(row);
}
);
});
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();
};
}
module.exports = { requireAuth, requireGroup };