exec('DELETE FROM login_events'); audit_log($admin['id'], 'Anmelde-Wächter: Protokoll geleert (' . (int) $n . ' Einträge)'); flash('success', 'Protokoll geleert.'); } elseif ($action === 'forget_devices') { $sid = (int) ($_POST['staff_id'] ?? 0); if ($sid > 0) { $pdo->prepare('DELETE FROM login_devices WHERE staff_id = ?')->execute([$sid]); $pdo->prepare('DELETE FROM login_places WHERE staff_id = ?')->execute([$sid]); audit_log($admin['id'], 'Anmelde-Wächter: gemerkte Geräte und Orte vergessen (Mitarbeiter ' . $sid . ')'); flash('success', 'Geräte und Orte vergessen. Die nächste Anmeldung zählt wieder als erste.'); } } redirect('/staff/login_log.php'); } $labels = login_guard_event_labels(); $filter = (string) ($_GET['event'] ?? ''); if (!isset($labels[$filter])) $filter = ''; $q = trim((string) ($_GET['q'] ?? '')); $where = ['1=1']; $params = []; if ($filter !== '') { $where[] = 'e.event = ?'; $params[] = $filter; } if ($q !== '') { $where[] = '(e.email LIKE ? OR e.ip LIKE ? OR e.device LIKE ? OR e.place LIKE ?)'; $like = '%' . $q . '%'; array_push($params, $like, $like, $like, $like); } $st = $pdo->prepare('SELECT e.*, s.name AS staff_name FROM login_events e LEFT JOIN staff s ON s.id = e.staff_id WHERE ' . implode(' AND ', $where) . ' ORDER BY e.id DESC LIMIT 300'); $st->execute($params); $rows = $st->fetchAll(); $since = date('Y-m-d H:i:s', time() - 86400); $cnt = $pdo->prepare('SELECT event, COUNT(*) AS n FROM login_events WHERE created_at >= ? GROUP BY event'); $cnt->execute([$since]); $counts = array_fill_keys(array_keys($labels), 0); foreach ($cnt->fetchAll() as $r) $counts[$r['event']] = (int) $r['n']; $pageTitle = 'Anmelde-Wächter'; $activePage = 'login_log'; $colors = ['success' => '#15803d', 'new_device' => '#b45309', 'new_place' => '#b45309', 'failed' => '#b91c1c', 'locked' => '#b91c1c', 'revoked' => '#7c3aed']; require __DIR__ . '/_header.php'; ?>
Der Wächter merkt sich die Geräte und Orte, von denen sich Mitarbeiter anmelden (Web und App). Meldet sich jemand von einem neuen Gerät oder neuen Ort an, bekommt er eine Mail mit dem Link „Das war ich nicht“. Der Link macht das Passwort ungültig, beendet App-Anmeldungen und Browser-Sitzungen und informiert die Administratoren. Nach zu vielen Fehlversuchen wird die Anmeldung gesperrt; auch das steht im Protokoll und geht per Mail an Kontoinhaber und Administratoren. Als Ort gilt das Land (wenn Cloudflare es mitschickt), sonst das Netz der IP-Adresse; die erste Anmeldung eines Kontos wird still gemerkt.
Keine Einträge= ($filter !== '' || $q !== '') ? ' zu diesem Filter' : '' ?>.
| Zeit | Ereignis | Konto | Gerät | Ort / IP | Hinweis | |
|---|---|---|---|---|---|---|
| = e(date('d.m.Y H:i', strtotime((string) $r['created_at']))) ?> | = e($labels[$r['event']] ?? $r['event']) ?> = $r['channel'] === 'app' ? 'App' : 'Web' ?> |
= $r['staff_name'] ? e($r['staff_name']) . ' ' . e($r['email']) . ' ' : e($r['email']) ?> |
= e($r['device']) ?> | = e($r['place']) ?> = e($r['ip']) ?> |
= e($r['detail']) ?> |
Zeigt die letzten 300 Einträge. Einträge werden nach = login_guard_retention_days() ?> Tagen automatisch gelöscht.