252 lines
13 KiB
PHP
252 lines
13 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once dirname(__DIR__, 3) . '/src/App/bootstrap.php';
|
|
|
|
use App\ConfigLoader;
|
|
use App\AccountGate;
|
|
use App\RegistrationService;
|
|
|
|
session_start();
|
|
|
|
$projectRoot = dirname(__DIR__, 3);
|
|
$accountGate = new AccountGate(ConfigLoader::load($projectRoot, 'registration'));
|
|
$registration = new RegistrationService($projectRoot, ConfigLoader::load($projectRoot, 'registration'));
|
|
|
|
if (isset($_SESSION['desktop_auth']) && is_array($_SESSION['desktop_auth'])) {
|
|
$currentAuthUser = is_array($_SESSION['desktop_auth']['user'] ?? null) ? $_SESSION['desktop_auth']['user'] : [];
|
|
$accountCheck = $accountGate->checkUsername((string) ($currentAuthUser['username'] ?? ''));
|
|
|
|
if (!($accountCheck['allowed'] ?? false)) {
|
|
unset($_SESSION['desktop_auth']);
|
|
$target = (string) ($accountCheck['state'] ?? '') === 'pending'
|
|
? '/auth/pending/?username=' . urlencode((string) ($currentAuthUser['username'] ?? ''))
|
|
: '/auth/inactive/?message=' . urlencode((string) ($accountCheck['message'] ?? 'Dieses Konto ist noch nicht freigeschaltet.'));
|
|
header('Location: ' . $target, true, 302);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$currentUser = is_array($_SESSION['desktop_auth']['user'] ?? null) ? $_SESSION['desktop_auth']['user'] : [];
|
|
$currentGroups = array_map(static fn (string $group): string => strtolower(trim($group, '/')), array_values(array_map('strval', (array) ($currentUser['groups'] ?? []))));
|
|
|
|
if (!in_array('administrators', $currentGroups, true)) {
|
|
http_response_code(403);
|
|
echo 'Kein Zugriff auf User Management.';
|
|
exit;
|
|
}
|
|
|
|
$csrfToken = (string) ($_SESSION['user_management_token'] ?? '');
|
|
|
|
if ($csrfToken === '') {
|
|
$csrfToken = bin2hex(random_bytes(16));
|
|
$_SESSION['user_management_token'] = $csrfToken;
|
|
}
|
|
|
|
$messages = [];
|
|
$errors = [];
|
|
$selectedId = trim((string) ($_GET['id'] ?? $_POST['selected_id'] ?? ''));
|
|
$manualUsername = trim((string) ($_POST['manual_username'] ?? ''));
|
|
$manualResetUsername = trim((string) ($_POST['reset_username'] ?? ''));
|
|
$manualResetPassword = (string) ($_POST['reset_password'] ?? '');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$postedToken = (string) ($_POST['csrf_token'] ?? '');
|
|
|
|
if ($postedToken === '' || !hash_equals($csrfToken, $postedToken)) {
|
|
$errors[] = 'Die Formularprüfung ist fehlgeschlagen.';
|
|
} else {
|
|
$action = (string) ($_POST['action'] ?? '');
|
|
|
|
if ($action === 'approve-registration') {
|
|
$groupDns = array_values(array_filter(array_map('strval', (array) ($_POST['group_dns'] ?? []))));
|
|
$memberOfList = implode(PHP_EOL, $groupDns);
|
|
$result = $registration->approve($selectedId, [
|
|
'member_of_list' => $memberOfList,
|
|
'admin_note' => (string) ($_POST['admin_note'] ?? ''),
|
|
], (string) ($currentUser['username'] ?? 'administrator'));
|
|
|
|
if (($result['success'] ?? false) !== true) {
|
|
$errors = array_merge($errors, array_values(array_map('strval', (array) ($result['errors'] ?? []))));
|
|
} else {
|
|
$messages[] = 'Registrierung wurde freigeschaltet.';
|
|
}
|
|
} elseif ($action === 'deactivate-user') {
|
|
$result = $registration->deactivateUser($manualUsername);
|
|
($result['success'] ?? false) ? $messages[] = (string) ($result['message'] ?? '') : $errors[] = (string) ($result['message'] ?? '');
|
|
} elseif ($action === 'activate-user') {
|
|
$groupDns = array_values(array_filter(array_map('strval', (array) ($_POST['manual_group_dns'] ?? []))));
|
|
$result = $registration->activateExistingUser($manualUsername, $groupDns);
|
|
($result['success'] ?? false) ? $messages[] = (string) ($result['message'] ?? '') : $errors[] = (string) ($result['message'] ?? '');
|
|
} elseif ($action === 'send-reset-mail') {
|
|
$origin = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost');
|
|
$result = $registration->sendPasswordReset($manualResetUsername, $origin);
|
|
($result['success'] ?? false) ? $messages[] = (string) ($result['message'] ?? '') : $errors[] = (string) ($result['message'] ?? '');
|
|
} elseif ($action === 'set-password') {
|
|
if (strlen($manualResetPassword) < 12) {
|
|
$errors[] = 'Das neue Passwort muss mindestens 12 Zeichen lang sein.';
|
|
} else {
|
|
$result = $registration->setUserPassword($manualResetUsername, $manualResetPassword);
|
|
($result['success'] ?? false) ? $messages[] = (string) ($result['message'] ?? '') : $errors[] = (string) ($result['message'] ?? '');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$pendingRequests = $registration->pendingApprovals();
|
|
$availableGroups = $registration->availableGroups();
|
|
$selected = $selectedId !== ''
|
|
? $registration->find($selectedId)
|
|
: ($pendingRequests[0] ?? null);
|
|
?><!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>User Management</title>
|
|
<link rel="stylesheet" href="/assets/auth/login.css">
|
|
</head>
|
|
<body>
|
|
<main class="login-shell">
|
|
<section class="login-panel login-panel-admin">
|
|
<div class="login-panel-top">
|
|
<p class="login-kicker">Kusche.Berlin</p>
|
|
<h1>User Management</h1>
|
|
<p class="login-copy">Nur für Benutzer in der Gruppe <strong>administrators</strong>. Hier werden Neuregistrierungen freigeschaltet sowie bestehende LDAP-Benutzer aktiviert, deaktiviert oder zurückgesetzt.</p>
|
|
</div>
|
|
|
|
<?php if ($messages !== []): ?>
|
|
<div class="login-notice login-notice-success">
|
|
<strong>Ergebnis</strong>
|
|
<ul class="login-list">
|
|
<?php foreach ($messages as $message): ?>
|
|
<li><?= htmlspecialchars($message, ENT_QUOTES) ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($errors !== []): ?>
|
|
<div class="login-notice login-notice-error">
|
|
<strong>Bitte prüfen</strong>
|
|
<ul class="login-list">
|
|
<?php foreach ($errors as $error): ?>
|
|
<li><?= htmlspecialchars($error, ENT_QUOTES) ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="admin-layout">
|
|
<aside class="admin-sidebar">
|
|
<h2>Offene Registrierungen</h2>
|
|
<div class="admin-request-list">
|
|
<?php foreach ($pendingRequests as $request): ?>
|
|
<a class="admin-request-card<?= (($selected['id'] ?? '') === ($request['id'] ?? '')) ? ' is-active' : '' ?>" href="/admin/users/?id=<?= urlencode((string) ($request['id'] ?? '')) ?>">
|
|
<strong><?= htmlspecialchars((string) ($request['username'] ?? ''), ENT_QUOTES) ?></strong>
|
|
<span><?= htmlspecialchars((string) ($request['email'] ?? ''), ENT_QUOTES) ?></span>
|
|
<span class="admin-status"><?= htmlspecialchars((string) ($request['status'] ?? ''), ENT_QUOTES) ?></span>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</aside>
|
|
|
|
<section class="admin-detail">
|
|
<?php if (is_array($selected)): ?>
|
|
<div class="admin-summary">
|
|
<h2>Freischaltung</h2>
|
|
<p>Benutzer: <?= htmlspecialchars((string) ($selected['username'] ?? ''), ENT_QUOTES) ?></p>
|
|
<p>E-Mail: <?= htmlspecialchars((string) ($selected['email'] ?? ''), ENT_QUOTES) ?></p>
|
|
<p>Status: <?= htmlspecialchars((string) ($selected['status'] ?? ''), ENT_QUOTES) ?></p>
|
|
</div>
|
|
|
|
<form class="login-form" method="post" action="/admin/users/">
|
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES) ?>">
|
|
<input type="hidden" name="selected_id" value="<?= htmlspecialchars((string) ($selected['id'] ?? ''), ENT_QUOTES) ?>">
|
|
<input type="hidden" name="action" value="approve-registration">
|
|
|
|
<label class="login-field">
|
|
<span>Zielgruppen für Freischaltung</span>
|
|
<div class="admin-request-list">
|
|
<?php foreach ($availableGroups as $group): ?>
|
|
<label class="login-field">
|
|
<span>
|
|
<input type="checkbox" name="group_dns[]" value="<?= htmlspecialchars($group['dn'], ENT_QUOTES) ?>">
|
|
<?= htmlspecialchars($group['label'], ENT_QUOTES) ?>
|
|
</span>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</label>
|
|
|
|
<label class="login-field">
|
|
<span>Admin-Notiz</span>
|
|
<textarea name="admin_note" rows="3"></textarea>
|
|
</label>
|
|
|
|
<div class="login-actions">
|
|
<button class="login-button login-button-primary" type="submit">Freischaltung bestätigen</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
|
|
<div class="admin-summary">
|
|
<h2>Bestehenden Benutzer verwalten</h2>
|
|
</div>
|
|
|
|
<form class="login-form" method="post" action="/admin/users/">
|
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES) ?>">
|
|
<label class="login-field">
|
|
<span>Benutzername</span>
|
|
<input type="text" name="manual_username" value="<?= htmlspecialchars($manualUsername, ENT_QUOTES) ?>" required>
|
|
</label>
|
|
|
|
<label class="login-field">
|
|
<span>Gruppen für Aktivierung</span>
|
|
<div class="admin-request-list">
|
|
<?php foreach ($availableGroups as $group): ?>
|
|
<label class="login-field">
|
|
<span>
|
|
<input type="checkbox" name="manual_group_dns[]" value="<?= htmlspecialchars($group['dn'], ENT_QUOTES) ?>">
|
|
<?= htmlspecialchars($group['label'], ENT_QUOTES) ?>
|
|
</span>
|
|
</label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</label>
|
|
|
|
<div class="login-actions">
|
|
<button class="login-button login-button-primary" type="submit" name="action" value="activate-user">Benutzer aktivieren</button>
|
|
<button class="login-button login-button-danger" type="submit" name="action" value="deactivate-user">Benutzer deaktivieren</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="admin-summary">
|
|
<h2>Passwort zurücksetzen</h2>
|
|
</div>
|
|
|
|
<form class="login-form" method="post" action="/admin/users/">
|
|
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES) ?>">
|
|
<label class="login-field">
|
|
<span>Benutzername</span>
|
|
<input type="text" name="reset_username" value="<?= htmlspecialchars($manualResetUsername, ENT_QUOTES) ?>" required>
|
|
</label>
|
|
|
|
<label class="login-field">
|
|
<span>Neues Passwort für direkten Reset</span>
|
|
<input type="password" name="reset_password" value="" placeholder="Optional für direkten Admin-Reset">
|
|
</label>
|
|
|
|
<div class="login-actions">
|
|
<button class="login-button login-button-secondary" type="submit" name="action" value="send-reset-mail">Reset-Mail senden</button>
|
|
<button class="login-button login-button-primary" type="submit" name="action" value="set-password">Passwort direkt setzen</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|