Files
deskhub/DeskHub-Webseite/staff/plugin_login.php
T
2026-10-30 21:50:04 +00:00

92 lines
4.7 KiB
PHP

<?php
/**
* staff/plugin_login.php
*
* Gemeinsamer Einstieg für Anmeldedienste, die als Plugin kommen (zum Beispiel authentik über OpenID Connect): GET ?p=<Plugin>&e=<Name>.
* Das Plugin muss die Berechtigung "auth.login" haben und die Adresse mit plugin_register_login() anmelden. Hier steht nur, was für alle gleich ist:
* Ablauf der Antwort (Weiterleitung, Anmeldung, Fehler), Begrenzung der Aufrufe und der Eintrag im Admin-Protokoll. Wer sich anmelden darf,
* prüft das Plugin; DeskHub meldet nur aktive Mitarbeiterkonten an.
*
* Schon angemeldete Mitarbeiter kommen nur zu Adressen, die das Plugin ausdrücklich dafür angemeldet hat (zum Beispiel „Konto verknüpfen“);
* dabei kann nie ein anderer Mitarbeiter angemeldet werden.
*/
require_once __DIR__ . '/../includes/bootstrap.php';
header('Cache-Control: no-store');
header('Referrer-Policy: no-referrer');
/** Nur Ziele im Mitarbeiterbereich: beginnt mit /staff/, keine Doppel-Schrägstriche, keine Zeilenumbrüche. */
function plugin_login_local_ok(string $path): bool
{
return $path !== '' && strlen($path) <= 300 && str_starts_with($path, '/staff/') && !str_contains($path, '//') && !preg_match('/[\x00-\x20\\\\]/', $path);
}
/** Zurück mit Fehlermeldung: angemeldet in den Mitarbeiterbereich, sonst zur Anmeldeseite. */
function plugin_login_back(string $message, ?string $back = null): never
{
flash('error', $message);
if (current_staff()) redirect($back !== null && plugin_login_local_ok($back) ? $back : '/staff/reports.php');
redirect('/staff/login.php');
}
$staffNow = current_staff();
$slug = (string) ($_GET['p'] ?? '');
$endpoint = (string) ($_GET['e'] ?? '');
$handler = plugin_state()['logins'][$slug][$endpoint] ?? null;
if (!is_callable($handler)) {
if ($staffNow) redirect('/staff/reports.php');
http_response_code(404);
echo 'Unbekannte Anmelde-Adresse.';
exit;
}
$allowedLoggedIn = !empty(plugin_state()['login_loggedin'][$slug][$endpoint]);
if ($staffNow && !$allowedLoggedIn) redirect('/staff/reports.php');
if (!rate_limit_check('plugin_login', client_ip(), 40, 15)) plugin_login_back('Zu viele Anmeldeversuche. Bitte versuchen Sie es in einigen Minuten erneut.');
$request = ['query' => $_GET, 'ip' => client_ip()];
if ($staffNow) $request['staff'] = $staffNow;
$result = plugin_guard($slug, fn() => $handler($request), null);
$back = is_array($result) && isset($result['back']) ? (string) $result['back'] : null;
if (!is_array($result)) plugin_login_back('Die Anmeldung ist gerade nicht möglich. Bitte versuchen Sie es später noch einmal oder melden Sie sich mit E-Mail und Passwort an.');
// Weiter zum Anmeldedienst: nur https (oder http zu localhost zum Testen), keine Zeilenumbrüche
if (!empty($result['redirect'])) {
$url = (string) $result['redirect'];
if (!plugin_login_external_url_ok($url)) plugin_login_back('Die Adresse des Anmeldedienstes ist ungültig.', $back);
header('Location: ' . $url, true, 302);
exit;
}
// Kunden: Die gemeinsame Rückkehr-Adresse darf auch eine Kunden-Anmeldung beenden (Berechtigung auth.customer, prüft plugin_customer_login_finish)
if (!$staffNow && (isset($result['customer']) || ($result['audience'] ?? '') === 'customer')) {
if (!empty($result['customer']) && is_array($result['customer'])) plugin_customer_login_finish($slug, $result['customer']);
flash('error', mb_substr((string) ($result['error'] ?? 'Die Anmeldung wurde abgelehnt.'), 0, 300));
redirect('/login.php');
}
// Angemeldete Mitarbeiter: zurück in den Mitarbeiterbereich (mit Hinweis), nie ein anderer Mitarbeiter
if ($staffNow) {
if (!empty($result['staff_id'])) plugin_login_back('Dieser Schritt darf keinen anderen Mitarbeiter anmelden.', $back);
if (!empty($result['local'])) {
$local = (string) $result['local'];
if (!plugin_login_local_ok($local)) $local = '/staff/reports.php';
if (!empty($result['notice'])) flash('success', mb_substr((string) $result['notice'], 0, 300));
redirect($local);
}
plugin_login_back(mb_substr((string) ($result['error'] ?? 'Der Vorgang wurde abgelehnt.'), 0, 300), $back);
}
// Geprüfter Mitarbeiter: anmelden
if (!empty($result['staff_id'])) {
$stmt = get_db()->prepare('SELECT * FROM staff WHERE id = ? AND is_active = 1');
$stmt->execute([(int) $result['staff_id']]);
$staff = $stmt->fetch();
if (!$staff) plugin_login_back('Dieses Konto ist in DeskHub nicht aktiv.');
$via = mb_substr((string) ($result['via'] ?? $slug), 0, 60);
staff_login($staff);
audit_log((int) $staff['id'], 'Anmeldung über ' . $via . ' (Plugin ' . $slug . ')');
redirect('/staff/reports.php');
}
plugin_login_back(mb_substr((string) ($result['error'] ?? 'Die Anmeldung wurde abgelehnt.'), 0, 300));