Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 108x 1x 1x 19x 19x 19x 2x 19x | /**
* Logout-reason hand-off (Story 12.8 finding F5, 2026-06-04).
*
* When the gateway returns 403 ACCOUNT_DEACTIVATED, the apiClient interceptor forces a
* sign-out and routes to `/login?reason=account_deactivated`. For a FEDERATED session,
* however, Amplify `signOut()` performs a full-page redirect to the Cognito hosted-UI
* `/logout` endpoint — clobbering that in-app navigation (and its query param). This tiny
* sessionStorage hand-off carries the reason across the Cognito logout round-trip
* (sessionStorage is per-tab and survives cross-origin navigation away and back):
*
* apiClient (403) ── setLogoutReason ──▶ Cognito /logout ──▶ /logout (LogoutPage)
* │ consumeLogoutReason → /login?reason=…
* └─▶ in-app /login (native sessions / no redirect) — LoginForm consumeLogoutReason
*
* Both LoginForm and LogoutPage consume (whichever lands first wins); the flag is only
* ever set by the deactivated-account path, so a consumed-but-unused flag is harmless.
*/
const KEY = 'batbern.logout-reason';
export type LogoutReason = 'account_deactivated';
export function setLogoutReason(reason: LogoutReason): void {
try {
sessionStorage.setItem(KEY, reason);
} catch {
// Storage unavailable (private mode / quota) — non-fatal, the in-app
// `/login?reason=…` navigation still covers the non-redirect path.
}
}
export function consumeLogoutReason(): LogoutReason | null {
try {
const value = sessionStorage.getItem(KEY);
if (value !== null) {
sessionStorage.removeItem(KEY);
}
return value as LogoutReason | null;
} catch {
return null;
}
}
|