mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
fix(mana/web/who): surface guestPrompt on JWT expiry
When the access token had aged out mid-game and the silent refresh failed (auth.mana.how/api/v1/auth/refresh → 401), the who store threw a raw "not authenticated" error and the PlayView showed a gibberish red banner. Confusing because the navbar still shows the user as logged in — the session cookie is intact, only the JWT is gone — so the user has no clue what to do. Match the base-client.ts pattern: when getAccessToken() returns null OR the upstream returns 401, fire guestPrompt.requireAccount() to surface the standard "Sitzung abgelaufen, neu anmelden" prompt in the bottom-bar slot, then throw a German error string so the inline error banner reads as "Sitzung abgelaufen — bitte neu anmelden" instead of "not authenticated". Hit by the developer mid-test on the first end-to-end live game on production: the chat had been working for ~5 messages, then the JWT expired and the game appeared to "die" with a cryptic message. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f9b83990c6
commit
59b5114348
1 changed files with 25 additions and 1 deletions
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import { db } from '$lib/data/database';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { guestPrompt } from '$lib/stores/guest-prompt.svelte';
|
||||
import { encryptRecord } from '$lib/data/crypto';
|
||||
import { whoGameTable, whoMessageTable } from '../collections';
|
||||
import type {
|
||||
|
|
@ -37,10 +38,25 @@ const API_BASE = '/api/v1/who';
|
|||
* this app — Bearer token from authStore, JSON body, structured
|
||||
* error throwing. Kept inline (no wrapping client) because the who
|
||||
* module has only three endpoints; a full client would be overkill.
|
||||
*
|
||||
* 401 handling: when the access token is missing OR the upstream
|
||||
* returns 401, we surface the standard `guestPrompt.requireAccount`
|
||||
* UI instead of throwing a raw "not authenticated" error. The
|
||||
* common case is JWT expiry mid-game — the session cookie is still
|
||||
* present (so the navbar still shows the user as logged in) but
|
||||
* the access token has aged out and the silent refresh failed.
|
||||
* Same pattern as base-client.ts uses for every other API call.
|
||||
*/
|
||||
async function postJson<T>(path: string, body: unknown): Promise<T> {
|
||||
const token = await authStore.getAccessToken();
|
||||
if (!token) throw new Error('not authenticated');
|
||||
if (!token) {
|
||||
guestPrompt.requireAccount(
|
||||
'who',
|
||||
'Sitzung abgelaufen — bitte neu anmelden, um weiterzuspielen.',
|
||||
'Neu anmelden'
|
||||
);
|
||||
throw new Error('Sitzung abgelaufen — bitte neu anmelden');
|
||||
}
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
@ -49,6 +65,14 @@ async function postJson<T>(path: string, body: unknown): Promise<T> {
|
|||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (res.status === 401) {
|
||||
guestPrompt.requireAccount(
|
||||
'who',
|
||||
'Sitzung abgelaufen — bitte neu anmelden, um weiterzuspielen.',
|
||||
'Neu anmelden'
|
||||
);
|
||||
throw new Error('Sitzung abgelaufen — bitte neu anmelden');
|
||||
}
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '');
|
||||
throw new Error(`who ${path} failed: ${res.status} ${text}`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue