Fix jwt-token
This commit is contained in:
@@ -17,6 +17,7 @@ const detectionsRoutes = require('./detections');
|
||||
const droneTypesRoutes = require('./droneTypes');
|
||||
const tenantDebugRoutes = require('./tenant-debug');
|
||||
const dataRetentionRoutes = require('./dataRetention');
|
||||
const securityLogsRoutes = require('./securityLogs');
|
||||
|
||||
// Management portal routes (before API versioning)
|
||||
router.use('/management', managementRoutes);
|
||||
@@ -37,6 +38,7 @@ router.use('/v1/device-health', deviceHealthRoutes);
|
||||
router.use('/v1/detectors', detectorsRoutes);
|
||||
router.use('/v1/detections', detectionsRoutes);
|
||||
router.use('/v1/drone-types', droneTypesRoutes);
|
||||
router.use('/v1/security-logs', securityLogsRoutes);
|
||||
|
||||
// Default routes (no version prefix for backward compatibility)
|
||||
router.use('/devices', deviceRoutes);
|
||||
@@ -49,6 +51,7 @@ router.use('/debug', debugRoutes);
|
||||
router.use('/detectors', detectorsRoutes);
|
||||
router.use('/detections', detectionsRoutes);
|
||||
router.use('/drone-types', droneTypesRoutes);
|
||||
router.use('/security-logs', securityLogsRoutes);
|
||||
router.use('/tenant-debug', tenantDebugRoutes);
|
||||
router.use('/data-retention', dataRetentionRoutes);
|
||||
|
||||
@@ -67,6 +70,7 @@ router.get('/', (req, res) => {
|
||||
health: '/api/health',
|
||||
'device-health': '/api/device-health',
|
||||
'drone-types': '/api/drone-types',
|
||||
'security-logs': '/api/security-logs',
|
||||
'data-retention': '/api/data-retention'
|
||||
},
|
||||
microservices: {
|
||||
|
||||
@@ -1561,4 +1561,93 @@ router.get('/audit-logs/summary', requireManagementAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Security logs endpoint - view ALL security logs across tenants
|
||||
router.get('/security-logs', requireManagementAuth, 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
|
||||
let whereConditions = {};
|
||||
|
||||
// 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
|
||||
if (search) {
|
||||
whereConditions[Op.or] = [
|
||||
{ message: { [Op.iLike]: `%${search}%` } },
|
||||
{ 'metadata.ip_address': { [Op.iLike]: `%${search}%` } },
|
||||
{ 'metadata.username': { [Op.iLike]: `%${search}%` } },
|
||||
{ 'metadata.tenant_slug': { [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
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
logs,
|
||||
total,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
totalPages: Math.ceil(total / parseInt(limit))
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error retrieving security logs:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to retrieve security logs',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
192
server/routes/securityLogs.js
Normal file
192
server/routes/securityLogs.js
Normal file
@@ -0,0 +1,192 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user