85 lines
5.1 KiB
PHP
85 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* includes/web_handoff.php
|
|
*
|
|
* Übergabe von der App an die Webseite: Für alles, was nur am Bildschirm sinnvoll zu bedienen ist (Einstellungen, Assistent,
|
|
* Backup, Plugins, Webhooks …), öffnen Android- und Windows-App die passende Seite der Weboberfläche. Die App holt dafür eine
|
|
* einmalige Anmelde-Adresse (60 Sekunden gültig, nur einmal benutzbar); die Webseite prüft dann wie immer selbst die Rechte.
|
|
* Die App zeigt nur die Seiten, die der Mitarbeiter laut dieser Liste überhaupt öffnen darf.
|
|
*/
|
|
|
|
/**
|
|
* Seiten der Weboberfläche, die die Apps nicht selbst nachbauen.
|
|
*
|
|
* @return array<int,array{key:string,label:string,path:string,group:string}>
|
|
*/
|
|
function web_handoff_pages(array $staff): array
|
|
{
|
|
$isAdmin = ($staff['role'] ?? '') === 'admin';
|
|
$perm = fn(string $p): bool => $isAdmin || has_permission($staff, $p);
|
|
$all = [
|
|
// Alle Mitarbeiter
|
|
['mentions', 'Erwähnungen', '/staff/mentions.php', 'Allgemein', true],
|
|
['agent_directory', 'Mitarbeiterverzeichnis', '/staff/agent_directory.php', 'Allgemein', true],
|
|
// Mit Recht
|
|
['assistant', 'Digitaler Assistent (Antworten, Fragen-Log)', '/staff/assistant.php', 'Verwaltung', $perm('manage_assistant')],
|
|
['imap_accounts', 'Postfächer (E-Mail-Abruf)', '/staff/imap_accounts.php', 'Verwaltung', $perm('manage_email_addresses')],
|
|
// Nur Administratoren
|
|
['settings', 'Einstellungen', '/staff/settings.php', 'Verwaltung', $isAdmin],
|
|
['recurring_tickets', 'Wiederkehrende Tickets', '/staff/recurring_tickets.php', 'Verwaltung', $isAdmin],
|
|
['canned_responses', 'Textbausteine', '/staff/canned_responses.php', 'Verwaltung', $isAdmin],
|
|
['custom_fields', 'Ticket-Felder', '/staff/custom_fields.php', 'Verwaltung', $isAdmin],
|
|
['custom_lists', 'Benutzerdefinierte Listen', '/staff/custom_lists.php', 'Verwaltung', $isAdmin],
|
|
['site_pages', 'Seiten (Impressum, Datenschutz …)', '/staff/site_pages.php', 'Verwaltung', $isAdmin],
|
|
['webhooks', 'Webhooks', '/staff/webhooks.php', 'Verwaltung', $isAdmin],
|
|
['api_keys', 'API-Schlüssel', '/staff/api_keys.php', 'Verwaltung', $isAdmin],
|
|
['plugins', 'Plugins und Themes', '/staff/plugins.php', 'System', $isAdmin],
|
|
['backup', 'Backup', '/staff/backup.php', 'System', $isAdmin],
|
|
['update', 'System-Update', '/staff/update.php', 'System', $isAdmin],
|
|
['security_check', 'Sicherheitsprüfung', '/staff/security_check.php', 'System', $isAdmin],
|
|
['import_osticket', 'Import aus osTicket', '/staff/import_osticket.php', 'System', $isAdmin],
|
|
];
|
|
$out = [];
|
|
foreach ($all as [$key, $label, $path, $group, $allowed]) {
|
|
if ($allowed) $out[] = ['key' => $key, 'label' => $label, 'path' => $path, 'group' => $group];
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
/** Darf diese Adresse aus der App geöffnet werden? (eine Seite der Liste oder ein einzelnes Ticket) */
|
|
function web_handoff_path_allowed(array $staff, string $path): bool
|
|
{
|
|
if (preg_match('#^/staff/(ticket_view|ticket_print|ticket_split)\.php\?n=[A-Za-z0-9._-]{1,40}$#', $path)) return true;
|
|
foreach (web_handoff_pages($staff) as $p) if ($p['path'] === $path) return true;
|
|
return false;
|
|
}
|
|
|
|
/** Erzeugt die einmalige Anmelde-Adresse für die Seite $path. */
|
|
function web_handoff_create(PDO $pdo, array $staff, string $path): ?string
|
|
{
|
|
if (!web_handoff_path_allowed($staff, $path)) return null;
|
|
$token = bin2hex(random_bytes(32));
|
|
$now = db_now();
|
|
$pdo->prepare('DELETE FROM web_login_tokens WHERE expires_at < ?')->execute([date('Y-m-d H:i:s', time() - 3600)]);
|
|
$pdo->prepare('INSERT INTO web_login_tokens (staff_id, token_hash, path, created_at, expires_at) VALUES (?,?,?,?,?)')
|
|
->execute([(int) $staff['id'], hash('sha256', $token), $path, $now, date('Y-m-d H:i:s', time() + 60)]);
|
|
return rtrim(base_url(), '/') . '/staff/app_login.php?t=' . $token;
|
|
}
|
|
|
|
/** Löst die Anmelde-Adresse ein (einmalig). @return array{staff:array,path:string}|null */
|
|
function web_handoff_consume(PDO $pdo, string $token): ?array
|
|
{
|
|
if (!preg_match('/^[a-f0-9]{64}$/', $token)) return null;
|
|
$hash = hash('sha256', $token);
|
|
$upd = $pdo->prepare('UPDATE web_login_tokens SET used_at = ? WHERE token_hash = ? AND used_at IS NULL AND expires_at >= ?');
|
|
$upd->execute([db_now(), $hash, db_now()]);
|
|
if ($upd->rowCount() !== 1) return null; // schon benutzt, abgelaufen oder unbekannt
|
|
$row = $pdo->prepare('SELECT t.path AS handoff_path, s.* FROM web_login_tokens t JOIN staff s ON s.id = t.staff_id WHERE t.token_hash = ? AND s.is_active = 1');
|
|
$row->execute([$hash]);
|
|
$r = $row->fetch();
|
|
if (!$r) return null;
|
|
$path = (string) $r['handoff_path'];
|
|
unset($r['handoff_path']);
|
|
return ['staff' => $r, 'path' => $path];
|
|
}
|