const jwt = require('jsonwebtoken'); const { one } = require('../db'); const JWT_SECRET = process.env.MIXEDASSETS_JWT_SECRET || 'mixedassets-local-development-secret'; function publicUser(user) { if (!user) return null; return { id: user.id, name: user.name, email: user.email, role: user.role, teamId: user.team_id }; } function tokenFor(user) { return jwt.sign({ sub: user.id, role: user.role, teamId: user.team_id }, JWT_SECRET, { expiresIn: '12h' }); } function requireAuth(req, res, next) { const header = req.headers.authorization || ''; const [, token] = header.split(' '); if (!token) return res.status(401).json({ error: 'Authentication required' }); try { const payload = jwt.verify(token, JWT_SECRET); const user = one('SELECT * FROM users WHERE id = ? AND status = ?', [payload.sub, 'active']); if (!user) return res.status(401).json({ error: 'User is inactive or missing' }); req.user = user; return next(); } catch { return res.status(401).json({ error: 'Invalid or expired token' }); } } function requireRole(...roles) { return (req, res, next) => { if (!roles.includes(req.user.role)) return res.status(403).json({ error: 'Insufficient access' }); return next(); }; } // Capability-based guard: the user's role must grant at least one of the listed capabilities. // Required lazily to avoid a load-time cycle (roles -> db -> ...). function requireCapability(...capabilities) { return (req, res, next) => { const { capabilitiesForRole } = require('../services/roles'); const { capabilitySetIncludes } = require('../services/accessControl'); const granted = capabilitiesForRole(req.user.role); if (!capabilities.some((cap) => capabilitySetIncludes(granted, cap))) { return res.status(403).json({ error: 'Insufficient access' }); } return next(); }; } module.exports = { publicUser, requireAuth, requireCapability, requireRole, tokenFor };