$name, 'password_hash' => password_hash($password, PASSWORD_DEFAULT), 'role' => $role, 'groups' => $groups, ]; file_put_contents(USERS_FILE, json_encode($users, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"); $success[] = "User " . htmlspecialchars($username) . " saved."; } } elseif ($action === 'change_password') { $username = trim($_POST['username'] ?? ''); $password = $_POST['password'] ?? ''; $confirm = $_POST['confirm'] ?? ''; if (!isset($users[$username])) $errors[] = 'User not found.'; if (strlen($password) < 8) $errors[] = 'Password must be at least 8 characters.'; if ($password !== $confirm) $errors[] = 'Passwords do not match.'; if (!$errors) { $users[$username]['password_hash'] = password_hash($password, PASSWORD_DEFAULT); file_put_contents(USERS_FILE, json_encode($users, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"); $success[] = "Password updated for " . htmlspecialchars($username) . "."; } } elseif ($action === 'delete_user') { $username = trim($_POST['username'] ?? ''); $users_left = array_filter($users, fn($u) => $u['role'] === 'admin'); if (count($users_left) <= 1 && isset($users[$username]) && $users[$username]['role'] === 'admin') { $errors[] = 'Cannot delete the last admin account.'; } elseif (!isset($users[$username])) { $errors[] = 'User not found.'; } else { unset($users[$username]); file_put_contents(USERS_FILE, json_encode($users, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"); $success[] = "User " . htmlspecialchars($username) . " deleted."; } } elseif ($action === 'lock') { file_put_contents(LOCK_FILE, date('Y-m-d H:i:s')); $locked = true; } } } // ── Load current users for display ─────────────────────────────────────────── $users = json_decode(@file_get_contents(USERS_FILE), true) ?: []; $has_real_admin = false; foreach ($users as $u) { if ($u['role'] === 'admin' && !str_starts_with($u['password_hash'], '$2y$12$placeholder')) { $has_real_admin = true; break; } } $key_set = file_exists(LOCK_FILE . '.key'); // ── HTML ────────────────────────────────────────────────────────────────────── ?>
Account setup has been completed and locked.
For security, delete this file from your server:
rm setup.php
To make further changes, delete data/setup.lock and reload this page.
No users yet.
| Username | Display Name | Role | Groups |
|---|---|---|---|
| = htmlspecialchars($uname) ?> | = htmlspecialchars($u['name'] ?? '') ?> | = htmlspecialchars($u['role'] ?? 'user') ?> | = htmlspecialchars(implode(', ', $u['groups'] ?? [])) ?> |
data/setup.lock. Do this when you are done configuring accounts.
After locking, delete setup.php from your server for maximum security.
The data/setup.lock.key file also contains your setup key in plaintext — delete it too once you no longer need this tool.