Fix jwt-token
This commit is contained in:
@@ -292,9 +292,14 @@ router.get('/devices', async (req, res) => {
|
||||
const deviceDetails = [];
|
||||
|
||||
for (const device of devices) {
|
||||
const lastHeartbeat = device.heartbeats && device.heartbeats[0];
|
||||
const isOnline = lastHeartbeat &&
|
||||
(Date.now() - new Date(lastHeartbeat.timestamp).getTime()) < 300000; // 5 minutes
|
||||
// Get latest heartbeat metrics for this device
|
||||
const latestHeartbeat = await Heartbeat.findOne({
|
||||
where: { device_id: device.id },
|
||||
order: [['timestamp', 'DESC']]
|
||||
});
|
||||
|
||||
const isOnline = latestHeartbeat &&
|
||||
(Date.now() - new Date(latestHeartbeat.timestamp).getTime()) < 300000; // 5 minutes
|
||||
|
||||
if (isOnline) {
|
||||
onlineDevices++;
|
||||
@@ -302,12 +307,29 @@ router.get('/devices', async (req, res) => {
|
||||
offlineDevices++;
|
||||
}
|
||||
|
||||
// Calculate uptime (time since first heartbeat)
|
||||
const firstHeartbeat = await Heartbeat.findOne({
|
||||
where: { device_id: device.id },
|
||||
order: [['timestamp', 'ASC']]
|
||||
});
|
||||
|
||||
let uptime = null;
|
||||
if (firstHeartbeat && latestHeartbeat) {
|
||||
uptime = Math.floor((new Date(latestHeartbeat.timestamp).getTime() - new Date(firstHeartbeat.timestamp).getTime()) / 1000);
|
||||
}
|
||||
|
||||
deviceDetails.push({
|
||||
id: device.id,
|
||||
name: device.name,
|
||||
status: isOnline ? 'online' : 'offline',
|
||||
lastSeen: lastHeartbeat ? lastHeartbeat.timestamp : null,
|
||||
uptime: lastHeartbeat ? Math.floor(Date.now() / 1000) - Math.floor(new Date(lastHeartbeat.timestamp).getTime() / 1000) : null
|
||||
lastSeen: latestHeartbeat ? latestHeartbeat.timestamp : null,
|
||||
uptime: uptime,
|
||||
metrics: latestHeartbeat ? {
|
||||
cpu_usage: latestHeartbeat.cpu_usage,
|
||||
memory_usage: latestHeartbeat.memory_usage,
|
||||
disk_usage: latestHeartbeat.disk_usage,
|
||||
uptime: latestHeartbeat.uptime
|
||||
} : null
|
||||
});
|
||||
}
|
||||
|
||||
@@ -350,17 +372,58 @@ router.post('/devices/:id/heartbeat', async (req, res) => {
|
||||
if (!device.is_approved) {
|
||||
return res.status(403).json({
|
||||
status: 'error',
|
||||
message: 'Device not approved for heartbeat reporting'
|
||||
message: 'Device not approved for heartbeat reporting',
|
||||
approval_required: true
|
||||
});
|
||||
}
|
||||
|
||||
// Validate heartbeat data format
|
||||
const { status, cpu_usage, memory_usage, disk_usage } = req.body;
|
||||
const { timestamp, status, cpu_usage, memory_usage, disk_usage } = req.body;
|
||||
|
||||
if (!status || typeof status !== 'string') {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: 'Invalid heartbeat data format - status is required'
|
||||
message: 'Invalid heartbeat data format - status is required and must be a string'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate status values
|
||||
const validStatuses = ['online', 'offline', 'error', 'maintenance'];
|
||||
if (!validStatuses.includes(status)) {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: `Invalid status value. Must be one of: ${validStatuses.join(', ')}`
|
||||
});
|
||||
}
|
||||
|
||||
// Validate timestamp if provided
|
||||
if (timestamp && isNaN(new Date(timestamp).getTime())) {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: 'Invalid timestamp format'
|
||||
});
|
||||
}
|
||||
|
||||
// Validate percentage fields
|
||||
const percentageFields = { cpu_usage, memory_usage, disk_usage };
|
||||
for (const [field, value] of Object.entries(percentageFields)) {
|
||||
if (value !== undefined && value !== null && (typeof value !== 'number' || value < 0 || value > 100)) {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: `Invalid ${field} value. Must be a number between 0 and 100`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unexpected fields
|
||||
const allowedFields = ['timestamp', 'status', 'cpu_usage', 'memory_usage', 'disk_usage', 'uptime'];
|
||||
const receivedFields = Object.keys(req.body);
|
||||
const invalidFields = receivedFields.filter(field => !allowedFields.includes(field));
|
||||
|
||||
if (invalidFields.length > 0) {
|
||||
return res.status(400).json({
|
||||
status: 'error',
|
||||
message: `Invalid fields in heartbeat data: ${invalidFields.join(', ')}`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -431,18 +494,51 @@ router.get('/metrics', async (req, res) => {
|
||||
await sequelize.authenticate();
|
||||
const dbResponseTime = Date.now() - startTime;
|
||||
|
||||
// Get CPU usage
|
||||
const cpuUsage = process.cpuUsage();
|
||||
|
||||
// Get database statistics
|
||||
const [deviceCount] = await sequelize.query(
|
||||
'SELECT COUNT(*) as count FROM "Devices" WHERE tenant_id = :tenantId',
|
||||
{
|
||||
replacements: { tenantId: req.user.tenant_id },
|
||||
type: sequelize.QueryTypes.SELECT
|
||||
}
|
||||
);
|
||||
|
||||
const [detectionCount] = await sequelize.query(
|
||||
'SELECT COUNT(*) as count FROM "DroneDetections" WHERE tenant_id = :tenantId',
|
||||
{
|
||||
replacements: { tenantId: req.user.tenant_id },
|
||||
type: sequelize.QueryTypes.SELECT
|
||||
}
|
||||
);
|
||||
|
||||
res.status(200).json({
|
||||
status: 'ok',
|
||||
metrics: {
|
||||
system: {
|
||||
memory: {
|
||||
heapUsed: Math.round((memUsage.heapUsed / 1024 / 1024) * 100) / 100,
|
||||
heapTotal: Math.round((memUsage.heapTotal / 1024 / 1024) * 100) / 100,
|
||||
external: Math.round((memUsage.external / 1024 / 1024) * 100) / 100
|
||||
},
|
||||
database: {
|
||||
responseTime: dbResponseTime
|
||||
cpu: {
|
||||
user: cpuUsage.user,
|
||||
system: cpuUsage.system
|
||||
},
|
||||
uptime: process.uptime()
|
||||
},
|
||||
database: {
|
||||
responseTime: dbResponseTime,
|
||||
connection_pool: {
|
||||
active: sequelize.connectionManager.pool._count || 0,
|
||||
idle: sequelize.connectionManager.pool._idle?.length || 0,
|
||||
total: sequelize.connectionManager.pool.options.max || 10
|
||||
}
|
||||
},
|
||||
statistics: {
|
||||
total_devices: parseInt(deviceCount.count),
|
||||
total_detections: parseInt(detectionCount.count)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user