Web: abgelaufene Anmeldung erkennen statt leere Seiten zeigen

Zwei Defekte, die zusammen das gemeldete Muster ergeben.

1) Es gab keine zentrale Behandlung von HTTP 401. AuthProvider prueft die
Anmeldung EINMAL beim Start; laeuft das Token danach ab, bleibt der Zustand
"angemeldet" stehen, waehrend jede Abfrage scheitert. Seiten mit
.catch(() => {}) (18 Stellen) zeigen dann schlicht nichts, andere eine
englische Servermeldung - genau das "mal gar nichts, mal die Haelfte".
Jetzt raeumt der API-Client bei 401 die Sitzung auf und der Login sagt, dass
sie abgelaufen ist. Beim Anmelden selbst greift das nicht, dort heisst 401
"Passwort falsch".

2) Der Start hatte ein blankes `catch`, das das Token bei JEDEM Fehler loeschte -
auch bei 502 oder weggebrochenem Netz. Wer waehrend eines Server-Neustarts F5
drueckte, war deshalb abgemeldet, obwohl die Sitzung voellig in Ordnung war.
Das duerfte der haeufigere Ausloeser gewesen sein, weil in letzter Zeit oft neu
deployt wurde. Jetzt wird nur bei 401/403 abgemeldet; bei allem anderen bleibt
die Anmeldung liegen und es erscheint "Server nicht erreichbar" mit einem
Knopf zum erneuten Versuchen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-08-16 11:07:55 +02:00
co-authored by Claude Opus 5
parent 01c93d8b2c
commit eddbb3710e
4 changed files with 97 additions and 13 deletions
+23 -1
View File
@@ -115,9 +115,31 @@ function Sidebar() {
);
}
/** Server nicht erreichbar – die Anmeldung bleibt bestehen, nur der Abruf nicht. */
function StartFehler({ text, erneut }) {
return (
<div className="center" style={{ padding: 60 }}>
<div className="alert error" style={{ maxWidth: 520 }}>
<Icon name="alert" size={16} />
<div>
<div>{text}</div>
<div className="muted small" style={{ marginTop: 4 }}>
Deine Anmeldung ist noch gültig – sobald der Server wieder antwortet,
geht es weiter.
</div>
</div>
</div>
<button className="btn primary" style={{ marginTop: 16 }} onClick={erneut}>
Erneut versuchen
</button>
</div>
);
}
function Protected({ children, adminOnly = false, wide = false }) {
const { user, isAdmin, loading } = useAuth();
const { user, isAdmin, loading, startFehler, erneutVersuchen } = useAuth();
if (loading) return <div className="center muted" style={{ padding: 60 }}>Lädt…</div>;
if (startFehler) return <StartFehler text={startFehler} erneut={erneutVersuchen} />;
if (!user) return <Navigate to="/login" replace />;
if (adminOnly && !isAdmin) return <Navigate to="/" replace />;
return (