From a5db81a73d5a4de8296d139ef84b8f6adebf8d16 Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Mon, 15 Jun 2026 16:16:02 +0200 Subject: [PATCH] fix: change adminOld return type from string to string|array The closure returned arrays when formData values were arrays (e.g. jury_promoteur), but the PHP return type annotation was :string. PHP 8.x enforces this strictly, causing a fatal TypeError in jury-fieldset.php on add mode. --- TODO.md | 6 ++++-- app/public/assets/js/app/file-upload-filepond.js | 13 +++++++++---- app/src/Form/FormBootstrap.php | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/TODO.md b/TODO.md index 6e5a3af..4882035 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ # TODO -> Last updated: 2026-06-11 -> Context: Removed overtype autosave (403 CSRF bug), replaced with explicit Save button above full-page editor +> Last updated: 2026-06-15 +> Context: Fix FilePond CSRF token staleness caused by autosave token rotation ## Pending @@ -12,6 +12,8 @@ ## Completed +- [x] #filepond-csrf-stale Fix FilePond CSRF token going stale when autosave rotates it — headers are now functions that re-read meta tag on each request `(file-upload-filepond.js)` ✓ + - [x] #csp-media-iframe-fix Fix CSP `frame-ancestors 'none'` blocking PDF iframes — replaced `try_files` redirect with direct `fastcgi_pass` in `location = /media` so `add_header` CSP override survives internal nginx redirect `(nginx/xamxam.conf)` ✓ - [x] #duration-migration Add migration to reintroduce `duration_value` and `duration_unit` columns + update views `(migrations/applied/040_duration_fields.sql)` ✓ diff --git a/app/public/assets/js/app/file-upload-filepond.js b/app/public/assets/js/app/file-upload-filepond.js index c3d9740..e92aa6b 100644 --- a/app/public/assets/js/app/file-upload-filepond.js +++ b/app/public/assets/js/app/file-upload-filepond.js @@ -245,7 +245,11 @@ process: { url: `${base}/process.php`, method: "POST", - headers: { "X-CSRF-Token": csrfToken }, + // Use a function for headers so the CSRF token is re-read + // from the meta tag on every request. The autosave handler + // rotates the token periodically and updates the meta tag; + // a static snapshot captured at init time would go stale. + headers: () => ({ "X-CSRF-Token": getCsrfToken() }), ondata: (formData) => { formData.append("queue_type", queueType); console.log(`[filepond] process ondata | queueType=${queueType}`); @@ -283,7 +287,8 @@ revert: { url: `${base}/revert.php`, method: "DELETE", - headers: { "X-CSRF-Token": csrfToken }, + // Re-read CSRF token on each request (same rationale as process). + headers: () => ({ "X-CSRF-Token": getCsrfToken() }), onload: () => { console.log("[filepond] revert OK"); }, @@ -320,7 +325,7 @@ if (/^[a-f0-9]{32}$/.test(source)) { fetch(`${base}/revert.php`, { method: "DELETE", - headers: { "X-CSRF-Token": csrfToken }, + headers: { "X-CSRF-Token": getCsrfToken() }, body: source, }) .then((r) => { @@ -343,7 +348,7 @@ method: "DELETE", headers: { "Content-Type": "application/json", - "X-CSRF-Token": csrfToken, + "X-CSRF-Token": getCsrfToken(), }, body: JSON.stringify({ db_id: source }), }) diff --git a/app/src/Form/FormBootstrap.php b/app/src/Form/FormBootstrap.php index e4e863a..54c8b8f 100644 --- a/app/src/Form/FormBootstrap.php +++ b/app/src/Form/FormBootstrap.php @@ -48,7 +48,7 @@ class FormBootstrap */ public static function adminOld(array &$formData): callable { - return function (string $key, string $default = '') use (&$formData): string { + return function (string $key, string $default = '') use (&$formData): string|array { if (!isset($formData[$key])) return $default; if (is_array($formData[$key])) return $formData[$key]; if ($formData[$key] === null) return $default;