[FEAT] Add EmailService, RateLimitService, ReportService + integrations

Services:
- EmailService: CSIRT notifications (24h/72h/30d), training alerts, welcome email
- RateLimitService: File-based rate limiting for auth and AI endpoints
- ReportService: Executive HTML report, CSV exports (risks/incidents/controls/assets)

Integrations:
- AuthController: Rate limiting on login (5/min, 20/h) and register (3/10min)
- IncidentController: Email notifications on CSIRT milestones
- AuditController: Executive report and CSV export endpoints
- Router: 429 rate limit error handling, new audit export routes

Database:
- Migration 002: email_log table for notification tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 19:12:46 +01:00
co-authored by Claude Opus 4.6
parent 9aa2788c68
commit 6f4b457ce0
9 changed files with 2383 additions and 0 deletions
+15
View File
@@ -258,6 +258,8 @@ $actionMap = [
'GET:report' => 'generateReport',
'GET:logs' => 'getAuditLogs',
'GET:iso27001Mapping' => 'getIsoMapping',
'GET:executiveReport' => 'executiveReport',
'GET:export' => 'export',
],
// ── AdminController ─────────────────────────────
@@ -373,6 +375,19 @@ try {
} else {
$controller->$resolvedAction();
}
} catch (RuntimeException $e) {
// Rate limit exceeded (429)
if ($e->getCode() === 429) {
http_response_code(429);
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'message' => $e->getMessage(),
'error_code' => 'RATE_LIMITED',
]);
exit;
}
throw $e;
} catch (PDOException $e) {
error_log('[DB_ERROR] ' . $e->getMessage());
http_response_code(500);
+2
View File
@@ -238,6 +238,8 @@ class NIS2API {
generateComplianceReport() { return this.get('/audit/report'); }
getAuditLogs(params = {}) { return this.get('/audit/logs?' + new URLSearchParams(params)); }
getIsoMapping() { return this.get('/audit/iso27001-mapping'); }
getExecutiveReportUrl() { return this.baseUrl + '/audit/executive-report'; }
getExportUrl(type) { return this.baseUrl + '/audit/export?type=' + type; }
// ═══════════════════════════════════════════════════════════════════
// Onboarding