Access
32) { return 'Username must be between 3 and 32 characters.'; } if (!preg_match('/^[a-zA-Z0-9_.-]+$/', $username)) { return 'Username can only contain letters, numbers, and . _ -'; } return null; } function handle_create_user(array $post, array $currentUser): array { $username = post_str($post, 'username'); $password = post_str($post, 'password'); $confirm = post_str($post, 'confirm_password'); if ($error = validate_username($username)) { return ['success' => false, 'error' => $error]; } if (username_exists($username)) { return ['success' => false, 'error' => 'That username is already taken.']; } if (strlen($password) < MIN_PASSWORD_LENGTH) { return ['success' => false, 'error' => 'Password must be at least ' . MIN_PASSWORD_LENGTH . ' characters.']; } if ($password !== $confirm) { return ['success' => false, 'error' => 'Passwords do not match.']; } $newId = create_user($username, $password, post_role($post)); return ['success' => true, 'user' => get_user_by_id($newId)]; } function handle_change_password(array $post, array $currentUser): array { $targetId = (int) ($post['user_id'] ?? 0); $target = $targetId > 0 ? get_user_by_id($targetId) : null; if (!$target) { return ['success' => false, 'error' => 'User not found.']; } $newPassword = post_str($post, 'new_password'); $confirm = post_str($post, 'confirm_password'); $isSelf = $targetId === (int) $currentUser['id']; if ($isSelf) { $currentPassword = post_str($post, 'current_password'); if (!verify_user_password($targetId, $currentPassword)) { return ['success' => false, 'error' => 'Your current password is incorrect.']; } } if (strlen($newPassword) < MIN_PASSWORD_LENGTH) { return ['success' => false, 'error' => 'Password must be at least ' . MIN_PASSWORD_LENGTH . ' characters.']; } if ($newPassword !== $confirm) { return ['success' => false, 'error' => 'Passwords do not match.']; } set_user_password($targetId, $newPassword); return ['success' => true]; } function handle_delete_user(array $post, array $currentUser): array { $targetId = (int) ($post['user_id'] ?? 0); if ($targetId <= 0 || !get_user_by_id($targetId)) { return ['success' => false, 'error' => 'User not found.']; } if ($targetId === (int) $currentUser['id']) { return ['success' => false, 'error' => "You can't delete your own account while logged in as it."]; } if (count_users() <= 1) { return ['success' => false, 'error' => 'At least one user account must remain.']; } delete_user($targetId); return ['success' => true]; } function handle_users_action(string $action, array $post, array $currentUser): array { return match ($action) { 'create_user' => handle_create_user($post, $currentUser), 'change_password' => handle_change_password($post, $currentUser), 'delete_user' => handle_delete_user($post, $currentUser), default => ['success' => false, 'error' => 'Unknown action'], }; } // Handle AJAX actions (JSON response) if ($_SERVER['REQUEST_METHOD'] === 'POST') { header('Content-Type: application/json; charset=utf-8'); $csrfToken = $_POST['csrf_token'] ?? null; if (!verify_csrf_token(is_string($csrfToken) ? $csrfToken : null)) { http_response_code(403); echo json_encode(['success' => false, 'error' => 'Session expired or invalid security token. Please refresh.']); exit; } $action = is_string($_POST['action'] ?? null) ? $_POST['action'] : ''; echo json_encode(handle_users_action($action, $_POST, $user)); exit; } $users = get_all_users(); ?>
Access