From 835bdf5abb40c7b143c5cdafb507c317a7c349bf Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Thu, 9 Apr 2026 13:54:23 +0200 Subject: [PATCH] fix: resolve password change redirect loop and file watcher crash #263: The mandatory password change modal updated React state before the browser stored the new JWT cookie, causing a race condition where the auth context checked the session with the old (invalidated) token. Replace the state update with a full page redirect to /admin/dashboard after a brief delay, ensuring the new cookie is applied cleanly. #269: The file watcher service imported isVideoMimeType from fileSecurityUtils where it doesn't exist. The function is exported from videoProcessor. Fix the import path. Closes #269 --- backend/src/services/fileWatcher.js | 2 +- .../admin/MandatoryPasswordChangeModal.tsx | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/services/fileWatcher.js b/backend/src/services/fileWatcher.js index b118d543..4f073868 100644 --- a/backend/src/services/fileWatcher.js +++ b/backend/src/services/fileWatcher.js @@ -5,7 +5,7 @@ const { db } = require('../database/db'); const { formatBoolean } = require('../utils/dbCompat'); const { generateThumbnail, generateVideoPlaceholder } = require('./imageProcessor'); const logger = require('../utils/logger'); -const { isVideoMimeType } = require('../utils/fileSecurityUtils'); +const { isVideoMimeType } = require('./videoProcessor'); const mime = require('mime-types'); const getStoragePath = () => process.env.STORAGE_PATH || path.join(__dirname, '../../../storage'); diff --git a/frontend/src/components/admin/MandatoryPasswordChangeModal.tsx b/frontend/src/components/admin/MandatoryPasswordChangeModal.tsx index bb71b3de..1f2bc88f 100644 --- a/frontend/src/components/admin/MandatoryPasswordChangeModal.tsx +++ b/frontend/src/components/admin/MandatoryPasswordChangeModal.tsx @@ -27,14 +27,12 @@ export const MandatoryPasswordChangeModal: React.FC = () => { mutationFn: adminService.changePassword, onSuccess: () => { toast.success(t('mandatoryPasswordChange.success')); - updatePasswordChanged(); - // Reset form - setFormData({ - currentPassword: '', - newPassword: '', - confirmPassword: '' - }); - setErrors({}); + // Force a full page reload so the browser picks up the new JWT cookie + // set by the backend. A React state update alone causes a race condition + // where the auth context checks the session before the cookie is stored. + setTimeout(() => { + window.location.href = '/admin/dashboard'; + }, 500); }, onError: (error: any) => { if (error.response?.data?.error) {