From 1e98b8a04732a120f43a95f68f540aba64d2dbca Mon Sep 17 00:00:00 2001 From: Hosteroid Date: Mon, 15 Dec 2025 17:48:55 +0200 Subject: [PATCH] Enhance user actions with CSRF protection and POST requests Added CSRF protection and enforced POST requests for user delete and toggle status actions in UserController. Updated the users index view to use JavaScript for submitting POST forms with CSRF tokens for these actions, improving security and user experience. Also improved login success messages to include the user's full name. --- app/Controllers/AuthController.php | 8 +++++ app/Controllers/TwoFactorController.php | 2 +- app/Controllers/UserController.php | 16 +++++++++ app/Views/users/index.php | 43 ++++++++++++++++++++++--- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/app/Controllers/AuthController.php b/app/Controllers/AuthController.php index 3e743af..5306b33 100644 --- a/app/Controllers/AuthController.php +++ b/app/Controllers/AuthController.php @@ -167,6 +167,11 @@ class AuthController extends Controller $_SESSION['email'] = $user['email']; $_SESSION['role'] = $user['role']; + // Clear any existing session messages before successful login + unset($_SESSION['error']); + unset($_SESSION['success']); + unset($_SESSION['info']); + // Session is automatically tracked by DatabaseSessionHandler // No need to manually create session record @@ -178,6 +183,9 @@ class AuthController extends Controller // Update last login $this->userModel->updateLastLogin($user['id']); + // Set success message for login + $_SESSION['success'] = 'Login successful! Welcome back, ' . htmlspecialchars($user['full_name']) . '.'; + // Redirect to dashboard $this->redirect('/'); } diff --git a/app/Controllers/TwoFactorController.php b/app/Controllers/TwoFactorController.php index 7237861..acabded 100644 --- a/app/Controllers/TwoFactorController.php +++ b/app/Controllers/TwoFactorController.php @@ -295,7 +295,7 @@ class TwoFactorController extends Controller 'method' => $method ]); - $_SESSION['success'] = 'Login successful!'; + $_SESSION['success'] = 'Login successful! Welcome back, ' . htmlspecialchars($user['full_name']) . '.'; $this->redirect('/'); } else { $_SESSION['error'] = 'Invalid verification code. Please try again.'; diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php index 862dd0b..1f5815e 100644 --- a/app/Controllers/UserController.php +++ b/app/Controllers/UserController.php @@ -306,6 +306,14 @@ class UserController extends Controller */ public function delete($params = []) { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + $this->redirect('/users'); + return; + } + + // CSRF Protection + $this->verifyCsrf('/users'); + $userId = $params['id'] ?? 0; $user = $this->userModel->find($userId); @@ -348,6 +356,14 @@ class UserController extends Controller */ public function toggleStatus($params = []) { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + $this->redirect('/users'); + return; + } + + // CSRF Protection + $this->verifyCsrf('/users'); + $userId = $params['id'] ?? 0; $user = $this->userModel->find($userId); diff --git a/app/Views/users/index.php b/app/Views/users/index.php index 8287ae2..3a3b7d1 100644 --- a/app/Views/users/index.php +++ b/app/Views/users/index.php @@ -273,15 +273,16 @@ $pagination = $pagination ?? [ - + title="" + onclick="toggleUserStatus(); return false;"> - + onclick="deleteUser(); return false;"> @@ -479,6 +480,40 @@ function bulkToggleStatus(action) { form.submit(); } +function toggleUserStatus(userId) { + const form = document.createElement('form'); + form.method = 'POST'; + form.action = '/users/' + userId + '/toggle-status'; + + const csrfInput = document.createElement('input'); + csrfInput.type = 'hidden'; + csrfInput.name = 'csrf_token'; + csrfInput.value = ''; + form.appendChild(csrfInput); + + document.body.appendChild(form); + form.submit(); +} + +function deleteUser(userId) { + if (!confirm('Are you sure you want to delete this user? This action cannot be undone.')) { + return; + } + + const form = document.createElement('form'); + form.method = 'POST'; + form.action = '/users/' + userId + '/delete'; + + const csrfInput = document.createElement('input'); + csrfInput.type = 'hidden'; + csrfInput.name = 'csrf_token'; + csrfInput.value = ''; + form.appendChild(csrfInput); + + document.body.appendChild(form); + form.submit(); +} + function bulkDeleteUsers() { const userIds = getSelectedUserIds();