Files
theoldfitz/admin/login.php
T
David Dyer 242c5165e1 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.
2026-10-25 12:58:19 -04:00

87 lines
3.6 KiB
PHP

<?php
require_once __DIR__ . '/../inc/auth.php';
require_once __DIR__ . '/../inc/login-throttle.php';
require_once __DIR__ . '/../inc/assets.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = is_string($_POST['username'] ?? null) ? $_POST['username'] : '';
$password = is_string($_POST['password'] ?? null) ? $_POST['password'] : '';
$ip = client_ip();
$throttleKey = strtolower(trim($username));
$lockSeconds = login_lock_seconds($ip, $throttleKey);
if ($lockSeconds > 0) {
http_response_code(429);
$error = 'Too many failed attempts. Try again in ' . (int) ceil($lockSeconds / 60) . ' minute(s).';
} elseif (authenticate_user($username, $password)) {
clear_login_failures($ip, $throttleKey);
header('Location: index.php');
exit;
} else {
record_login_failure($ip, $throttleKey);
$error = 'Invalid username or password.';
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Admin Login | The Old Fitz Public House</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@600&family=Karla:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../styles.css<?= asset_version('styles.css') ?>">
</head>
<body class="admin-login-body">
<div class="login-card">
<div class="login-header">
<img src="../assets/knot.png" alt="" class="knot">
<h1>The Old Fitz</h1>
<p>Management Portal</p>
</div>
<?php if (!empty($error)): ?>
<div class="error-msg" role="alert"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<form method="POST" action="login.php">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" class="form-input" required autofocus autocomplete="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<div class="password-input-wrap">
<input type="password" id="password" name="password" class="form-input" required autocomplete="current-password">
<button type="button" class="password-toggle-btn" aria-label="Show password" id="btn-toggle-login-password">
<span class="js-eye-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="icon-eye">
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
<circle cx="12" cy="12" r="3" />
</svg>
</span>
<span class="js-eye-off" hidden>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" class="icon-eye-off">
<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24" />
<path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" />
<path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" />
<line x1="2" y1="2" x2="22" y2="22" />
</svg>
</span>
</button>
</div>
</div>
<button type="submit" class="btn btn-primary login-btn">Sign In</button>
</form>
<a href="../" class="back-link">← Return to Pub Website</a>
</div>
<script src="login.js" defer></script>
</body>
</html>