fix(frontend): Session-Timeout ausgeloggt statt in kaputtem Zustand stecken
401 bei abgelaufenem Token wurde nirgends erkannt - "eingeloggt" blieb true, Hard-Reload half nicht, da der abgelaufene Token weiter in localStorage lag und /auth/me erneut mit 401 scheiterte (gleicher Zustand auf derselben URL). apiRequest ruft jetzt bei echtem Session-Timeout einen von AuthProvider registrierten Handler auf, der korrekt auf logout() setzt - Router-Guard leitet danach automatisch zu /login um. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDMvneg6wKfXdXvTYNd3dN
This commit is contained in:
1 parent
c8d9480cf9
commit
9312d6a17c
4 files changed
+117
-1
No files matched your search
@@ -14999,3 +14999,73 @@ Keine Commits in dieser Session.
|
||||
- flutter_app/test/offline_queue_test.dart | 6 ++++
|
||||
|
||||
---
|
||||
## 2026-09-12 22:21 – 22:23 (1m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** asb-material
|
||||
|
||||
### Commits
|
||||
- c8d9480 perf(mangel): Foto-Kompression vor Upload in beiden Clients ergänzt
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
## 2026-09-12 22:23 – 22:24 (0m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** asb-material
|
||||
|
||||
### Commits
|
||||
Keine Commits in dieser Session.
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
## 2026-09-12 22:24 – 22:24 (0m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** asb-material
|
||||
|
||||
### Commits
|
||||
Keine Commits in dieser Session.
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
## 2026-09-12 22:28 – 22:28 (0m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** asb-material
|
||||
|
||||
### Commits
|
||||
Keine Commits in dieser Session.
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
## 2026-09-12 22:32 – 22:33 (0m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** frontend
|
||||
|
||||
### Commits
|
||||
Keine Commits in dieser Session.
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
@@ -1292,3 +1292,17 @@ Keine Commits in dieser Session.
|
||||
- frontend/src/pages/admin/objektZeileTypen.ts | 43 ++++++++++++
|
||||
|
||||
---
|
||||
## 2026-09-12 22:30 – 22:31 (1m)
|
||||
**Beschreibung:** Claude Code Session
|
||||
**Projekt:** asb-material
|
||||
|
||||
### Commits
|
||||
Keine Commits in dieser Session.
|
||||
|
||||
### Geänderte Dateien
|
||||
- DEVLOG.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
- flutter_app/lib/screens/mangel_melden_screen.dart | 12 +++-
|
||||
- frontend/src/offline/fotoKomprimierung.ts | 34 ++++++++++++
|
||||
- frontend/src/pages/MangelListePage.tsx | 6 +-
|
||||
|
||||
---
|
||||
@@ -15,6 +15,19 @@ export function getAuthToken(): string | null {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
// Bug-Fund: Session-Timeout (Token abgelaufen) wurde bisher NIRGENDS erkannt -
|
||||
// apiRequest warf zwar ApiError(401), aber "eingeloggt" im AuthContext blieb
|
||||
// true, da niemand darauf reagierte. Ein Hard-Reload half nicht, weil der
|
||||
// (abgelaufene) Token weiter in localStorage lag und /auth/me erneut mit 401
|
||||
// scheiterte - derselbe kaputte Zustand auf derselben URL. AuthProvider trägt
|
||||
// sich hier als Handler ein, um bei echtem Session-Timeout (nicht beim
|
||||
// Login-Versuch selbst, siehe Ausschluss in apiRequest) auszuloggen.
|
||||
let unauthorizedHandler: (() => void) | null = null;
|
||||
|
||||
export function setUnauthorizedHandler(handler: (() => void) | null): void {
|
||||
unauthorizedHandler = handler;
|
||||
}
|
||||
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
detail: unknown;
|
||||
@@ -55,6 +68,11 @@ export async function apiRequest<T>(path: string, options: RequestOptions = {}):
|
||||
} catch {
|
||||
// Antwort ohne JSON-Body (z. B. 204) - detail bleibt null.
|
||||
}
|
||||
// Nur bei tatsächlich gesendetem Token auslösen - ein 401 ohne Token
|
||||
// (z.B. noch vor dem Login) ist kein Session-Timeout.
|
||||
if (response.status === 401 && authToken) {
|
||||
unauthorizedHandler?.();
|
||||
}
|
||||
throw new ApiError(response.status, detail);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from "react";
|
||||
|
||||
import { apiRequest, getAuthToken, login as apiLogin, setAuthToken } from "../api/client";
|
||||
import {
|
||||
apiRequest,
|
||||
getAuthToken,
|
||||
login as apiLogin,
|
||||
setAuthToken,
|
||||
setUnauthorizedHandler,
|
||||
} from "../api/client";
|
||||
import type { Me } from "../api/types";
|
||||
|
||||
interface AuthContextValue {
|
||||
@@ -69,6 +75,14 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
[eingeloggt, rollenGeladen, rollen]
|
||||
);
|
||||
|
||||
// Bug-Fund: Session-Timeout wurde bisher nicht erkannt - siehe Kommentar in
|
||||
// api/client.ts. Registrierung statt direktem Aufruf in apiRequest, da
|
||||
// apiRequest außerhalb des React-Baums liegt und keinen Hook-Zugriff hat.
|
||||
useEffect(() => {
|
||||
setUnauthorizedHandler(value.logout);
|
||||
return () => setUnauthorizedHandler(null);
|
||||
}, [value.logout]);
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user