Refactor admin panel: enhance user management and security features

- Added role-based access control for user management links in admin navigation.
- Improved user account display with a dedicated account link.
- Implemented form submission confirmation for delete actions in the admin interface.
- Introduced a password visibility toggle on the login page.
- Added login throttling to prevent brute-force attacks, recording failed attempts.
- Created a CLI script for creating an admin user, replacing the previous hardcoded admin credentials.
- Updated database schema to support login attempt tracking.
- Enhanced user editing functionality, allowing role changes with restrictions.
- Improved modal handling for user actions, ensuring better focus management.
- Added styles for new account management page and improved modal transitions.
This commit is contained in:
David Dyer committed 2026-10-25 12:58:19 -04:00
1 parent 91ec95a4a9
commit 242c5165e1
21 files changed
+669 -77

No files matched your search

+15 -8
View File
@@ -96,6 +96,17 @@ function init_db_schema(PDO $pdo): void {
menu_enabled INTEGER NOT NULL DEFAULT 1,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Failed admin logins, used by inc/login-throttle.php. Rows older
-- than the throttle window are pruned on every new failure.
CREATE TABLE IF NOT EXISTS login_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip TEXT NOT NULL,
username TEXT NOT NULL,
attempted_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_login_attempts_ip ON login_attempts (ip, attempted_at);
CREATE INDEX IF NOT EXISTS idx_login_attempts_username ON login_attempts (username, attempted_at);
");
// users.is_enabled shipped after the initial release — CREATE TABLE IF
@@ -112,14 +123,10 @@ function init_db_schema(PDO $pdo): void {
$pdo->exec("ALTER TABLE users ADD COLUMN is_enabled INTEGER NOT NULL DEFAULT 1");
}
// Seed default admin user if table is empty (username: admin / password: password)
$stmt = $pdo->query("SELECT COUNT(*) as count FROM users");
$userCount = $stmt->fetchColumn();
if ($userCount == 0) {
$defaultPassHash = password_hash('password', PASSWORD_DEFAULT);
$insert = $pdo->prepare("INSERT INTO users (username, password_hash, role) VALUES (?, ?, 'admin')");
$insert->execute(['admin', $defaultPassHash]);
}
// No default admin is seeded — a fresh database has no users until one
// is created from the CLI (run as www-data so the sqlite file stays
// writable by Apache):
// docker exec -it -u www-data the-old-fitz php /var/www/html/bin/create-user.php
// Seed default weekly hours if the table is empty: closed Sun–Wed,
// 4–10pm Thu–Sat with the kitchen closing at 9 — matches the hours the