From a9b08bdc6eb46ed4f48ebe2e6a7da07ca4a362bb Mon Sep 17 00:00:00 2001 From: Vladimir Tomashevskiy Date: Sun, 8 Feb 2026 16:28:16 +0000 Subject: [PATCH] Fix CSRF token in POST body for AJAX requests - Add csrf_token parameter to fetch() body - CodeIgniter 4 CSRF filter requires token in POST body, not just headers --- app/Modules/Tasks/Views/tasks/show.twig | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/Modules/Tasks/Views/tasks/show.twig b/app/Modules/Tasks/Views/tasks/show.twig index e661b54..0963df9 100644 --- a/app/Modules/Tasks/Views/tasks/show.twig +++ b/app/Modules/Tasks/Views/tasks/show.twig @@ -235,12 +235,15 @@ function addSubtask(event, taskId) { if (!title) return; + // Получаем CSRF токен из формы + const csrfToken = form.querySelector('input[name="csrf_token"]').value; + fetch(`/tasks/${taskId}/subtasks`, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', }, - body: 'title=' + encodeURIComponent(title) + body: 'title=' + encodeURIComponent(title) + '&csrf_token=' + csrfToken }) .then(response => response.json()) .then(data => { @@ -289,11 +292,16 @@ function updateSubtasksCount() { } function toggleSubtask(taskId, subtaskId) { + // Получаем CSRF токен из формы на странице + const csrfForm = document.querySelector('form[action*="/tasks/' + taskId + '"]'); + const csrfToken = csrfForm ? csrfForm.querySelector('input[name="csrf_token"]').value : ''; + fetch(`/tasks/${taskId}/subtasks/${subtaskId}/toggle`, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', - } + }, + body: 'csrf_token=' + csrfToken }) .then(response => response.json()) .then(data => { @@ -301,7 +309,6 @@ function toggleSubtask(taskId, subtaskId) { alert(data.error || 'Ошибка'); location.reload(); } else { - // Перезагружаем страницу для обновления UI location.reload(); } }) @@ -314,11 +321,16 @@ function toggleSubtask(taskId, subtaskId) { function deleteSubtask(taskId, subtaskId) { if (!confirm('Удалить подзадачу?')) return; + // Получаем CSRF токен из формы на странице + const csrfForm = document.querySelector('form[action*="/tasks/' + taskId + '"]'); + const csrfToken = csrfForm ? csrfForm.querySelector('input[name="csrf_token"]').value : ''; + fetch(`/tasks/${taskId}/subtasks/${subtaskId}/delete`, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', - } + }, + body: 'csrf_token=' + csrfToken }) .then(response => response.json()) .then(data => {