225 lines
5.6 KiB
JavaScript
225 lines
5.6 KiB
JavaScript
const express = require('express');
|
|
const { body, validationResult } = require('express-validator');
|
|
const { protect, authorize } = require('../middleware/auth');
|
|
const database = require('../config/database');
|
|
const alertService = require('../services/alertService');
|
|
const logger = require('../utils/logger');
|
|
|
|
const router = express.Router();
|
|
|
|
// Get all alerts
|
|
router.get('/', protect, async (req, res) => {
|
|
try {
|
|
const { page = 1, limit = 50, status, severity, device_id } = req.query;
|
|
const offset = (page - 1) * limit;
|
|
|
|
let query = 'SELECT * FROM alerts WHERE 1=1';
|
|
const params = [];
|
|
|
|
if (status) {
|
|
query += ' AND status = ?';
|
|
params.push(status);
|
|
}
|
|
|
|
if (severity) {
|
|
query += ' AND severity = ?';
|
|
params.push(severity);
|
|
}
|
|
|
|
if (device_id) {
|
|
query += ' AND device_id = ?';
|
|
params.push(device_id);
|
|
}
|
|
|
|
query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
|
|
params.push(parseInt(limit), offset);
|
|
|
|
const alerts = await database.query(query, params);
|
|
|
|
// Get total count
|
|
let countQuery = 'SELECT COUNT(*) as total FROM alerts WHERE 1=1';
|
|
const countParams = [];
|
|
|
|
if (status) {
|
|
countQuery += ' AND status = ?';
|
|
countParams.push(status);
|
|
}
|
|
|
|
if (severity) {
|
|
countQuery += ' AND severity = ?';
|
|
countParams.push(severity);
|
|
}
|
|
|
|
if (device_id) {
|
|
countQuery += ' AND device_id = ?';
|
|
countParams.push(device_id);
|
|
}
|
|
|
|
const [countResult] = await database.query(countQuery, countParams);
|
|
const total = countResult.total;
|
|
|
|
res.json({
|
|
success: true,
|
|
data: alerts,
|
|
pagination: {
|
|
page: parseInt(page),
|
|
limit: parseInt(limit),
|
|
total,
|
|
pages: Math.ceil(total / limit)
|
|
}
|
|
});
|
|
} catch (error) {
|
|
logger.error('Get alerts error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to get alerts'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Get alert by ID
|
|
router.get('/:alertId', protect, async (req, res) => {
|
|
try {
|
|
const { alertId } = req.params;
|
|
|
|
const alerts = await database.query(
|
|
'SELECT * FROM alerts WHERE id = ?',
|
|
[alertId]
|
|
);
|
|
|
|
if (alerts.length === 0) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Alert not found'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: alerts[0]
|
|
});
|
|
} catch (error) {
|
|
logger.error('Get alert error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to get alert'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Acknowledge alert
|
|
router.post('/:alertId/acknowledge', protect, async (req, res) => {
|
|
try {
|
|
const { alertId } = req.params;
|
|
|
|
await alertService.acknowledgeAlert(alertId, req.user.id);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Alert acknowledged successfully'
|
|
});
|
|
} catch (error) {
|
|
logger.error('Acknowledge alert error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to acknowledge alert'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Resolve alert
|
|
router.post('/:alertId/resolve', protect, [
|
|
body('resolution').optional().isString().withMessage('Resolution must be a string')
|
|
], async (req, res) => {
|
|
try {
|
|
const errors = validationResult(req);
|
|
if (!errors.isEmpty()) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
errors: errors.array()
|
|
});
|
|
}
|
|
|
|
const { alertId } = req.params;
|
|
const { resolution } = req.body;
|
|
|
|
await alertService.resolveAlert(alertId, req.user.id, resolution);
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Alert resolved successfully'
|
|
});
|
|
} catch (error) {
|
|
logger.error('Resolve alert error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to resolve alert'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Get alert statistics
|
|
router.get('/stats/overview', protect, async (req, res) => {
|
|
try {
|
|
const { period = '24h' } = req.query;
|
|
|
|
let timeFilter;
|
|
switch (period) {
|
|
case '1h':
|
|
timeFilter = 'DATE_SUB(NOW(), INTERVAL 1 HOUR)';
|
|
break;
|
|
case '24h':
|
|
timeFilter = 'DATE_SUB(NOW(), INTERVAL 24 HOUR)';
|
|
break;
|
|
case '7d':
|
|
timeFilter = 'DATE_SUB(NOW(), INTERVAL 7 DAY)';
|
|
break;
|
|
case '30d':
|
|
timeFilter = 'DATE_SUB(NOW(), INTERVAL 30 DAY)';
|
|
break;
|
|
default:
|
|
timeFilter = 'DATE_SUB(NOW(), INTERVAL 24 HOUR)';
|
|
}
|
|
|
|
// Get total alerts
|
|
const [totalAlerts] = await database.query(
|
|
`SELECT COUNT(*) as count FROM alerts WHERE created_at >= ${timeFilter}`
|
|
);
|
|
|
|
// Get alerts by severity
|
|
const severityStats = await database.query(
|
|
`SELECT severity, COUNT(*) as count FROM alerts WHERE created_at >= ${timeFilter} GROUP BY severity`
|
|
);
|
|
|
|
// Get alerts by status
|
|
const statusStats = await database.query(
|
|
`SELECT status, COUNT(*) as count FROM alerts WHERE created_at >= ${timeFilter} GROUP BY status`
|
|
);
|
|
|
|
// Get alerts by type
|
|
const typeStats = await database.query(
|
|
`SELECT type, COUNT(*) as count FROM alerts WHERE created_at >= ${timeFilter} GROUP BY type ORDER BY count DESC LIMIT 10`
|
|
);
|
|
|
|
const stats = {
|
|
period,
|
|
total_alerts: totalAlerts.count,
|
|
by_severity: severityStats,
|
|
by_status: statusStats,
|
|
by_type: typeStats
|
|
};
|
|
|
|
res.json({
|
|
success: true,
|
|
data: stats
|
|
});
|
|
} catch (error) {
|
|
logger.error('Get alert stats error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to get alert statistics'
|
|
});
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|