' . '

Access Denied

' . '

You do not have permission to view this page.

' . '← Dashboard'; exit; } } /** True if current session user has at least $min_role. */ function has_role(string $min): bool { _auth_start(); $levels = ['user' => 1, 'superuser' => 2, 'admin' => 3, 'superadmin' => 4]; return ($levels[$_SESSION['role'] ?? ''] ?? 0) >= ($levels[$min] ?? 999); } /** Return current user data from session (or empty defaults). */ function current_user(): array { _auth_start(); return [ 'id' => $_SESSION['user_id'] ?? null, 'username' => $_SESSION['username'] ?? '', 'email' => $_SESSION['email'] ?? '', 'role' => $_SESSION['role'] ?? '', 'display_name' => $_SESSION['display_name'] ?? '', 'rosary_limit' => $_SESSION['rosary_limit'] ?? 1, ]; } /** * Check if user can create another rosary. * Novenas count as 1 regardless of number of days. * Returns true if under limit (or limit is -1 = unlimited). */ function can_create_rosary(int $user_id, int $limit): bool { if ($limit < 0) return true; // unlimited $pdo = get_pdo(); $st = $pdo->prepare(" SELECT (SELECT COUNT(*) FROM sessions WHERE user_id = ? AND occasion != 'novena_deceased') + (SELECT COUNT(*) FROM novena_groups WHERE user_id = ?) AS total "); $st->execute([$user_id, $user_id]); return (int)$st->fetchColumn() < $limit; } const LOGIN_LOCKOUT_THRESHOLD = 5; const LOGIN_LOCKOUT_MINUTES = 15; /** True if this user account is currently locked out from login attempts. */ function is_locked_out(array $user): bool { if (empty($user['locked_until'])) return false; return strtotime($user['locked_until']) > time(); } /** Minutes remaining until a locked-out account can try again (0 if not locked). */ function login_lockout_minutes_remaining(array $user): int { if (!is_locked_out($user)) return 0; return (int)ceil((strtotime($user['locked_until']) - time()) / 60); } /** Record a failed login attempt; locks the account after LOGIN_LOCKOUT_THRESHOLD attempts. */ function record_login_failure(int $user_id): void { $pdo = get_pdo(); $pdo->prepare('UPDATE users SET failed_login_attempts = failed_login_attempts + 1 WHERE id = ?') ->execute([$user_id]); $st = $pdo->prepare('SELECT failed_login_attempts FROM users WHERE id = ?'); $st->execute([$user_id]); $attempts = (int)$st->fetchColumn(); if ($attempts >= LOGIN_LOCKOUT_THRESHOLD) { $locked_until = date('Y-m-d H:i:s', time() + LOGIN_LOCKOUT_MINUTES * 60); $pdo->prepare('UPDATE users SET locked_until = ? WHERE id = ?')->execute([$locked_until, $user_id]); } } /** Reset the failed-attempt counter and any lockout after a successful login. */ function record_login_success(int $user_id): void { get_pdo()->prepare('UPDATE users SET failed_login_attempts = 0, locked_until = NULL WHERE id = ?') ->execute([$user_id]); }