fix: resolve auth:expired race condition and force SW cache refresh

- Add _pendingLoginRedirect flag in router.js to handle auth:expired
  events that fire during active navigation (isNavigating=true).
  Previously the navigate('/login') call was silently dropped, leaving
  the user stuck on the dashboard with an error toast.
- Bump SHELL_CACHE v33→v34 and PAGES_CACHE v28→v29 to force cache
  invalidation on iOS devices still running the pre-CSRF-fix code.
- Add err.status to dashboard error log for easier diagnostics.
This commit is contained in:
Ulas
2026-04-16 08:15:04 +02:00
parent dfd809c284
commit fc6e4fb9f2
3 changed files with 20 additions and 4 deletions
+1 -1
View File
@@ -655,7 +655,7 @@ export async function render(container, { user }) {
weather = weatherRes.data ?? null;
widgetConfig = prefsRes.data?.dashboard_widgets ?? DEFAULT_WIDGET_CONFIG;
} catch (err) {
console.error('[Dashboard] Ladefehler:', err.message);
console.error('[Dashboard] Ladefehler:', err.message, 'Status:', err.status ?? 'network');
window.oikos?.showToast(t('dashboard.loadError'), 'warning');
}
+17 -1
View File
@@ -115,6 +115,9 @@ async function importPage(pagePath) {
let currentUser = null;
let currentPath = null;
let isNavigating = false;
// Gesetzt wenn auth:expired waehrend einer laufenden Navigation feuert.
// Die Weiterleitung zu /login wird nach Abschluss der Navigation nachgeholt.
let _pendingLoginRedirect = false;
// --------------------------------------------------------
// Router
@@ -189,6 +192,13 @@ async function navigate(path, userOrPushState = true, pushState = true) {
updateThemeColorForRoute(route);
} finally {
isNavigating = false;
// auth:expired kann waehrend einer Navigation gefeuert haben (z.B. wenn ein
// paralleler API-Call 401 zurueckgab). Jetzt wo die Navigation abgeschlossen
// ist, holen wir die Login-Weiterleitung nach.
if (_pendingLoginRedirect) {
_pendingLoginRedirect = false;
navigate('/login');
}
}
}
@@ -511,7 +521,13 @@ window.addEventListener('popstate', (e) => {
window.addEventListener('auth:expired', () => {
currentUser = null;
stopReminders();
navigate('/login');
if (isNavigating) {
// navigate('/login') kann nicht sofort aufgerufen werden - wird im finally-Block
// der laufenden Navigation nachgeholt.
_pendingLoginRedirect = true;
} else {
navigate('/login');
}
});
// Sprache geändert: Navigation neu rendern damit Labels aktualisiert werden
+2 -2
View File
@@ -12,8 +12,8 @@
* API: Immer Netzwerk (kein Caching von Nutzerdaten)
*/
const SHELL_CACHE = 'oikos-shell-v33';
const PAGES_CACHE = 'oikos-pages-v28';
const SHELL_CACHE = 'oikos-shell-v34';
const PAGES_CACHE = 'oikos-pages-v29';
const ASSETS_CACHE = 'oikos-assets-v27';
const ALL_CACHES = [SHELL_CACHE, PAGES_CACHE, ASSETS_CACHE];