const express = require('express'); const router = express.Router(); const { Op } = require('sequelize'); const { authenticateToken, requireRole } = require('../middleware/auth'); // Security logs endpoint - tenant-specific with admin-only access router.get('/', authenticateToken, requireRole('admin'), async (req, res) => { try { const { page = 1, limit = 50, level = 'all', eventType = 'all', timeRange = '24h', search = '' } = req.query; const { SecurityLog } = require('../models'); // Build where conditions - only show logs for current tenant let whereConditions = { tenant_id: req.user.tenant_id // Ensure tenant isolation }; // Filter by security level if (level !== 'all') { whereConditions.level = level; } // Filter by event type if (eventType !== 'all') { whereConditions.event_type = eventType; } // Filter by time range const now = new Date(); let startTime; switch (timeRange) { case '1h': startTime = new Date(now.getTime() - 60 * 60 * 1000); break; case '24h': startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000); break; case '7d': startTime = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); break; case '30d': startTime = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); break; default: startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000); } if (timeRange !== 'all') { whereConditions.timestamp = { [Op.gte]: startTime }; } // Search filter - only search within tenant's logs if (search) { whereConditions[Op.or] = [ { message: { [Op.iLike]: `%${search}%` } }, { 'metadata.ip_address': { [Op.iLike]: `%${search}%` } }, { 'metadata.username': { [Op.iLike]: `%${search}%` } } ]; } const offset = (parseInt(page) - 1) * parseInt(limit); const { rows: logs, count: total } = await SecurityLog.findAndCountAll({ where: whereConditions, order: [['timestamp', 'DESC']], limit: parseInt(limit), offset: offset, attributes: [ 'id', 'timestamp', 'level', 'event_type', 'message', 'metadata' ] // Don't expose sensitive internal data }); res.json({ success: true, logs, total, page: parseInt(page), limit: parseInt(limit), totalPages: Math.ceil(total / parseInt(limit)) }); } catch (error) { console.error('Error retrieving tenant security logs:', error); res.status(500).json({ success: false, message: 'Failed to retrieve security logs', error: process.env.NODE_ENV === 'development' ? error.message : undefined }); } }); // Security logs summary endpoint for dashboard widgets router.get('/summary', authenticateToken, requireRole('admin'), async (req, res) => { try { const { timeRange = '24h' } = req.query; const { SecurityLog } = require('../models'); // Calculate time range const now = new Date(); let startTime; switch (timeRange) { case '1h': startTime = new Date(now.getTime() - 60 * 60 * 1000); break; case '24h': startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000); break; case '7d': startTime = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); break; case '30d': startTime = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); break; default: startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000); } const baseWhere = { tenant_id: req.user.tenant_id, timestamp: { [Op.gte]: startTime } }; // Get summary statistics const [ totalLogs, criticalLogs, highLogs, failedLogins, successfulLogins, countryAlerts, bruteForceAttempts ] = await Promise.all([ SecurityLog.count({ where: baseWhere }), SecurityLog.count({ where: { ...baseWhere, level: 'critical' } }), SecurityLog.count({ where: { ...baseWhere, level: 'high' } }), SecurityLog.count({ where: { ...baseWhere, event_type: 'failed_login' } }), SecurityLog.count({ where: { ...baseWhere, event_type: 'successful_login' } }), SecurityLog.count({ where: { ...baseWhere, event_type: 'country_alert' } }), SecurityLog.count({ where: { ...baseWhere, event_type: 'brute_force' } }) ]); // Get recent critical events const recentCriticalEvents = await SecurityLog.findAll({ where: { ...baseWhere, level: { [Op.in]: ['critical', 'high'] } }, order: [['timestamp', 'DESC']], limit: 5, attributes: ['timestamp', 'level', 'event_type', 'message'] }); res.json({ success: true, summary: { period: { start: startTime.toISOString(), end: now.toISOString(), range: timeRange }, totals: { totalLogs, criticalLogs, highLogs, failedLogins, successfulLogins, countryAlerts, bruteForceAttempts }, recentCriticalEvents } }); } catch (error) { console.error('Error retrieving security logs summary:', error); res.status(500).json({ success: false, message: 'Failed to retrieve security logs summary' }); } }); module.exports = router;