| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 |
- <?php
- require_once __DIR__ . '/../config.php';
- require_once __DIR__ . '/../includes/functions.php';
- require_once __DIR__ . '/../includes/manage.php';
- // Check admin login
- if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) {
- header('Location: login.php');
- exit;
- }
- $pageTitle = 'Einstellungen';
- // This page rolls out updates and hands out backup archives, so every form on
- // it carries a CSRF token - including the admin forms, which are otherwise
- // identical to what admins.php did before.
- function settingsCsrfToken() {
- if (empty($_SESSION['settings_csrf_token'])) {
- $_SESSION['settings_csrf_token'] = bin2hex(random_bytes(32));
- }
- return $_SESSION['settings_csrf_token'];
- }
- function settingsCsrfValid($token) {
- return !empty($_SESSION['settings_csrf_token']) &&
- is_string($token) &&
- hash_equals($_SESSION['settings_csrf_token'], $token);
- }
- function isValidAdminPasswordInput($password) {
- return is_string($password) && strlen($password) >= 8;
- }
- // Every message on this page, rendered as .alert blocks in source order.
- // A single action can produce several: an update reports deployment, migrations
- // and hook failure separately.
- $notices = [];
- $adminAccounts = getAdminAccounts();
- if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- if (!settingsCsrfValid($_POST['csrf_token'] ?? '')) {
- $notices[] = ['type' => 'error', 'text' => 'Ungültiges Sicherheitstoken. Bitte die Seite neu laden.'];
- } elseif (isset($_POST['create_backup'])) {
- try {
- $record = manageBackupCreate('manual');
- $notices[] = ['type' => 'success', 'text' => sprintf(
- 'Backup erstellt: %s (%d Dateien, %s).',
- $record['filename'],
- $record['file_count'],
- manageFormatBytes((int) $record['size'])
- )];
- // A failed upload is a warning, never an error: the local archive
- // is complete and valid either way.
- foreach ($record['remote_uploads'] as $upload) {
- if (empty($upload['success'])) {
- $notices[] = ['type' => 'warning', 'text' => 'Upload an ' . $upload['target'] .
- ' fehlgeschlagen: ' . ($upload['error'] ?? 'unbekannter Fehler')];
- }
- }
- manageHeartbeatSendQuietly();
- } catch (Throwable $exception) {
- $notices[] = ['type' => 'error', 'text' => 'Backup fehlgeschlagen: ' . $exception->getMessage()];
- }
- } elseif (isset($_POST['download_backup'])) {
- try {
- $path = manageBackupPath($_POST['filename'] ?? '');
- $handle = fopen($path, 'rb');
- $size = filesize($path);
- if ($handle === false || $size === false) {
- throw new RuntimeException('Das Backup konnte nicht geöffnet werden.');
- }
- header('Content-Type: application/zip');
- header('Content-Disposition: attachment; filename="' . addcslashes(basename($path), '"\\') . '"');
- header('Content-Length: ' . $size);
- header('Cache-Control: private, no-store');
- header('X-Content-Type-Options: nosniff');
- fpassthru($handle);
- fclose($handle);
- exit;
- } catch (Throwable $exception) {
- $notices[] = ['type' => 'error', 'text' => 'Download fehlgeschlagen: ' . $exception->getMessage()];
- }
- } elseif (isset($_POST['apply_update'])) {
- try {
- $result = manageUpdateApply(['force' => !empty($_POST['force'])]);
- $notices[] = ['type' => 'success', 'text' => sprintf(
- 'Update ausgerollt: %s → %s. %d Dateien kopiert, %d gesichert, %d übersprungen.',
- $result['from_version'] !== '' ? $result['from_version'] : 'unbekannt',
- $result['to_version'],
- $result['copied'],
- $result['backed_up'],
- $result['skipped']
- )];
- $notices[] = ['type' => 'info', 'text' => 'Die überschriebenen Dateien liegen unter ' .
- $result['backup_dir'] . ' - nur für eine manuelle Wiederherstellung, es gibt kein Rollback.'];
- // The files are live at this point. A failing post-update step is
- // therefore reported on its own, not as "update failed".
- $hook = $result['hook'];
- if (is_array($hook)) {
- $applied = $hook['migrations']['applied'] ?? [];
- if ($applied !== []) {
- $notices[] = ['type' => 'success', 'text' => 'Migrationen ausgeführt: ' . implode(', ', $applied)];
- }
- if (empty($hook['success'])) {
- if (!empty($hook['failed_migration'])) {
- $notices[] = ['type' => 'error', 'text' => 'Die Dateien wurden ausgerollt, aber die Migration "' .
- $hook['failed_migration'] . '" ist fehlgeschlagen: ' . ($hook['error'] ?? '')];
- $notices[] = ['type' => 'error', 'text' => 'Die restlichen Migrationen wurden nicht ausgeführt. ' .
- 'Nach Behebung der Ursache unten "Migrationen ausführen" verwenden.'];
- } else {
- $notices[] = ['type' => 'error', 'text' => 'Die Dateien wurden ausgerollt, aber der ' .
- 'Post-Update-Hook ist fehlgeschlagen: ' . ($hook['error'] ?? '')];
- }
- }
- }
- manageHeartbeatSendQuietly();
- } catch (Throwable $exception) {
- $notices[] = ['type' => 'error', 'text' => 'Update fehlgeschlagen: ' . $exception->getMessage()];
- }
- } elseif (isset($_POST['run_migrations'])) {
- $report = manageUpdateRunMigrations();
- if ($report['applied'] !== []) {
- $notices[] = ['type' => 'success', 'text' => 'Migrationen ausgeführt: ' . implode(', ', $report['applied'])];
- }
- if (!$report['success']) {
- $notices[] = ['type' => 'error', 'text' => 'Migration "' . $report['failed'] . '" ist fehlgeschlagen: ' .
- $report['error']];
- } elseif ($report['applied'] === []) {
- $notices[] = ['type' => 'info', 'text' => 'Es gibt keine offenen Migrationen.'];
- }
- } elseif (isset($_POST['send_heartbeat'])) {
- try {
- $result = manageHeartbeatSend();
- $notices[] = ['type' => 'success', 'text' => 'Status an den Manage-Server gemeldet. Aktuelles Release: ' .
- ($result['latest'] !== '' ? $result['latest'] : 'keines') . '.'];
- } catch (Throwable $exception) {
- $notices[] = ['type' => 'error', 'text' => 'Statusmeldung fehlgeschlagen: ' . $exception->getMessage()];
- }
- } elseif (isset($_POST['add_admin'])) {
- $username = normalizeAdminUsername($_POST['username'] ?? '');
- $description = normalizeAdminDescription($_POST['description'] ?? '');
- $email = normalizeAdminEmail($_POST['email'] ?? '');
- $password = $_POST['password'] ?? '';
- $passwordConfirm = $_POST['password_confirm'] ?? '';
- if (!isValidAdminUsername($username)) {
- $notices[] = ['type' => 'error', 'text' => 'Ungültiger Benutzername. Erlaubt: 3-50 Zeichen (Buchstaben, Zahlen, Punkt, Unterstrich, Bindestrich).'];
- } elseif (isset($adminAccounts[$username])) {
- $notices[] = ['type' => 'error', 'text' => 'Dieser Benutzername existiert bereits.'];
- } elseif (!isValidAdminDescription($description)) {
- $notices[] = ['type' => 'error', 'text' => 'Beschreibung ist erforderlich (max. 120 Zeichen).'];
- } elseif (!isValidAdminEmail($email)) {
- $notices[] = ['type' => 'error', 'text' => 'Gültige E-Mail ist erforderlich.'];
- } elseif (!isValidAdminPasswordInput($password)) {
- $notices[] = ['type' => 'error', 'text' => 'Passwort muss mindestens 8 Zeichen lang sein.'];
- } elseif ($password !== $passwordConfirm) {
- $notices[] = ['type' => 'error', 'text' => 'Passwort und Bestätigung stimmen nicht überein.'];
- } else {
- $adminAccounts[$username] = [
- 'password_hash' => password_hash($password, PASSWORD_BCRYPT),
- 'description' => $description,
- 'email' => $email
- ];
- saveAdminAccounts($adminAccounts);
- $notices[] = ['type' => 'success', 'text' => 'Admin wurde erfolgreich angelegt.'];
- }
- } elseif (isset($_POST['update_description'])) {
- $targetUsername = normalizeAdminUsername($_POST['target_username'] ?? '');
- $description = normalizeAdminDescription($_POST['description'] ?? '');
- $email = normalizeAdminEmail($_POST['email'] ?? '');
- if (!isset($adminAccounts[$targetUsername])) {
- $notices[] = ['type' => 'error', 'text' => 'Admin nicht gefunden.'];
- } elseif (!isValidAdminDescription($description)) {
- $notices[] = ['type' => 'error', 'text' => 'Beschreibung ist erforderlich (max. 120 Zeichen).'];
- } elseif (!isValidAdminEmail($email)) {
- $notices[] = ['type' => 'error', 'text' => 'Gültige E-Mail ist erforderlich.'];
- } else {
- $adminAccounts[$targetUsername]['description'] = $description;
- $adminAccounts[$targetUsername]['email'] = $email;
- saveAdminAccounts($adminAccounts);
- $notices[] = ['type' => 'success', 'text' => 'Beschreibung und E-Mail wurden aktualisiert.'];
- }
- } elseif (isset($_POST['change_password'])) {
- $targetUsername = normalizeAdminUsername($_POST['target_username'] ?? '');
- $newPassword = $_POST['new_password'] ?? '';
- $newPasswordConfirm = $_POST['new_password_confirm'] ?? '';
- if (!isset($adminAccounts[$targetUsername])) {
- $notices[] = ['type' => 'error', 'text' => 'Admin nicht gefunden.'];
- } elseif (!isValidAdminPasswordInput($newPassword)) {
- $notices[] = ['type' => 'error', 'text' => 'Passwort muss mindestens 8 Zeichen lang sein.'];
- } elseif ($newPassword !== $newPasswordConfirm) {
- $notices[] = ['type' => 'error', 'text' => 'Passwort und Bestätigung stimmen nicht überein.'];
- } else {
- $adminAccounts[$targetUsername]['password_hash'] = password_hash($newPassword, PASSWORD_BCRYPT);
- saveAdminAccounts($adminAccounts);
- $notices[] = ['type' => 'success', 'text' => 'Passwort wurde aktualisiert.'];
- }
- } elseif (isset($_POST['delete_admin'])) {
- $targetUsername = normalizeAdminUsername($_POST['target_username'] ?? '');
- if (!isset($adminAccounts[$targetUsername])) {
- $notices[] = ['type' => 'error', 'text' => 'Admin nicht gefunden.'];
- } else {
- unset($adminAccounts[$targetUsername]);
- saveAdminAccounts($adminAccounts);
- if (isset($_SESSION['admin_username']) && $_SESSION['admin_username'] === $targetUsername) {
- $_SESSION['admin_logged_in'] = false;
- unset($_SESSION['admin_username']);
- session_destroy();
- header('Location: login.php');
- exit;
- }
- $notices[] = ['type' => 'success', 'text' => 'Admin wurde gelöscht.'];
- }
- }
- $adminAccounts = getAdminAccounts();
- }
- // Collected after the actions, so the page shows the state they produced.
- // Never throws: remote failures come back inside the array.
- $status = manageClientStatus();
- // No cron on this host, so the report to the Manage server rides along with
- // this page load - at most once an hour.
- manageHeartbeatSendIfDue();
- $updateAvailable = $status['update'] !== null && !empty($status['update']['available']);
- $latestVersion = $status['update']['latest'] ?? '';
- $currentAdmin = isset($_SESSION['admin_username']) ? normalizeAdminUsername($_SESSION['admin_username']) : '';
- $changeUsername = normalizeAdminUsername($_GET['change'] ?? '');
- $selectedChangeUser = null;
- $editDescriptionUsername = normalizeAdminUsername($_GET['edit_description'] ?? '');
- $selectedDescriptionUser = null;
- if ($changeUsername !== '') {
- if (!isset($adminAccounts[$changeUsername])) {
- $notices[] = ['type' => 'error', 'text' => 'Ausgewählter Admin wurde nicht gefunden.'];
- } else {
- $selectedChangeUser = $changeUsername;
- }
- }
- if ($editDescriptionUsername !== '') {
- if (!isset($adminAccounts[$editDescriptionUsername])) {
- $notices[] = ['type' => 'error', 'text' => 'Ausgewählter Admin wurde nicht gefunden.'];
- } else {
- $selectedDescriptionUser = $editDescriptionUsername;
- }
- }
- ksort($adminAccounts);
- $csrfToken = settingsCsrfToken();
- $bodyClass = 'admin-page';
- include __DIR__ . '/../includes/header.php';
- ?>
- <div class="admin-header">
- <h2>Einstellungen</h2>
- <div>
- <a href="index.php" class="btn btn-secondary">Zurück zum Dashboard</a>
- </div>
- </div>
- <?php foreach ($notices as $notice): ?>
- <div class="alert alert-<?php echo htmlspecialchars($notice['type']); ?>">
- <?php echo htmlspecialchars($notice['text']); ?>
- </div>
- <?php endforeach; ?>
- <?php if (!$status['configured']): ?>
- <div class="alert alert-warning">
- Der Manage-Client ist nicht konfiguriert. Ohne <code>MANAGE_SERVER_URL</code>, <code>MANAGE_INSTANCE</code>
- und <code>MANAGE_TOKEN</code> in <code>config.php</code> funktionieren Update-Prüfung und Backup-Upload nicht.
- Lokale Backups lassen sich trotzdem erstellen.
- </div>
- <?php endif; ?>
- <div class="admin-stats">
- <div class="stat-card">
- <h3>Installierte Version</h3>
- <div class="stat-value"><?php echo htmlspecialchars($status['version'] !== '' ? $status['version'] : 'unbekannt'); ?></div>
- </div>
- <div class="stat-card">
- <h3>Aktuelles Release</h3>
- <div class="stat-value"><?php echo htmlspecialchars($latestVersion !== '' ? $latestVersion : '–'); ?></div>
- </div>
- <div class="stat-card">
- <h3>Lokale Backups</h3>
- <div class="stat-value"><?php echo count($status['backups']); ?></div>
- </div>
- <div class="stat-card">
- <h3>Letztes Backup</h3>
- <div class="stat-value" style="font-size: 1.2rem;">
- <?php echo $status['last_backup_at'] !== null ? htmlspecialchars(formatDate($status['last_backup_at'])) : 'nie'; ?>
- </div>
- </div>
- </div>
- <div class="panel">
- <h3>System</h3>
- <?php if ($status['update_error'] !== null): ?>
- <div class="alert alert-warning">
- Die Update-Prüfung ist fehlgeschlagen: <?php echo htmlspecialchars($status['update_error']); ?>
- </div>
- <?php elseif ($updateAvailable): ?>
- <div class="alert alert-warning">
- Version <?php echo htmlspecialchars($latestVersion); ?> steht bereit. Vor dem Ausrollen sollte ein
- aktuelles Backup vorliegen – ein Update lässt sich nicht zurücknehmen.
- </div>
- <?php elseif ($status['configured']): ?>
- <div class="alert alert-success">Der Shop ist auf dem aktuellen Stand.</div>
- <?php endif; ?>
- <div class="table-responsive">
- <table class="responsive-table">
- <tbody>
- <tr>
- <td data-label="Instanz"><strong>Instanz</strong></td>
- <td><?php echo htmlspecialchars($status['instance'] !== '' ? $status['instance'] : '–'); ?></td>
- </tr>
- <tr>
- <td data-label="Manage-Server"><strong>Manage-Server</strong></td>
- <td><?php echo htmlspecialchars($status['server_url'] !== '' ? $status['server_url'] : '–'); ?></td>
- </tr>
- <tr>
- <td data-label="PHP-Version"><strong>PHP-Version</strong></td>
- <td><?php echo htmlspecialchars($status['php_version']); ?></td>
- </tr>
- <tr>
- <td data-label="Offene Migrationen"><strong>Offene Migrationen</strong></td>
- <td><?php echo count($status['pending_migrations']); ?></td>
- </tr>
- </tbody>
- </table>
- </div>
- <form method="POST" style="margin-top: 1rem;" onsubmit="return confirm('Update jetzt ausrollen? Dateien werden überschrieben und es gibt kein Rollback.');">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <div class="form-group">
- <label>
- <input type="checkbox" name="force" value="1">
- Erneut ausrollen, auch wenn keine neuere Version vorliegt
- </label>
- </div>
- <button type="submit" name="apply_update" class="btn">Update ausrollen</button>
- <button type="submit" name="send_heartbeat" class="btn btn-secondary">Status melden</button>
- </form>
- </div>
- <div class="panel">
- <h3>Backup</h3>
- <p>
- Gesichert werden die Daten unter <code>data/</code> und die Produktbilder unter
- <code>assets/images/</code>. Lokal bleiben die letzten
- <?php echo (int) MANAGE_BACKUP_LOCAL_RETENTION; ?> Archive erhalten, jedes wird zusätzlich an den
- Manage-Server übertragen.
- <?php if ((int) MANAGE_BACKUP_AUTO_INTERVAL_SECONDS > 0): ?>
- Zusätzlich erstellt das Dashboard automatisch alle
- <?php echo (int) round(MANAGE_BACKUP_AUTO_INTERVAL_SECONDS / 86400); ?> Tage ein Backup.
- <?php endif; ?>
- </p>
- <form method="POST">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <button type="submit" name="create_backup" class="btn">Backup jetzt erstellen</button>
- </form>
- <?php if ($status['backups'] === []): ?>
- <p style="margin-top: 1rem;">Es wurde noch kein Backup erstellt.</p>
- <?php else: ?>
- <div class="table-responsive" style="margin-top: 1rem;">
- <table class="responsive-table">
- <thead>
- <tr>
- <th>Datei</th>
- <th>Erstellt</th>
- <th>Auslöser</th>
- <th>Dateien</th>
- <th>Größe</th>
- <th>Upload</th>
- <th>Aktionen</th>
- </tr>
- </thead>
- <tbody>
- <?php foreach ($status['backups'] as $backup): ?>
- <tr>
- <td data-label="Datei"><strong><?php echo htmlspecialchars($backup['filename']); ?></strong></td>
- <td data-label="Erstellt"><?php echo htmlspecialchars(formatDate($backup['created_at'])); ?></td>
- <td data-label="Auslöser"><?php echo htmlspecialchars($backup['trigger'] ?? ''); ?></td>
- <td data-label="Dateien"><?php echo (int) ($backup['file_count'] ?? 0); ?></td>
- <td data-label="Größe"><?php echo htmlspecialchars(manageFormatBytes((int) ($backup['size'] ?? 0))); ?></td>
- <td data-label="Upload">
- <?php
- $uploads = is_array($backup['remote_uploads'] ?? null) ? $backup['remote_uploads'] : [];
- if ($uploads === []) {
- echo '<span class="status status-expired">nicht übertragen</span>';
- } else {
- foreach ($uploads as $upload) {
- if (!empty($upload['success'])) {
- echo '<span class="status status-picked">' . htmlspecialchars($upload['target']) . ': OK</span>';
- } else {
- echo '<span class="status status-expired" title="' .
- htmlspecialchars($upload['error'] ?? '') . '">' .
- htmlspecialchars($upload['target']) . ': Fehler</span>';
- }
- }
- }
- ?>
- </td>
- <td data-label="Aktionen">
- <form method="POST" style="display: inline;">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <input type="hidden" name="filename" value="<?php echo htmlspecialchars($backup['filename']); ?>">
- <button type="submit" name="download_backup" class="btn btn-small btn-secondary">Herunterladen</button>
- </form>
- </td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- </div>
- <?php endif; ?>
- </div>
- <?php if ($status['pending_migrations'] !== []): ?>
- <div class="panel">
- <h3>Offene Migrationen</h3>
- <p>Diese Migrationen wurden noch nicht ausgeführt:</p>
- <ul>
- <?php foreach ($status['pending_migrations'] as $migration): ?>
- <li><code><?php echo htmlspecialchars($migration['id']); ?></code></li>
- <?php endforeach; ?>
- </ul>
- <form method="POST">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <button type="submit" name="run_migrations" class="btn">Migrationen ausführen</button>
- </form>
- </div>
- <?php endif; ?>
- <?php foreach ($status['errors'] as $error): ?>
- <div class="alert alert-warning"><?php echo htmlspecialchars($error); ?></div>
- <?php endforeach; ?>
- <div class="panel">
- <p><strong>Eingeloggt als:</strong> <?php echo htmlspecialchars($currentAdmin !== '' ? $currentAdmin : 'Unbekannt'); ?></p>
- </div>
- <div class="panel">
- <h3>Neuen Admin anlegen</h3>
- <form method="POST">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <div class="form-group">
- <label for="username">Benutzername *</label>
- <input type="text" id="username" name="username" required maxlength="50" pattern="[A-Za-z0-9][A-Za-z0-9._-]{2,49}" placeholder="z.B. max.mustermann">
- </div>
- <div class="form-group">
- <label for="description">Beschreibung *</label>
- <input type="text" id="description" name="description" required maxlength="120" placeholder="z.B. Kassierer, Shop-Team">
- </div>
- <div class="form-group">
- <label for="email">E-Mail *</label>
- <input type="email" id="email" name="email" required maxlength="190" placeholder="z.B. max.mustermann@example.org">
- </div>
- <div class="form-group">
- <label for="password">Passwort (mind. 8 Zeichen) *</label>
- <input type="password" id="password" name="password" required minlength="8">
- </div>
- <div class="form-group">
- <label for="password_confirm">Passwort bestätigen *</label>
- <input type="password" id="password_confirm" name="password_confirm" required minlength="8">
- </div>
- <button type="submit" name="add_admin" class="btn">Admin anlegen</button>
- </form>
- </div>
- <div class="panel">
- <h3>Admin-Liste</h3>
- <div class="table-responsive">
- <table class="responsive-table">
- <thead>
- <tr>
- <th>Benutzername</th>
- <th>Beschreibung</th>
- <th>E-Mail</th>
- <th>Aktionen</th>
- </tr>
- </thead>
- <tbody>
- <?php foreach ($adminAccounts as $username => $account): ?>
- <tr>
- <td data-label="Benutzername">
- <strong><?php echo htmlspecialchars($username); ?></strong>
- <?php if ($username === $currentAdmin): ?>
- <span class="status status-open" style="margin-left: 0.5rem;">Du</span>
- <?php endif; ?>
- </td>
- <td data-label="Beschreibung">
- <?php echo htmlspecialchars($account['description']); ?>
- </td>
- <td data-label="E-Mail">
- <?php echo htmlspecialchars($account['email']); ?>
- </td>
- <td data-label="Aktionen">
- <a href="settings.php?edit_description=<?php echo urlencode($username); ?>" class="btn btn-small btn-secondary">Profil ändern</a>
- <a href="settings.php?change=<?php echo urlencode($username); ?>" class="btn btn-small btn-secondary">Passwort ändern</a>
- <form method="POST" style="display: inline;" onsubmit="return confirm('Admin wirklich löschen?');">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <input type="hidden" name="target_username" value="<?php echo htmlspecialchars($username); ?>">
- <button type="submit" name="delete_admin" class="btn btn-small">Löschen</button>
- </form>
- </td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- </div>
- </div>
- <?php if ($selectedDescriptionUser !== null): ?>
- <div class="panel">
- <h3>Profil ändern: <?php echo htmlspecialchars($selectedDescriptionUser); ?></h3>
- <form method="POST">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <input type="hidden" name="target_username" value="<?php echo htmlspecialchars($selectedDescriptionUser); ?>">
- <div class="form-group">
- <label for="description_edit">Beschreibung *</label>
- <input type="text" id="description_edit" name="description" maxlength="120" required value="<?php echo htmlspecialchars($adminAccounts[$selectedDescriptionUser]['description']); ?>">
- </div>
- <div class="form-group">
- <label for="email_edit">E-Mail *</label>
- <input type="email" id="email_edit" name="email" maxlength="190" required value="<?php echo htmlspecialchars($adminAccounts[$selectedDescriptionUser]['email']); ?>">
- </div>
- <button type="submit" name="update_description" class="btn">Profil speichern</button>
- <a href="settings.php" class="btn btn-secondary">Abbrechen</a>
- </form>
- </div>
- <?php endif; ?>
- <?php if ($selectedChangeUser !== null): ?>
- <div class="panel">
- <h3>Passwort ändern: <?php echo htmlspecialchars($selectedChangeUser); ?></h3>
- <form method="POST">
- <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrfToken); ?>">
- <input type="hidden" name="target_username" value="<?php echo htmlspecialchars($selectedChangeUser); ?>">
- <div class="form-group">
- <label for="new_password">Neues Passwort (mind. 8 Zeichen) *</label>
- <input type="password" id="new_password" name="new_password" required minlength="8">
- </div>
- <div class="form-group">
- <label for="new_password_confirm">Neues Passwort bestätigen *</label>
- <input type="password" id="new_password_confirm" name="new_password_confirm" required minlength="8">
- </div>
- <button type="submit" name="change_password" class="btn">Passwort speichern</button>
- <a href="settings.php" class="btn btn-secondary">Abbrechen</a>
- </form>
- </div>
- <?php endif; ?>
- <?php include __DIR__ . '/../includes/footer.php'; ?>
|