"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateToken = generateToken; exports.verifyToken = verifyToken; exports.authenticateUser = authenticateUser; exports.authMiddleware = authMiddleware; exports.requireRole = requireRole; const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); const bcrypt_1 = __importDefault(require("bcrypt")); const migrate_1 = require("../db/migrate"); const JWT_SECRET = process.env.JWT_SECRET || 'change_this_in_production'; function generateToken(user) { return jsonwebtoken_1.default.sign({ id: user.id, email: user.email, role: user.role }, JWT_SECRET, { expiresIn: '7d' }); } function verifyToken(token) { try { return jsonwebtoken_1.default.verify(token, JWT_SECRET); } catch (error) { return null; } } async function authenticateUser(email, password) { const result = await migrate_1.pool.query('SELECT id, email, password_hash, role FROM users WHERE email = $1', [email]); if (result.rows.length === 0) { return null; } const user = result.rows[0]; const isValid = await bcrypt_1.default.compare(password, user.password_hash); if (!isValid) { return null; } return { id: user.id, email: user.email, role: user.role }; } async function authMiddleware(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: 'No token provided' }); } const token = authHeader.substring(7); // Try JWT first const jwtUser = verifyToken(token); if (jwtUser) { req.user = jwtUser; return next(); } // If JWT fails, try API token try { const result = await migrate_1.pool.query(` SELECT id, name, rate_limit, active, expires_at, allowed_endpoints FROM api_tokens WHERE token = $1 `, [token]); if (result.rows.length === 0) { return res.status(401).json({ error: 'Invalid token' }); } const apiToken = result.rows[0]; // Check if token is active if (!apiToken.active) { return res.status(401).json({ error: 'Token is disabled' }); } // Check if token is expired if (apiToken.expires_at && new Date(apiToken.expires_at) < new Date()) { return res.status(401).json({ error: 'Token has expired' }); } // Check allowed endpoints if (apiToken.allowed_endpoints && apiToken.allowed_endpoints.length > 0) { const isAllowed = apiToken.allowed_endpoints.some((pattern) => { // Simple wildcard matching const regex = new RegExp('^' + pattern.replace('*', '.*') + '$'); return regex.test(req.path); }); if (!isAllowed) { return res.status(403).json({ error: 'Endpoint not allowed for this token' }); } } // Set API token on request for tracking req.apiToken = { id: apiToken.id, name: apiToken.name, rate_limit: apiToken.rate_limit }; // Set a generic user for compatibility with existing code req.user = { id: apiToken.id, email: `api-token-${apiToken.id}@system`, role: 'api' }; next(); } catch (error) { console.error('Error verifying API token:', error); return res.status(500).json({ error: 'Authentication failed' }); } } function requireRole(...roles) { return (req, res, next) => { if (!req.user) { return res.status(401).json({ error: 'Not authenticated' }); } if (!roles.includes(req.user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }); } next(); }; }