import { Suspense } from "react"; import Link from "next/link"; import { ArrowLeft } from "lucide-react"; import { verifySessionToken } from "@/lib/admin-auth"; import { getAuditLogs } from "@/lib/audit-log"; import { cookies } from "next/headers"; interface AuditLogEntry { id: string; email: string; ip_addr: string; user_agent: string; success: boolean; timestamp: string; reason?: string; } async function AuditLogsContent() { // ──── Auth Check ──── const cookieStore = await cookies(); const token = cookieStore.get("admin_session")?.value; if (!token) { return (

Unauthorized

Zurück zum Login
); } const session = await verifySessionToken(token); if (!session) { return (

Session abgelaufen

Erneut anmelden
); } // ──── Audit-Logs abrufen (letzte 100) ──── const logs = await getAuditLogs({ limit: 100, offset: 0 }); // ──── Statistiken ──── const successCount = logs.filter((l) => l.success).length; const failedCount = logs.filter((l) => !l.success).length; const uniqueEmails = new Set(logs.map((l) => l.email)).size; const uniqueIps = new Set(logs.map((l) => l.ip_addr)).size; // ──── Fehlerrate in der letzten Stunde ──── const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString(); const recentLogs = logs.filter((l) => l.timestamp > oneHourAgo); const recentFailed = recentLogs.filter((l) => !l.success).length; return (
{/* Header */}

Audit-Logs

Login-Aktivitäten und Sicherheitsereignisse

Zurück
{/* Statistiken */}
Erfolgreich (Gesamt)
{successCount}
Fehlgeschlagen (Gesamt)
{failedCount}
Fehlgeschlagen (1h)
= 5 ? "text-red-600" : "text-green-600"}`}> {recentFailed}
Eindeutige IPs
{uniqueIps}
{/* Warnung bei verdächtiger Aktivität */} {recentFailed >= 5 && (

⚠️ Verdächtige Aktivität erkannt

{recentFailed} fehlgeschlagene Login-Versuche in der letzten Stunde

)} {/* Logs Tabelle */}
{logs.length === 0 ? ( ) : ( logs.map((log) => ( )) )}
Zeitstempel E-Mail IP-Adresse Status Grund
Keine Audit-Logs vorhanden
{new Date(log.timestamp).toLocaleString("de-DE")} {log.email} {log.ip_addr} {log.success ? "✓ Erfolgreich" : "✗ Fehlgeschlagen"} {log.reason ? formatReason(log.reason) : "-"}
{/* User-Agent Info */}

Hinweis: User-Agent und detaillierte Geräte-Informationen sind in der Datenbank gespeichert. Für erweiterte Analysen siehe die Supabase-Tabelle{" "} admin_audit_logs

); } function formatReason(reason: string): string { const reasons: Record = { invalid_password: "Falsches Passwort", user_not_found_or_inactive: "User nicht gefunden / inaktiv", missing_credentials: "Fehlende Anmeldedaten", invalid_token: "Ungültiger Token", token_expired: "Token abgelaufen", }; return reasons[reason] || reason; } export default function AuditLogsPage() { return (

Lädt Audit-Logs...

} > ); }