Files
deskhub/DeskHub-Webseite/staff/roles.php
T
2026-10-16 19:12:21 +00:00

199 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/../includes/bootstrap.php';
require_once __DIR__ . '/_ui.php';
$staff = require_admin_or_permission('manage_roles');
$pdo = get_db();
$ticketPermLabels = [
'reply_ticket' => 'Tickets beantworten',
'close_ticket' => 'Tickets schließen/lösen',
'delete_ticket' => 'Tickets löschen',
'transfer_ticket' => 'Tickets übertragen (Abteilung ändern)',
'post_note' => 'Interne Notizen schreiben',
'assign_ticket' => 'Tickets zuweisen (Mitarbeiter/Team)',
'manage_canned' => 'Textbausteine verwalten',
'view_reports' => 'Berichte einsehen',
'manage_kb' => 'Wissensdatenbank verwalten',
'create_ticket' => 'Tickets im Namen von Kunden erstellen',
];
// Feinkörnige Adminportal-Rechte ("Co-Admin") – siehe admin_section_permissions() in functions.php.
// manage_kb steckt bewusst nur oben bei den Ticket-Rechten, nicht doppelt hier.
$adminPermLabels = admin_section_permissions();
unset($adminPermLabels['manage_kb']);
$permLabels = array_merge($ticketPermLabels, $adminPermLabels);
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
if ($action === 'create' || $action === 'update') {
$id = (int) ($_POST['id'] ?? 0);
$name = trim($_POST['name'] ?? '');
$isActive = ($_POST['status'] ?? 'active') === 'active' ? 1 : 0;
$notes = trim($_POST['notes'] ?? '');
if ($name === '') $errors[] = 'Bitte einen Namen angeben.';
$dup = $pdo->prepare('SELECT COUNT(*) FROM roles WHERE LOWER(name) = LOWER(?) AND id <> ?');
$dup->execute([$name, $id]);
if ($dup->fetchColumn() > 0) $errors[] = 'Eine Rolle mit diesem Namen existiert bereits.';
if (!$errors) {
$perms = [];
foreach (array_keys($permLabels) as $p) {
$perms[$p] = !empty($_POST['perm_' . $p]);
}
$json = json_encode($perms);
if ($action === 'create') {
$pdo->prepare('INSERT INTO roles (name, permissions, is_active, notes, created_at, updated_at) VALUES (?,?,?,?,?,?)')
->execute([$name, $json, $isActive, $notes ?: null, db_now(), db_now()]);
audit_log($staff['id'], "Rolle erstellt: {$name}");
flash('success', 'Rolle erstellt.');
} else {
$pdo->prepare('UPDATE roles SET name=?, permissions=?, is_active=?, notes=?, updated_at=? WHERE id=?')
->execute([$name, $json, $isActive, $notes ?: null, db_now(), $id]);
audit_log($staff['id'], "Rolle aktualisiert: {$name}");
flash('success', 'Änderungen gespeichert.');
}
redirect('/staff/roles.php');
}
}
if ($action === 'delete') {
$id = (int) $_POST['id'];
// Mitarbeiter und Abteilungszugriffe auf die Hauptrolle zurücksetzen
$pdo->prepare('UPDATE staff SET role_id = NULL WHERE role_id = ?')->execute([$id]);
$pdo->prepare('UPDATE staff_department SET role_id = NULL WHERE role_id = ?')->execute([$id]);
$pdo->prepare('DELETE FROM roles WHERE id = ?')->execute([$id]);
audit_log($staff['id'], "Rolle gelöscht: #{$id}");
flash('success', 'Rolle gelöscht.');
redirect('/staff/roles.php');
}
}
$isNew = isset($_GET['new']);
$editId = (int) ($_GET['edit'] ?? 0);
$showForm = $isNew || $editId || ($errors && in_array($_POST['action'] ?? '', ['create', 'update'], true));
$roles = $pdo->query(
'SELECT r.*, (SELECT COUNT(*) FROM staff s WHERE s.role_id = r.id) + (SELECT COUNT(*) FROM staff_department sd WHERE sd.role_id = r.id) AS staff_count
FROM roles r ORDER BY r.name'
)->fetchAll();
$editRole = null;
$editPerms = array_fill_keys(array_keys($permLabels), false);
if ($editId) {
$es = $pdo->prepare('SELECT * FROM roles WHERE id = ?'); $es->execute([$editId]);
$editRole = $es->fetch() ?: null;
if ($editRole) $editPerms = array_merge($editPerms, json_decode($editRole['permissions'] ?? '{}', true) ?? []);
}
if ($_POST && $errors) foreach (array_keys($permLabels) as $p) $editPerms[$p] = !empty($_POST['perm_' . $p]);
$pageTitle = 'Rollen'; $activePage = 'roles';
require __DIR__ . '/_header.php';
?>
<?php foreach ($errors as $err): ?><div class="flash error"><?= e($err) ?></div><?php endforeach; ?>
<?php if ($showForm): ?>
<?php
$f = fn(string $k, $default = '') => $_POST[$k] ?? $default;
$v = fn(string $k, string $col, $default = '') => $f($k, $editRole[$col] ?? $default);
$curActive = $_POST ? (($_POST['status'] ?? 'active') === 'active') : (bool) ($editRole['is_active'] ?? 1);
?>
<h1>
<?= $editRole ? 'Rolle aktualisieren' : 'Neue Rolle' ?>
<?php if ($editRole): ?><span class="muted" style="font-size:1rem;font-weight:400">— <?= e($editRole['name']) ?></span><?php endif; ?>
</h1>
<form method="post" class="card" style="padding:0">
<?= csrf_field() ?>
<input type="hidden" name="action" value="<?= $editRole ? 'update' : 'create' ?>">
<?php if ($editRole): ?><input type="hidden" name="id" value="<?= (int) $editRole['id'] ?>"><?php endif; ?>
<?php ui_tab_bar(['role' => 'Rolle', 'perms' => 'Berechtigungen']); ?>
<div class="tab-pane" data-pane="role" style="padding:16px 20px">
<h3 style="margin-top:0">Rolleninformationen</h3>
<label for="name">Name *</label>
<input type="text" id="name" name="name" value="<?= e($v('name', 'name')) ?>" placeholder="z. B. Nur-Antwort" required>
<?php ui_status_radios($curActive); ?>
<p class="muted" style="font-size:.78rem;margin-top:-6px">Eine deaktivierte Rolle wird ignoriert; betroffene Mitarbeiter haben dann die Standard-Mitarbeiterrechte.</p>
<h3>Administratornotizen <span class="muted" style="font-weight:400;font-size:.85rem">– Interne Notizen, sichtbar für alle Administratoren</span></h3>
<textarea name="notes" rows="6"><?= e($v('notes', 'notes')) ?></textarea>
</div>
<div class="tab-pane" data-pane="perms" style="padding:16px 20px;display:none">
<p class="muted" style="margin-top:0">Administratoren haben immer alle Rechte. Die Rechte einer Rolle gelten für Mitarbeiter mit dieser Rolle – je Abteilung kann ein Mitarbeiter eine andere Rolle haben (Mitarbeiter → Zugang).</p>
<h4 style="border-bottom:1px dotted var(--border);padding-bottom:4px">Tickets</h4>
<div style="columns:2;column-gap:24px">
<?php foreach ($ticketPermLabels as $key => $label): ?>
<label style="display:flex;align-items:center;gap:8px;padding:4px 0;font-weight:400;cursor:pointer;break-inside:avoid">
<input type="checkbox" name="perm_<?= $key ?>" style="width:auto" <?= ($editPerms[$key] ?? false) ? 'checked' : '' ?>> <?= e($label) ?>
</label>
<?php endforeach; ?>
</div>
<h4 style="border-bottom:1px dotted var(--border);padding-bottom:4px;margin-top:20px">Adminportal-Bereiche („Co-Admin“)</h4>
<div style="columns:2;column-gap:24px">
<?php foreach ($adminPermLabels as $key => $label): ?>
<label style="display:flex;align-items:center;gap:8px;padding:4px 0;font-weight:400;cursor:pointer;break-inside:avoid">
<input type="checkbox" name="perm_<?= $key ?>" style="width:auto" <?= ($editPerms[$key] ?? false) ? 'checked' : '' ?>> <?= e($label) ?>
</label>
<?php endforeach; ?>
</div>
</div>
<div class="btn-row" style="padding:0 20px 18px">
<button type="submit" class="btn"><?= $editRole ? 'Änderungen speichern' : 'Rolle erstellen' ?></button>
<a href="/staff/roles.php" class="btn secondary">Abbrechen</a>
</div>
</form>
<?php ui_tab_assets('role'); ?>
<?php else: ?>
<div style="display:flex;justify-content:space-between;align-items:center;gap:12px">
<h1 style="margin:0">Rollen</h1>
<a href="/staff/roles.php?new=1" class="btn">Neue Rolle hinzufügen</a>
</div>
<p class="muted">Benutzerdefinierte Berechtigungssets für Mitarbeiter. Ohne Rolle gelten die Standard-Mitarbeiterrechte.</p>
<div class="card">
<?php $defaults = default_permissions('agent'); ?>
<details>
<summary style="cursor:pointer;font-weight:600">Standard-Mitarbeiterrechte (ohne eigene Rolle)</summary>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-top:10px">
<?php foreach ($permLabels as $key => $label): ?>
<div style="font-size:.82rem;color:<?= ($defaults[$key] ?? false) ? 'var(--success)' : 'var(--muted)' ?>"><?= ($defaults[$key] ?? false) ? '✓' : '✕' ?> <?= e($label) ?></div>
<?php endforeach; ?>
</div>
</details>
</div>
<div class="card">
<table>
<thead><tr><th>Rollenname</th><th>Status</th><th style="text-align:center">Zugewiesen</th><th>Erstellt</th><th>Zuletzt aktualisiert</th><th></th></tr></thead>
<tbody>
<?php foreach ($roles as $r): ?>
<tr>
<td><a href="/staff/roles.php?edit=<?= (int) $r['id'] ?>"><?= e($r['name']) ?></a></td>
<td><strong><?= ($r['is_active'] ?? 1) ? 'Aktiv' : 'Deaktiviert' ?></strong></td>
<td style="text-align:center"><?= (int) $r['staff_count'] ?></td>
<td class="muted" style="font-size:.82rem"><?= e(ui_date($r['created_at'] ?? null)) ?></td>
<td class="muted" style="font-size:.82rem"><?= e(ui_date($r['updated_at'] ?? null)) ?></td>
<td style="white-space:nowrap">
<a href="/staff/roles.php?edit=<?= (int) $r['id'] ?>">Bearbeiten</a> ·
<form method="post" style="display:inline" onsubmit="return confirm('Rolle löschen? Zugeordnete Mitarbeiter erhalten wieder ihre Hauptrolle bzw. die Standardrechte.')">
<?= csrf_field() ?>
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= (int) $r['id'] ?>">
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.9rem">Löschen</button>
</form>
</td>
</tr>
<?php endforeach; ?>
<?php if (!$roles): ?><tr><td colspan="6" class="muted">Noch keine benutzerdefinierten Rollen angelegt.</td></tr><?php endif; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php require __DIR__ . '/_footer.php'; ?>