import { createServiceClient } from "@/lib/supabase"; export interface AuditLogEntry { id: string; email: string; ip_addr: string; user_agent: string; success: boolean; timestamp: string; reason?: string; // z.B. "invalid_password", "user_not_found", "account_inactive" } /** * Protokolliert einen Login-Versuch (erfolgreich oder fehlgeschlagen) */ export async function logLoginAttempt( email: string, ipAddr: string, success: boolean, userAgent: string, reason?: string ): Promise { try { const db = createServiceClient(); await db.from("admin_audit_logs").insert({ email: email.toLowerCase().trim(), ip_addr: ipAddr, user_agent: userAgent, success, reason, timestamp: new Date().toISOString(), }); } catch (error) { console.error("Fehler beim Audit-Logging:", error); // Nicht werfen – Login sollte nicht scheitern wenn Logging scheitert } } /** * Prüft auf verdächtige Aktivitäten (zu viele fehlgeschlagene Versuche) * Gibt die Anzahl fehlgeschlagener Versuche in der letzten Stunde zurück */ export async function getFailedLoginCount( emailOrIp: string, type: "email" | "ip" = "email", timeWindowMinutes = 60 ): Promise { try { const db = createServiceClient(); const since = new Date(Date.now() - timeWindowMinutes * 60 * 1000).toISOString(); const column = type === "email" ? "email" : "ip_addr"; const { count } = await db .from("admin_audit_logs") .select("id", { count: "exact" }) .eq(column, emailOrIp) .eq("success", false) .gt("timestamp", since); return count || 0; } catch (error) { console.error("Fehler beim Abrufen fehlgeschlagener Logins:", error); return 0; } } /** * Holt die Audit-Log-Einträge mit optionalen Filtern */ export async function getAuditLogs(options?: { email?: string; ipAddr?: string; successOnly?: boolean; limit?: number; offset?: number; }): Promise { try { const db = createServiceClient(); const limit = options?.limit ?? 100; const offset = options?.offset ?? 0; let query = db .from("admin_audit_logs") .select("*") .order("timestamp", { ascending: false }) .range(offset, offset + limit - 1); if (options?.email) { query = query.eq("email", options.email.toLowerCase().trim()); } if (options?.ipAddr) { query = query.eq("ip_addr", options.ipAddr); } if (options?.successOnly !== undefined) { query = query.eq("success", options.successOnly); } const { data, error } = await query; if (error) { console.error("Fehler beim Abrufen von Audit-Logs:", error); return []; } return data || []; } catch (error) { console.error("Fehler beim Abrufen von Audit-Logs:", error); return []; } } /** * Löscht alte Audit-Logs (älter als X Tage) * Sollte als Cron-Job regelmäßig ausgeführt werden */ export async function deleteOldAuditLogs(daysToKeep = 90): Promise { try { const db = createServiceClient(); const cutoffDate = new Date(Date.now() - daysToKeep * 24 * 60 * 60 * 1000).toISOString(); await db .from("admin_audit_logs") .delete() .lt("timestamp", cutoffDate); console.log(`Audit-Logs älter als ${daysToKeep} Tage gelöscht.`); } catch (error) { console.error("Fehler beim Löschen alter Audit-Logs:", error); } } /** * Sendet eine Alert-Email bei verdächtiger Aktivität * TODO: Implementieren wenn Email-System erweitert ist */ export async function sendSecurityAlert( subject: string, message: string, adminEmail: string = process.env.SMTP_TO || "" ): Promise { if (!adminEmail) { console.warn("SMTP_TO nicht konfiguriert – keine Alert-Email gesendet"); return; } try { // TODO: Nodemailer/Email-Integration wenn nötig console.log(`⚠️ SECURITY ALERT: ${subject}\n${message}`); } catch (error) { console.error("Fehler beim Senden der Security-Alert:", error); } }