cms.c2sgmbh/src/hooks/auditTenantChanges.ts
Martin Porwoll f667792ba7 fix: complete audit logging integration based on audit review
Fixes identified gaps from the monitoring & alerting audit:

1. Auth Events Integration:
   - Add auditAuthEvents.ts hook for login/logout tracking
   - Integrate afterLogin and afterLogout hooks in Users collection
   - Log successful logins, logouts, and password reset requests

2. Rate-Limit Logging:
   - Add logRateLimit calls to /api/send-email endpoint
   - Log when users exceed rate limits

3. Access-Denied Logging:
   - Add logAccessDenied calls to all protected endpoints:
     - /api/send-email
     - /api/email-logs/export
     - /api/email-logs/stats

4. Tenant Delete Sanitizing Fix:
   - Extract sanitizeTenantDoc as reusable function
   - Apply sanitization to auditTenantAfterDelete hook
   - SMTP passwords are now properly masked in delete audit logs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 21:24:28 +00:00

85 lines
2 KiB
TypeScript

/**
* Audit Hook für Tenant-Änderungen
*
* Loggt alle Änderungen an Tenant-Dokumenten für Compliance und Debugging.
*/
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload'
import { logTenantChange } from '../lib/audit/audit-service'
interface TenantUser {
id: number
email: string
isSuperAdmin?: boolean
}
/**
* Entfernt sensitive Felder aus Tenant-Dokumenten für Audit-Logging
* WICHTIG: Diese Funktion muss bei ALLEN Audit-Operationen verwendet werden
*/
const sanitizeTenantDoc = (document: Record<string, unknown> | undefined) => {
if (!document) return undefined
const sanitized = { ...document }
// SMTP-Passwort entfernen
if (sanitized.email && typeof sanitized.email === 'object') {
const emailConfig = { ...(sanitized.email as Record<string, unknown>) }
if (emailConfig.smtp && typeof emailConfig.smtp === 'object') {
const smtp = { ...(emailConfig.smtp as Record<string, unknown>) }
delete smtp.pass
emailConfig.smtp = smtp
}
sanitized.email = emailConfig
}
return sanitized
}
/**
* Hook: Loggt Tenant-Erstellung und -Aktualisierung
*/
export const auditTenantAfterChange: CollectionAfterChangeHook = async ({
doc,
previousDoc,
operation,
req,
}) => {
const user = req.user as TenantUser | undefined
if (!user) return doc
await logTenantChange(
req.payload,
doc.id,
operation,
user.id,
user.email,
sanitizeTenantDoc(previousDoc),
sanitizeTenantDoc(doc),
req,
)
return doc
}
/**
* Hook: Loggt Tenant-Löschung
* WICHTIG: Verwendet sanitizeTenantDoc um SMTP-Passwörter zu maskieren
*/
export const auditTenantAfterDelete: CollectionAfterDeleteHook = async ({ doc, req }) => {
const user = req.user as TenantUser | undefined
if (!user) return doc
// WICHTIG: Auch bei Löschung das Dokument sanitizen!
await logTenantChange(
req.payload,
doc.id,
'delete',
user.id,
user.email,
sanitizeTenantDoc(doc),
undefined,
req,
)
return doc
}