77 lines
4.4 KiB
PHP
77 lines
4.4 KiB
PHP
<?php
|
|
/**
|
|
* „Von allen Geräten abmelden“: beendet alle Anmeldungen eines Mitarbeiters auf einmal.
|
|
* - Browser-Sitzungen (current_staff() prüft den Zeitpunkt „login_guard_revoke_<id>“, siehe includes/login_guard.php)
|
|
* - Anmeldungen der Apps (Android, Windows-Programm, Chrome-Erweiterung): ihre Tokens werden gelöscht, die Programme fragen danach neu nach der Anmeldung
|
|
* - Push: Browser-Abonnements und Android-Geräte, damit ein verlorenes Gerät keine Benachrichtigungen mehr bekommt
|
|
* - Ticket-Sperren des Mitarbeiters und laufende Zeiterfassung
|
|
* Das Passwort bleibt unverändert; wer es zusätzlich ändern will, tut das im Profil oder über „Das war ich nicht“.
|
|
*/
|
|
|
|
/**
|
|
* @param bool $keepCurrentSession true = die Sitzung, in der das gerade geschieht, bleibt angemeldet (nur bei eigener Abmeldung sinnvoll)
|
|
* @return array{at:int,apps:int,browsers:int,devices:int,locks:int}
|
|
*/
|
|
function staff_sign_out_everywhere(PDO $pdo, int $staffId, ?int $byStaffId = null, bool $keepCurrentSession = false): array
|
|
{
|
|
$st = $pdo->prepare('SELECT id, name, email FROM staff WHERE id = ?');
|
|
$st->execute([$staffId]);
|
|
$staff = $st->fetch();
|
|
$res = ['at' => 0, 'apps' => 0, 'browsers' => 0, 'devices' => 0, 'locks' => 0];
|
|
if (!$staff) return $res;
|
|
|
|
$count = function (string $table) use ($pdo, $staffId): int {
|
|
try {
|
|
$c = $pdo->prepare("SELECT COUNT(*) FROM {$table} WHERE staff_id = ?");
|
|
$c->execute([$staffId]);
|
|
return (int) $c->fetchColumn();
|
|
} catch (Throwable $e) {
|
|
return 0;
|
|
}
|
|
};
|
|
$res['apps'] = $count('mobile_api_tokens');
|
|
$res['browsers'] = $count('push_subscriptions');
|
|
$res['devices'] = $count('push_devices');
|
|
|
|
$at = time();
|
|
$res['at'] = $at;
|
|
set_setting('login_guard_revoke_' . $staffId, (string) $at);
|
|
foreach (['mobile_api_tokens', 'push_subscriptions', 'push_devices'] as $table) {
|
|
try { $pdo->prepare("DELETE FROM {$table} WHERE staff_id = ?")->execute([$staffId]); } catch (Throwable $e) { error_log('signout ' . $table . ': ' . $e->getMessage()); }
|
|
}
|
|
try {
|
|
$l = $pdo->prepare('UPDATE tickets SET locked_by = NULL, locked_at = NULL, updated_at = updated_at WHERE locked_by = ?');
|
|
$l->execute([$staffId]);
|
|
$res['locks'] = $l->rowCount();
|
|
} catch (Throwable $e) {
|
|
error_log('signout locks: ' . $e->getMessage());
|
|
}
|
|
if (function_exists('finalize_all_sessions_for_staff')) {
|
|
try { finalize_all_sessions_for_staff($pdo, $staffId); } catch (Throwable $e) { error_log('signout time: ' . $e->getMessage()); }
|
|
}
|
|
|
|
// Die eigene Sitzung bleibt, wenn gewünscht: Ihr Anmeldezeitpunkt liegt dann hinter dem Zeitpunkt des Widerrufs
|
|
if ($keepCurrentSession && $byStaffId === $staffId && PHP_SAPI !== 'cli' && session_status() === PHP_SESSION_ACTIVE) {
|
|
$_SESSION['staff_login_at'] = $at + 1;
|
|
}
|
|
|
|
$self = $byStaffId === null || $byStaffId === $staffId;
|
|
$detail = $self ? 'Von allen Geräten abgemeldet (eigene Veranlassung)' : 'Von allen Geräten abgemeldet durch Administrator #' . (int) $byStaffId;
|
|
try { login_guard_record($pdo, 'signout', $staffId, (string) $staff['email'], 'web', $detail); } catch (Throwable $e) { error_log('signout log: ' . $e->getMessage()); }
|
|
audit_log($byStaffId ?? $staffId, "Mitarbeiter #{$staffId} von allen Geräten abgemeldet ({$res['apps']} App-Anmeldungen, {$res['browsers']} Browser-Push, {$res['devices']} App-Geräte)");
|
|
|
|
if (!$self && trim((string) $staff['email']) !== '') {
|
|
send_mail((string) $staff['email'], 'Sie wurden von allen Geräten abgemeldet',
|
|
email_wrap('<h2 style="margin:0 0 14px;color:#0f172a;font-size:22px;line-height:1.3;font-weight:700;font-family:Segoe UI,Arial,sans-serif;">Von allen Geräten abgemeldet</h2><p style="margin:0;color:#334155">Ein Administrator hat Ihre Anmeldungen in DeskHub beendet. Bitte melden Sie sich neu an. Haben Sie das nicht erwartet, wenden Sie sich an Ihre Administration.</p>'));
|
|
}
|
|
return $res;
|
|
}
|
|
|
|
/** Aktive App-Anmeldungen eines Mitarbeiters (Android, Windows, Chrome) für die Anzeige. @return list<array<string,mixed>> */
|
|
function staff_app_logins(PDO $pdo, int $staffId): array
|
|
{
|
|
$s = $pdo->prepare('SELECT device_name, last_used_at, created_at FROM mobile_api_tokens WHERE staff_id = ? AND revoked_at IS NULL AND expires_at > ? ORDER BY COALESCE(last_used_at, created_at) DESC');
|
|
$s->execute([$staffId, db_now()]);
|
|
return $s->fetchAll();
|
|
}
|