125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { Router, Request, Response, NextFunction } from 'express';
|
|
import { authenticate } from '../../middleware/auth.middleware';
|
|
import { requireRole } from '../../middleware/rbac.middleware';
|
|
import {
|
|
getDashboardSummary,
|
|
getSystemInfo,
|
|
getContainerStatuses,
|
|
getWeather,
|
|
getApiMetrics,
|
|
getTimeSeries,
|
|
getContainerResources,
|
|
} from './dashboard.service';
|
|
|
|
const router = Router();
|
|
router.use(authenticate);
|
|
router.use(requireRole('SUPER_ADMIN', 'INFLUENCE_ADMIN', 'MAP_ADMIN'));
|
|
|
|
// GET /api/dashboard/summary — platform counts
|
|
router.get('/summary', async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const summary = await getDashboardSummary();
|
|
res.json(summary);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/system — hardware + OS info (SUPER_ADMIN only)
|
|
router.get('/system', requireRole('SUPER_ADMIN'), async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const info = getSystemInfo();
|
|
res.json(info);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/containers — Docker container statuses (SUPER_ADMIN only)
|
|
router.get('/containers', requireRole('SUPER_ADMIN'), async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const containers = await getContainerStatuses();
|
|
res.json(containers);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/weather — weather from map settings location
|
|
router.get('/weather', async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const weather = await getWeather();
|
|
if (!weather) {
|
|
res.json({ error: 'No location configured or weather unavailable' });
|
|
return;
|
|
}
|
|
res.json(weather);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/api-metrics — Prometheus API performance metrics (SUPER_ADMIN only)
|
|
router.get('/api-metrics', requireRole('SUPER_ADMIN'), async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const metrics = await getApiMetrics();
|
|
if (!metrics) {
|
|
res.json({ error: 'Prometheus unavailable' });
|
|
return;
|
|
}
|
|
res.json(metrics);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/time-series — predefined-key time-series from Prometheus (SUPER_ADMIN only)
|
|
const ALLOWED_METRIC_KEYS = new Set([
|
|
'request_rate_2xx', 'request_rate_4xx', 'request_rate_5xx',
|
|
'latency_p50', 'latency_p95', 'latency_p99',
|
|
'email_sent_rate', 'email_failed_rate', 'email_queue_size',
|
|
'cpu_usage', 'memory_usage', 'active_sessions', 'login_rate',
|
|
]);
|
|
const ALLOWED_RANGES = new Set(['1h', '6h', '24h']);
|
|
const ALLOWED_STEPS = new Set(['1m', '5m', '15m']);
|
|
|
|
router.get('/time-series', requireRole('SUPER_ADMIN'), async (req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const metricsParam = (req.query.metrics as string) || '';
|
|
const range = (req.query.range as string) || '1h';
|
|
const step = (req.query.step as string) || '5m';
|
|
|
|
if (!ALLOWED_RANGES.has(range)) {
|
|
res.status(400).json({ error: 'Invalid range. Allowed: 1h, 6h, 24h' });
|
|
return;
|
|
}
|
|
if (!ALLOWED_STEPS.has(step)) {
|
|
res.status(400).json({ error: 'Invalid step. Allowed: 1m, 5m, 15m' });
|
|
return;
|
|
}
|
|
|
|
const metricKeys = metricsParam.split(',').filter(k => ALLOWED_METRIC_KEYS.has(k.trim()));
|
|
if (metricKeys.length === 0) {
|
|
res.status(400).json({ error: 'No valid metric keys provided' });
|
|
return;
|
|
}
|
|
|
|
const data = await getTimeSeries(metricKeys, range, step);
|
|
res.json(data);
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
// GET /api/dashboard/container-resources — cAdvisor container CPU/memory/network (SUPER_ADMIN only)
|
|
router.get('/container-resources', requireRole('SUPER_ADMIN'), async (_req: Request, res: Response, next: NextFunction) => {
|
|
try {
|
|
const containers = await getContainerResources();
|
|
res.json({ containers });
|
|
} catch (err) {
|
|
next(err);
|
|
}
|
|
});
|
|
|
|
export const dashboardRouter = router;
|