92 lines
4.7 KiB
PHP
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));
|