From aafb1877aeb7f30440572cf82b107b2c3912f3f8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 24 Apr 2026 23:24:46 +0300 Subject: [PATCH] fix(admin): add CSRF token to admin user management operations (#1065) Fixes #1064 Admin user operations (create, update, delete, toggle registration) were failing with "CSRF token missing" error when accessed behind a reverse proxy. This happened because the frontend was using plain fetch() instead of fetchWithCsrf() utility which automatically includes the CSRF token header. Changed all state-changing operations in AdminUsersPage to use fetchWithCsrf: - createAdminUser (POST /admin/users) - updateAdminUser (PUT /admin/users/:id) - deleteAdminUser (DELETE /admin/users/:id) - toggleRegistration (POST /admin/toggle-registration) --- frontend/components/Admin/AdminUsersPage.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/components/Admin/AdminUsersPage.tsx b/frontend/components/Admin/AdminUsersPage.tsx index 25a89f0..e370a1f 100644 --- a/frontend/components/Admin/AdminUsersPage.tsx +++ b/frontend/components/Admin/AdminUsersPage.tsx @@ -10,6 +10,7 @@ import { import ConfirmDialog from '../Shared/ConfirmDialog'; import { getApiPath } from '../../config/paths'; import { useToast } from '../Shared/ToastContext'; +import { fetchWithCsrf } from '../../utils/csrfService'; interface AdminUserItem { id: number; @@ -43,7 +44,7 @@ const createAdminUser = async ( surname?: string, role?: 'admin' | 'user' ): Promise => { - const res = await fetch(getApiPath('admin/users'), { + const res = await fetchWithCsrf(getApiPath('admin/users'), { method: 'POST', credentials: 'include', headers: { @@ -84,7 +85,7 @@ const updateAdminUser = async ( const body: any = { email, name, surname, role }; if (password) body.password = password; - const res = await fetch(getApiPath(`admin/users/${id}`), { + const res = await fetchWithCsrf(getApiPath(`admin/users/${id}`), { method: 'PUT', credentials: 'include', headers: { @@ -116,7 +117,7 @@ const updateAdminUser = async ( }; const deleteAdminUser = async (id: number, t: any): Promise => { - const res = await fetch(getApiPath(`admin/users/${id}`), { + const res = await fetchWithCsrf(getApiPath(`admin/users/${id}`), { method: 'DELETE', credentials: 'include', headers: { Accept: 'application/json' }, @@ -466,7 +467,7 @@ const AdminUsersPage: React.FC = () => { // Toggle registration const toggleRegistration = async () => { try { - const res = await fetch(getApiPath('admin/toggle-registration'), { + const res = await fetchWithCsrf(getApiPath('admin/toggle-registration'), { method: 'POST', credentials: 'include', headers: {