All 13 nginx embed proxy ports (8881-8895) are now driven by environment variables instead of being hardcoded. This prevents port conflicts when running multiple Changemaker instances on the same host. Chain: .env → docker-compose port mappings → nginx container env → entrypoint.sh envsubst → services.conf.template listen directives → API /services/config endpoint → frontend buildServiceUrl(). Existing deployments are unaffected (all vars default to current values). Bunker Admin
81 lines
2.8 KiB
TypeScript
81 lines
2.8 KiB
TypeScript
import { Router, Request, Response } from 'express';
|
|
import { EventSeverity } from '@prisma/client';
|
|
import { authenticate, requireRole } from '../../middleware/auth';
|
|
import * as eventService from '../../services/event.service';
|
|
|
|
const router = Router();
|
|
|
|
router.use(authenticate);
|
|
|
|
// ─── Cross-Instance Event Queries ────────────────────────────────
|
|
|
|
// GET /api/events — list events with filters
|
|
router.get(
|
|
'/',
|
|
async (req: Request, res: Response) => {
|
|
const { instanceId, severity, acknowledged, source, from, to, page, limit } = req.query;
|
|
|
|
const filters: eventService.EventFilters = {
|
|
instanceId: instanceId as string | undefined,
|
|
severity: severity ? (severity as EventSeverity) : undefined,
|
|
acknowledged: acknowledged !== undefined ? acknowledged === 'true' : undefined,
|
|
source: source as string | undefined,
|
|
from: from ? new Date(from as string) : undefined,
|
|
to: to ? new Date(to as string) : undefined,
|
|
page: page ? Math.max(1, parseInt(page as string, 10)) : 1,
|
|
limit: limit ? Math.min(100, Math.max(1, parseInt(limit as string, 10))) : 50,
|
|
};
|
|
|
|
const result = await eventService.listEvents(filters);
|
|
res.json(result);
|
|
}
|
|
);
|
|
|
|
// GET /api/events/summary — unacknowledged counts for dashboard
|
|
router.get(
|
|
'/summary',
|
|
async (_req: Request, res: Response) => {
|
|
const summary = await eventService.getUnacknowledgedSummary();
|
|
res.json({ data: summary });
|
|
}
|
|
);
|
|
|
|
// PUT /api/events/:id/acknowledge — acknowledge a single event
|
|
router.put(
|
|
'/:id/acknowledge',
|
|
requireRole('SUPER_ADMIN', 'OPERATOR'),
|
|
async (req: Request, res: Response) => {
|
|
const event = await eventService.acknowledgeEvent(req.params.id as string, req.user!.id);
|
|
res.json({ data: event });
|
|
}
|
|
);
|
|
|
|
// ─── Instance-Scoped Event Routes ────────────────────────────────
|
|
// These are mounted at /api/instances/:id/events via a sub-export
|
|
|
|
export const instanceEventsRouter = Router({ mergeParams: true });
|
|
instanceEventsRouter.use(authenticate);
|
|
|
|
// GET /api/instances/:id/events
|
|
instanceEventsRouter.get(
|
|
'/',
|
|
async (req: Request, res: Response) => {
|
|
const page = Math.max(1, parseInt(req.query.page as string, 10) || 1);
|
|
const limit = Math.min(100, Math.max(1, parseInt(req.query.limit as string, 10) || 50));
|
|
const result = await eventService.listInstanceEvents(req.params.id as string, page, limit);
|
|
res.json(result);
|
|
}
|
|
);
|
|
|
|
// PUT /api/instances/:id/events/acknowledge-all
|
|
instanceEventsRouter.put(
|
|
'/acknowledge-all',
|
|
requireRole('SUPER_ADMIN', 'OPERATOR'),
|
|
async (req: Request, res: Response) => {
|
|
const result = await eventService.acknowledgeAllForInstance(req.params.id as string, req.user!.id);
|
|
res.json({ data: result });
|
|
}
|
|
);
|
|
|
|
export default router;
|