129 lines
9.9 KiB
PHP
129 lines
9.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Prüft den Rechte-Katalog (includes/permissions.php) und has_permission(): vollständig und eindeutig, Standardwerte, Rückfall für Rechte, die in älteren
|
|
* Rollen fehlen, Rolle pro Abteilung, deaktivierte Rollen und die Rollen-Vorlagen.
|
|
*/
|
|
|
|
putenv('DESKHUB_TESTING=1');
|
|
putenv('DESKHUB_SQLITE_PATH=:memory:');
|
|
require_once dirname(__DIR__) . '/includes/bootstrap.php';
|
|
|
|
$failures = [];
|
|
$total = 0;
|
|
$check = function (bool $ok, string $what) use (&$failures, &$total): void {
|
|
$total++;
|
|
if (!$ok) $failures[] = $what;
|
|
};
|
|
|
|
// ── Katalog ────────────────────────────────────────────────────────────────────
|
|
$catalog = permission_catalog();
|
|
$all = [];
|
|
$dupes = [];
|
|
foreach ($catalog as $g) {
|
|
$check(!empty($g['title']) && !empty($g['items']), 'Gruppe hat Titel und Rechte');
|
|
foreach ($g['items'] as $k => $i) {
|
|
if (isset($all[$k])) $dupes[] = $k;
|
|
$all[$k] = $i;
|
|
$check(preg_match('/^[a-z_]+$/', $k) === 1 && $i['label'] !== '' && $i['hint'] !== '' && is_bool($i['agent']) && is_bool($i['area']), "Recht {$k}: Schlüssel, Beschriftung, Hinweis und Flags");
|
|
}
|
|
}
|
|
$check($dupes === [], 'Kein Recht kommt doppelt vor: ' . implode(',', $dupes));
|
|
$check(array_keys(permission_labels()) === array_keys($all), 'permission_labels() entspricht dem Katalog');
|
|
|
|
// Alle bisherigen Rechte gibt es weiterhin (gespeicherte Rollen bleiben gültig)
|
|
$old = ['reply_ticket', 'close_ticket', 'delete_ticket', 'transfer_ticket', 'post_note', 'assign_ticket', 'manage_canned', 'view_reports', 'manage_kb', 'create_ticket',
|
|
'manage_departments', 'manage_priorities', 'manage_help_topics', 'manage_email_addresses', 'manage_email_templates', 'manage_organizations', 'manage_teams', 'manage_roles',
|
|
'manage_staff', 'view_audit_log', 'manage_escalations', 'view_time_entries', 'manage_business_hours', 'manage_assistant'];
|
|
$check(array_diff($old, array_keys($all)) === [], 'Alle bisherigen Rechte sind im Katalog');
|
|
$check(count($all) >= 40, 'Der Katalog hat die neuen Rechte (' . count($all) . ')');
|
|
|
|
// Neue Rechte, die es bisher gar nicht gab
|
|
foreach (['merge_split_ticket', 'link_tickets', 'manage_banlist', 'export_tickets', 'fetch_mail', 'share_views', 'schedule_reports', 'view_customers', 'manage_customers', 'manage_custom_fields',
|
|
'manage_ticket_templates', 'manage_automation', 'manage_site_pages', 'manage_languages', 'manage_status_page', 'view_mail_queue', 'view_login_guard', 'manage_problems', 'manage_availability', 'view_help'] as $k) {
|
|
$check(isset($all[$k]), "Neues Recht {$k} vorhanden");
|
|
}
|
|
|
|
// Adminportal-Bereiche
|
|
$areas = admin_section_permissions();
|
|
$check(isset($areas['manage_canned'], $areas['manage_kb'], $areas['view_help'], $areas['view_login_guard']) && !isset($areas['reply_ticket'], $areas['manage_banlist'], $areas['export_tickets']), 'admin_section_permissions(): Bereiche ja, Ticket-Rechte nein');
|
|
foreach (['settings', 'backup', 'update', 'plugins', 'api_keys', 'webhooks', 'import', 'security_check', 'passkeys'] as $needle) {
|
|
$hit = array_filter(array_keys($all), fn($k) => str_contains($k, $needle));
|
|
$check($hit === [], "Nicht delegierbar: kein Recht für {$needle}");
|
|
}
|
|
|
|
// ── Standardwerte ──────────────────────────────────────────────────────────────
|
|
$adm = default_permissions('admin');
|
|
$agt = default_permissions('agent');
|
|
$check(count(array_filter($adm)) === count($all), 'Administrator: alle Rechte');
|
|
foreach (['reply_ticket', 'close_ticket', 'transfer_ticket', 'post_note', 'assign_ticket', 'create_ticket', 'view_reports', 'merge_split_ticket', 'link_tickets', 'manage_banlist', 'fetch_mail', 'share_views', 'schedule_reports', 'view_customers'] as $k) {
|
|
$check($agt[$k] === true, "Standard-Mitarbeiter darf weiterhin: {$k}");
|
|
}
|
|
foreach (['delete_ticket', 'export_tickets'] as $k) $check($agt[$k] === false, "Standard-Mitarbeiter darf nicht: {$k}");
|
|
foreach ($areas as $k => $_l) $check($agt[$k] === false, "Adminportal-Bereich standardmäßig aus: {$k}");
|
|
|
|
// ── has_permission ─────────────────────────────────────────────────────────────
|
|
$pdo = get_db();
|
|
$now = date('Y-m-d H:i:s');
|
|
$dept = (int) $pdo->query('SELECT id FROM departments ORDER BY id LIMIT 1')->fetchColumn();
|
|
$pdo->prepare('INSERT INTO departments (name, email, is_active, created_at) VALUES (?,?,1,?)')->execute(['Zweite', 'zweite@test.de', $now]);
|
|
$dept2 = (int) $pdo->lastInsertId();
|
|
$pdo->exec('DELETE FROM staff');
|
|
$mkRole = function (string $name, array $perms, int $active = 1) use ($pdo, $now): int {
|
|
$pdo->prepare('INSERT INTO roles (name, permissions, is_active, created_at, updated_at) VALUES (?,?,?,?,?)')->execute([$name, json_encode($perms), $active, $now, $now]);
|
|
return (int) $pdo->lastInsertId();
|
|
};
|
|
$mkStaff = function (string $mail, string $role, ?int $roleId) use ($pdo, $dept, $now): array {
|
|
$pdo->prepare('INSERT INTO staff (name, email, password_hash, role, role_id, department_id, is_active, created_at) VALUES (?,?,?,?,?,?,1,?)')->execute([$mail, $mail . '@test.de', 'x', $role, $roleId, $dept, $now]);
|
|
return $pdo->query('SELECT * FROM staff WHERE id = ' . (int) $pdo->lastInsertId())->fetch();
|
|
};
|
|
$admin = $mkStaff('chef', 'admin', null);
|
|
$plain = $mkStaff('eva', 'agent', null);
|
|
$check(has_permission($admin, 'manage_staff') && has_permission($admin, 'gibt_es_nicht'), 'Administrator hat immer alles');
|
|
$check(has_permission($plain, 'reply_ticket') && has_permission($plain, 'merge_split_ticket') && !has_permission($plain, 'delete_ticket') && !has_permission($plain, 'manage_custom_fields'), 'Mitarbeiter ohne Rolle: Standardrechte');
|
|
$check(!has_permission($plain, 'gibt_es_nicht'), 'Unbekanntes Recht: nein');
|
|
|
|
// Alte Rolle (gespeichert vor den neuen Rechten): neue Rechte gelten mit dem Standardwert
|
|
$oldJson = array_fill_keys($old, false);
|
|
$oldJson['reply_ticket'] = true;
|
|
$oldJson['manage_departments'] = true;
|
|
$roleOld = $mkRole('Alt', $oldJson);
|
|
$s1 = $mkStaff('alt', 'agent', $roleOld);
|
|
$check(has_permission($s1, 'reply_ticket') && has_permission($s1, 'manage_departments') && !has_permission($s1, 'close_ticket'), 'Alte Rolle: gespeicherte Werte gelten (auch „aus“)');
|
|
$check(has_permission($s1, 'merge_split_ticket') && has_permission($s1, 'manage_banlist') && has_permission($s1, 'fetch_mail'), 'Alte Rolle: bisher offene Funktionen bleiben erlaubt (Standardwert)');
|
|
$check(!has_permission($s1, 'manage_custom_fields') && !has_permission($s1, 'view_help') && !has_permission($s1, 'export_tickets'), 'Alte Rolle: neue Adminbereiche bleiben aus');
|
|
// Altes Recht fehlt in einer gespeicherten Rolle: wie bisher „nein“
|
|
$roleGap = $mkRole('Lücke', ['reply_ticket' => true]);
|
|
$sg = $mkStaff('luecke', 'agent', $roleGap);
|
|
$check(has_permission($sg, 'reply_ticket') && !has_permission($sg, 'post_note') && !has_permission($sg, 'close_ticket'), 'Fehlendes altes Recht in einer Rolle: nein (wie bisher)');
|
|
$check(array_diff(permission_legacy_keys(), array_keys($all)) === [] && count(permission_legacy_keys()) === 24, 'Liste der alten Rechte ist vollständig');
|
|
$eff = permission_effective(['reply_ticket' => true]);
|
|
$check($eff['reply_ticket'] && !$eff['post_note'] && $eff['merge_split_ticket'] && !$eff['manage_custom_fields'] && count($eff) === count($all), 'permission_effective(): wie has_permission() für fehlende Rechte');
|
|
// Neue Rolle mit ausdrücklich „aus“
|
|
$roleNew = $mkRole('Neu', ['merge_split_ticket' => false, 'manage_custom_fields' => true]);
|
|
$s2 = $mkStaff('neu', 'agent', $roleNew);
|
|
$check(!has_permission($s2, 'merge_split_ticket') && has_permission($s2, 'manage_custom_fields'), 'Ausdrücklich gesetzte Werte schlagen den Standard');
|
|
// Deaktivierte Rolle
|
|
$roleOff = $mkRole('Aus', ['reply_ticket' => false, 'manage_custom_fields' => true], 0);
|
|
$s3 = $mkStaff('aus', 'agent', $roleOff);
|
|
$check(has_permission($s3, 'reply_ticket') && !has_permission($s3, 'manage_custom_fields'), 'Deaktivierte Rolle: Standardrechte');
|
|
// Rolle pro Abteilung
|
|
$pdo->prepare('INSERT INTO staff_department (staff_id, department_id, notify, role_id) VALUES (?,?,?,?)')->execute([$s1['id'], $dept2, 1, $roleNew]);
|
|
$check(has_permission($s1, 'manage_custom_fields', $dept2) && !has_permission($s1, 'manage_custom_fields', $dept), 'Rolle pro Abteilung gilt nur in dieser Abteilung');
|
|
|
|
// ── Vorlagen ───────────────────────────────────────────────────────────────────
|
|
$presets = permission_presets();
|
|
foreach ($presets as $key => [$name, $desc, $perms]) {
|
|
$check(array_keys($perms) === array_keys($all) || count(array_diff(array_keys($all), array_keys($perms))) === 0, "Vorlage {$key} nennt jedes Recht");
|
|
$check(array_diff(array_keys($perms), array_keys($all)) === [], "Vorlage {$key} nennt keine unbekannten Rechte");
|
|
}
|
|
$check($presets['mitarbeiter'][2] == $agt, 'Vorlage „Mitarbeiter“ entspricht den Standardrechten');
|
|
$check(!$presets['nur_lesen'][2]['reply_ticket'] && $presets['nur_lesen'][2]['view_customers'], 'Vorlage „Nur lesen“ darf nicht antworten');
|
|
$check($presets['teamleitung'][2]['delete_ticket'] && !$presets['teamleitung'][2]['manage_staff'], 'Vorlage „Teamleitung“: löschen ja, Mitarbeiter verwalten nein');
|
|
$check($presets['support_manager'][2]['manage_staff'] && !$presets['support_manager'][2]['manage_roles'], 'Vorlage „Support-Manager“: Mitarbeiter ja, Rollen nein');
|
|
|
|
echo $failures ? "FEHLGESCHLAGEN:\n - " . implode("\n - ", $failures) . "\n" : '';
|
|
echo "Rechte-Test: " . ($total - count($failures)) . " von {$total} Prüfungen in Ordnung.\n";
|
|
exit($failures ? 1 : 0);
|