PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); $currentUserId = (int)$_SESSION['user_id']; $loggedIn = true; $errors = []; $successMessage = ''; $pageTitle = 'Benutzerverwaltung'; $headerIntroPre = 'Administration'; $headerIntroTitle = 'Benutzerkonten verwalten'; $headerIntroSub = 'Konten freischalten, deaktivieren und Rollen verwalten'; function h(?string $value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); } function redirectToAdminUsers(): void { header('Location: admin_users.php'); exit; } function isPrivilegedRole(?string $role): bool { return isAdminLikeRole($role); } function ensureUserPagePermissionsTable(PDO $pdo): void { $pdo->exec(" CREATE TABLE IF NOT EXISTS `app_user_page_permissions` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `user_id` bigint(20) unsigned NOT NULL, `page_key` varchar(100) NOT NULL, `created_at` datetime NOT NULL DEFAULT current_timestamp(), `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`id`), UNIQUE KEY `uq_app_user_page_permissions_user_page` (`user_id`, `page_key`), KEY `idx_app_user_page_permissions_page_key` (`page_key`), CONSTRAINT `fk_app_user_page_permissions_user_id` FOREIGN KEY (`user_id`) REFERENCES `app_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); } function sendActivationNotification(string $username, string $email, ?string $displayName): void { $subject = 'Dein SkyView-Konto wurde freigeschaltet'; $recipientName = $displayName !== null && $displayName !== '' ? $displayName : $username; $messageLines = [ 'Hallo ' . $recipientName . ',', '', 'dein Benutzerkonto bei SkyView wurde soeben freigeschaltet.', 'Du kannst dich ab sofort mit deinen Zugangsdaten anmelden.', '', 'Benutzername: ' . $username, '', 'Viele Grüße', 'Astronomiemuseum der Sternwarte Sonneberg', ]; $headers = [ 'MIME-Version: 1.0', 'Content-Type: text/plain; charset=UTF-8', 'From: noreply@astronomiemuseum.de', 'Reply-To: tm@astronomiemuseum.de', ]; try { mail( $email, $subject, implode(PHP_EOL, $messageLines), implode("\r\n", $headers) ); } catch (Throwable $e) { error_log('Activation notification mail failed: ' . $e->getMessage()); } } if (empty($_SESSION['admin_users_csrf'])) { $_SESSION['admin_users_csrf'] = bin2hex(random_bytes(16)); } $stmtCurrentUser = $pdo->prepare(" SELECT `id`, `username`, `display_name`, `role`, `is_active` FROM `app_users` WHERE `id` = :id LIMIT 1 "); $stmtCurrentUser->execute([':id' => $currentUserId]); $currentUser = $stmtCurrentUser->fetch(); if ( !$currentUser || !isAdminLikeRole((string) $currentUser['role']) || (int)$currentUser['is_active'] !== 1 ) { $_SESSION = []; session_destroy(); header('Location: login.php'); exit; } $currentUserIsMaster = isMasterRole((string) ($currentUser['role'] ?? '')); $manageablePages = manageablePublicPages(); if ($currentUserIsMaster) { ensureUserPagePermissionsTable($pdo); } if (isset($_SESSION['admin_users_flash_success'])) { $successMessage = (string)$_SESSION['admin_users_flash_success']; unset($_SESSION['admin_users_flash_success']); } if (isset($_SESSION['admin_users_flash_errors']) && is_array($_SESSION['admin_users_flash_errors'])) { $errors = array_values($_SESSION['admin_users_flash_errors']); unset($_SESSION['admin_users_flash_errors']); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = $_POST['action'] ?? ''; $targetUserId = (int)($_POST['user_id'] ?? 0); $csrfToken = (string)($_POST['csrf_token'] ?? ''); if (!hash_equals($_SESSION['admin_users_csrf'], $csrfToken)) { $errors[] = 'Die Sitzung ist abgelaufen. Bitte die Seite neu laden.'; } $stmtTargetUser = $pdo->prepare(" SELECT `id`, `username`, `email`, `display_name`, `role`, `is_active` FROM `app_users` WHERE `id` = :id LIMIT 1 "); $targetUser = null; if ($targetUserId > 0) { $stmtTargetUser->execute([':id' => $targetUserId]); $targetUser = $stmtTargetUser->fetch(); } if ($action === 'update_page_permissions' && !$currentUserIsMaster) { $errors[] = 'Nur ein Master-Benutzer darf Seitenfreigaben verwalten.'; } if (!$targetUser) { $errors[] = 'Das ausgewählte Benutzerkonto wurde nicht gefunden.'; } if ($targetUser && $targetUserId === $currentUserId && in_array($action, ['deactivate_user', 'change_role', 'delete_user'], true)) { $errors[] = 'Das eigene Administrationskonto kann hier nicht deaktiviert, gelöscht oder umgestellt werden.'; } $currentUserIsMaster = isMasterRole((string) ($currentUser['role'] ?? '')); $targetUserIsMaster = $targetUser ? isMasterRole((string) ($targetUser['role'] ?? '')) : false; $requestedRole = (string) ($_POST['role'] ?? 'user'); if (empty($errors) && $targetUser) { $stmtActiveAdminCount = $pdo->query(" SELECT COUNT(*) FROM `app_users` WHERE `role` IN ('admin', 'master') AND `is_active` = 1 "); $activeAdminCount = (int)$stmtActiveAdminCount->fetchColumn(); $stmtMasterCount = $pdo->query(" SELECT COUNT(*) FROM `app_users` WHERE `role` = 'master' "); $masterCount = (int)$stmtMasterCount->fetchColumn(); if ( !$currentUserIsMaster && $targetUserIsMaster ) { $errors[] = 'Nur ein Master-Benutzer darf die Rolle master vergeben oder ändern.'; } if ( !$currentUserIsMaster && $requestedRole === 'master' && $masterCount > 0 ) { $errors[] = 'Nur ein Master-Benutzer darf die Rolle master vergeben oder ändern.'; } if ( $action === 'deactivate_user' && isPrivilegedRole((string) $targetUser['role']) && (int)$targetUser['is_active'] === 1 && $activeAdminCount <= 1 ) { $errors[] = 'Der letzte aktive privilegierte Benutzer kann nicht deaktiviert werden.'; } if ( $action === 'change_role' && isPrivilegedRole((string) $targetUser['role']) && !isPrivilegedRole($requestedRole) && (int)$targetUser['is_active'] === 1 && $activeAdminCount <= 1 ) { $errors[] = 'Der letzte aktive privilegierte Benutzer kann nicht zur Benutzerrolle herabgestuft werden.'; } if ( $action === 'delete_user' && isPrivilegedRole((string) $targetUser['role']) && (int)$targetUser['is_active'] === 1 && $activeAdminCount <= 1 ) { $errors[] = 'Der letzte aktive privilegierte Benutzer kann nicht gelöscht werden.'; } } if (empty($errors) && $targetUser) { if ($action === 'activate_user') { $notifyUser = (int)($_POST['notify_user'] ?? 0) === 1; $stmtUpdate = $pdo->prepare(" UPDATE `app_users` SET `is_active` = 1, `updated_at` = NOW() WHERE `id` = :id "); $stmtUpdate->execute([':id' => $targetUserId]); if ($notifyUser) { sendActivationNotification( $targetUser['username'], $targetUser['email'], $targetUser['display_name'] ); $_SESSION['admin_users_flash_success'] = 'Benutzerkonto wurde freigeschaltet und der Benutzer wurde benachrichtigt.'; } else { $_SESSION['admin_users_flash_success'] = 'Benutzerkonto wurde freigeschaltet.'; } redirectToAdminUsers(); } if ($action === 'deactivate_user') { $stmtUpdate = $pdo->prepare(" UPDATE `app_users` SET `is_active` = 0, `updated_at` = NOW() WHERE `id` = :id "); $stmtUpdate->execute([':id' => $targetUserId]); $_SESSION['admin_users_flash_success'] = 'Benutzerkonto wurde deaktiviert.'; redirectToAdminUsers(); } if ($action === 'change_role') { $newRole = $requestedRole; if (!in_array($newRole, ['user', 'admin', 'master'], true)) { $errors[] = 'Die gewählte Rolle ist ungültig.'; } else { $stmtUpdate = $pdo->prepare(" UPDATE `app_users` SET `role` = :role, `updated_at` = NOW() WHERE `id` = :id "); $stmtUpdate->execute([ ':role' => $newRole, ':id' => $targetUserId, ]); $_SESSION['admin_users_flash_success'] = 'Die Benutzerrolle wurde aktualisiert.'; redirectToAdminUsers(); } } if ($action === 'delete_user') { $stmtDelete = $pdo->prepare(" DELETE FROM `app_users` WHERE `id` = :id "); $stmtDelete->execute([ ':id' => $targetUserId, ]); $_SESSION['admin_users_flash_success'] = 'Benutzerkonto wurde gelöscht. Zugehörige Standorte und Satelliten wurden automatisch entfernt.'; redirectToAdminUsers(); } if ($action === 'update_page_permissions' && $currentUserIsMaster) { $submittedPages = array_values(array_unique(array_filter(array_map( static fn ($value): string => trim((string) $value), is_array($_POST['page_keys'] ?? null) ? $_POST['page_keys'] : [] ), static fn (string $value): bool => $value !== ''))); $submittedPages = array_values(array_intersect($submittedPages, array_keys($manageablePages))); $pdo->beginTransaction(); try { $stmtDeletePermissions = $pdo->prepare(" DELETE FROM `app_user_page_permissions` WHERE `user_id` = :user_id "); $stmtDeletePermissions->execute([ ':user_id' => $targetUserId, ]); if ($submittedPages !== []) { $stmtInsertPermission = $pdo->prepare(" INSERT INTO `app_user_page_permissions` ( `user_id`, `page_key`, `created_at`, `updated_at` ) VALUES ( :user_id, :page_key, NOW(), NOW() ) "); foreach ($submittedPages as $pageKey) { $stmtInsertPermission->execute([ ':user_id' => $targetUserId, ':page_key' => $pageKey, ]); } } $pdo->commit(); } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } throw $e; } $_SESSION['admin_users_flash_success'] = 'Die Seitenfreigaben wurden aktualisiert.'; redirectToAdminUsers(); } } if (!empty($errors)) { $_SESSION['admin_users_flash_errors'] = $errors; redirectToAdminUsers(); } } $stats = [ 'total' => 0, 'active' => 0, 'pending' => 0, 'admins' => 0, 'masters' => 0, ]; $stmtStats = $pdo->query(" SELECT COUNT(*) AS total_users, SUM(CASE WHEN `is_active` = 1 THEN 1 ELSE 0 END) AS active_users, SUM(CASE WHEN `is_active` = 0 THEN 1 ELSE 0 END) AS pending_users, SUM(CASE WHEN `role` = 'admin' THEN 1 ELSE 0 END) AS admin_users, SUM(CASE WHEN `role` = 'master' THEN 1 ELSE 0 END) AS master_users FROM `app_users` "); $statsRow = $stmtStats->fetch(); if ($statsRow) { $stats['total'] = (int)$statsRow['total_users']; $stats['active'] = (int)$statsRow['active_users']; $stats['pending'] = (int)$statsRow['pending_users']; $stats['admins'] = (int)$statsRow['admin_users']; $stats['masters'] = (int)$statsRow['master_users']; } $stmtUsers = $pdo->query(" SELECT `id`, `username`, `email`, `display_name`, `role`, `is_active`, `last_login_at`, `created_at`, `updated_at` FROM `app_users` ORDER BY `is_active` ASC, `role` DESC, `created_at` DESC, `username` ASC "); $users = $stmtUsers->fetchAll(); $pagePermissionsByUser = []; if ($currentUserIsMaster) { $stmtPagePermissions = $pdo->query(" SELECT `user_id`, `page_key` FROM `app_user_page_permissions` ORDER BY `user_id` ASC, `page_key` ASC "); foreach ($stmtPagePermissions as $permissionRow) { $permissionUserId = (int) ($permissionRow['user_id'] ?? 0); $permissionPageKey = (string) ($permissionRow['page_key'] ?? ''); if ($permissionUserId < 1 || $permissionPageKey === '') { continue; } if (!isset($pagePermissionsByUser[$permissionUserId])) { $pagePermissionsByUser[$permissionUserId] = []; } $pagePermissionsByUser[$permissionUserId][$permissionPageKey] = true; } } ?>
Hier kannst du Benutzerkonten freischalten, deaktivieren, löschen und zwischen user, admin und master wechseln.
= h($successMessage) ?>
| Benutzer | Status | Rolle | Registriert | Letzter Login | Aktionen |
|---|---|---|---|---|---|
|
= h($userRow['display_name'] ?: $userRow['username']) ?>
= h($userRow['username']) ?>
= h($userRow['email']) ?>
Dieses Konto
|
= h($statusLabel) ?> | = h($userRow['role']) ?> | = h($userRow['created_at']) ?> | = h($userRow['last_login_at'] ?: 'Noch nie') ?> |
|
Nur Master-Benutzer dürfen hier festlegen, welche Seiten normale Nutzer im Menü sehen und direkt aufrufen dürfen.
| Benutzer | $pageLabel): ?>= h($pageLabel) ?> | Speichern |
|---|---|---|
|
= h($userRow['display_name'] ?: $userRow['username']) ?> = h($userRow['username']) ?> (= h($userRow['role']) ?>) |
$pageLabel): ?>
= $isPrivilegedUser ? 'disabled' : '' ?> > | Vollzugriff über Rolle |