new features
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* Admin API Routes — Audit Log
|
||||
* Admin API Routes — Audit Log + Data Cleanup
|
||||
*
|
||||
* GET /api/admin/audit-log — paginated, filtered list
|
||||
* GET /api/admin/audit-log/export — CSV download of filtered results
|
||||
* DELETE /api/admin/cleanup/:target — preview / delete old data
|
||||
*
|
||||
* Both endpoints require authentication + admin:access permission.
|
||||
*
|
||||
@@ -18,6 +19,7 @@ import { authenticate } from '../middleware/auth.middleware';
|
||||
import { requirePermission } from '../middleware/rbac.middleware';
|
||||
import { auditExport } from '../middleware/audit.middleware';
|
||||
import auditService, { AuditAction, AuditResourceType, AuditFilters } from '../services/audit.service';
|
||||
import cleanupService from '../services/cleanup.service';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
const router = Router();
|
||||
@@ -213,4 +215,53 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Cleanup / Data Management endpoints
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const cleanupBodySchema = z.object({
|
||||
olderThanDays: z.number().int().min(1).max(3650),
|
||||
confirm: z.boolean().optional().default(false),
|
||||
});
|
||||
|
||||
type CleanupTarget = 'notifications' | 'audit-log' | 'events' | 'bookings' | 'orders' | 'vehicle-history' | 'equipment-history';
|
||||
|
||||
const CLEANUP_TARGETS: Record<CleanupTarget, (days: number, confirm: boolean) => Promise<{ count: number; deleted: boolean }>> = {
|
||||
'notifications': (d, c) => cleanupService.cleanupNotifications(d, c),
|
||||
'audit-log': (d, c) => cleanupService.cleanupAuditLog(d, c),
|
||||
'events': (d, c) => cleanupService.cleanupEvents(d, c),
|
||||
'bookings': (d, c) => cleanupService.cleanupBookings(d, c),
|
||||
'orders': (d, c) => cleanupService.cleanupOrders(d, c),
|
||||
'vehicle-history': (d, c) => cleanupService.cleanupVehicleHistory(d, c),
|
||||
'equipment-history': (d, c) => cleanupService.cleanupEquipmentHistory(d, c),
|
||||
};
|
||||
|
||||
router.delete(
|
||||
'/cleanup/:target',
|
||||
authenticate,
|
||||
requirePermission('admin:write'),
|
||||
async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const target = req.params.target as CleanupTarget;
|
||||
const handler = CLEANUP_TARGETS[target];
|
||||
if (!handler) {
|
||||
res.status(400).json({ success: false, message: `Unknown cleanup target: ${target}` });
|
||||
return;
|
||||
}
|
||||
|
||||
const { olderThanDays, confirm } = cleanupBodySchema.parse(req.body);
|
||||
const result = await handler(olderThanDays, confirm);
|
||||
|
||||
res.json({ success: true, data: result });
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ success: false, message: 'Invalid parameters', errors: error.issues });
|
||||
return;
|
||||
}
|
||||
logger.error('Cleanup failed', { error, target: req.params.target });
|
||||
res.status(500).json({ success: false, message: 'Cleanup failed' });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user