Fix jwt-token

This commit is contained in:
2025-09-24 05:17:53 +02:00
parent 3e61013a8a
commit 1a72774848
9 changed files with 870 additions and 0 deletions

View File

@@ -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: {

View File

@@ -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;

View 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;