/** * Antivirus Admin Routes * Admin endpoints for ClamAV management and audit logs. */ import { Router, Request, Response } from 'express'; import { authenticateToken } from '../middlewares/auth.middleware'; import { requireAdmin } from '../middlewares/authorization.middleware'; import { asyncHandler } from '../middlewares/errorHandler.middleware'; import { getToggleStatus, setToggleStatus, getToggleHistory, } from '../services/clamav/clamavToggleManager'; import { pingDaemon } from '../services/clamav/clamavScanWrapper'; import { readAuditLogs, getAuditStats, exportAuditLogsCSV, logSecurityEvent, SecurityEventType, } from '../services/logging/securityEventLogger'; const router = Router(); // All routes require admin authentication router.use(authenticateToken, requireAdmin); /** * GET /api/v1/antivirus/clamav-status * Get ClamAV toggle status, daemon health, and recent toggle history */ router.get( '/clamav-status', asyncHandler(async (_req: Request, res: Response) => { const toggleStatus = getToggleStatus(); const daemonStatus = await pingDaemon(); const recentHistory = getToggleHistory(10); res.json({ success: true, toggle: toggleStatus, daemon: daemonStatus, recentHistory, }); }) ); /** * POST /api/v1/antivirus/clamav-toggle * Enable or disable ClamAV scanning * Body: { enabled: boolean, reason: string } */ router.post( '/clamav-toggle', asyncHandler(async (req: Request, res: Response) => { const { enabled, reason } = req.body; if (typeof enabled !== 'boolean') { res.status(400).json({ success: false, message: '"enabled" must be a boolean', }); return; } if (!reason || typeof reason !== 'string') { res.status(400).json({ success: false, message: '"reason" is required', }); return; } const userId = (req as any).user?.id || (req as any).user?.email || 'unknown'; const result = setToggleStatus(enabled, userId, reason); // Log the admin action logSecurityEvent(SecurityEventType.CLAMAV_TOGGLE_CHANGED, { enabled, reason, changedBy: userId, }, userId); res.json({ success: true, message: `ClamAV scanning ${enabled ? 'enabled' : 'disabled'}`, state: result.state, }); }) ); /** * GET /api/v1/antivirus/audit-logs * Search and paginate security audit logs * Query params: eventType, severity, category, startDate, endDate, limit, offset */ router.get( '/audit-logs', asyncHandler(async (req: Request, res: Response) => { const { eventType, severity, category, startDate, endDate, limit = '50', offset = '0', } = req.query; const result = readAuditLogs({ eventType: eventType as string, severity: severity as string, category: category as string, startDate: startDate as string, endDate: endDate as string, limit: parseInt(limit as string, 10), offset: parseInt(offset as string, 10), }); res.json({ success: true, ...result, }); }) ); /** * GET /api/v1/antivirus/audit-logs/export * Export filtered audit logs as CSV */ router.get( '/audit-logs/export', asyncHandler(async (req: Request, res: Response) => { const { eventType, severity, startDate, endDate } = req.query; const csv = exportAuditLogsCSV({ eventType: eventType as string, severity: severity as string, startDate: startDate as string, endDate: endDate as string, }); res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Disposition', `attachment; filename=audit-logs-${new Date().toISOString().split('T')[0]}.csv`); res.send(csv); }) ); /** * GET /api/v1/antivirus/audit-stats * Get audit log statistics */ router.get( '/audit-stats', asyncHandler(async (_req: Request, res: Response) => { const stats = getAuditStats(); res.json({ success: true, stats, }); }) ); export default router;