fix(auth): stop the re-login dialog hijacking the login screen
Nightly Build / build (push) Successful in 8m11s
Nightly Build / build (push) Successful in 8m11s
On a cold load with no session, both shells mount every component before their boot auth check resolves, so a dozen gated /api calls 401 in parallel and the fetch watch raised the re-login dialog over the login screen the boot check was about to show (.relogin-backdrop is z-10000, .login-page z-9999). The user typed their password into the modal, which only closes itself on success — revealing the login page still up with the app hidden, so they were asked a second time and only a manual reload got them in. The dialog is for a session that dies under an open tab, so gate it on one having ever been established. Recognising that is passive, in the same fetch wrapper: mobile.html probes /api/auth/me from a classic inline script that runs before this module exists, so an explicit marker per shell would never fire there and the dialog would be dead on mobile. Any 2xx from a gated endpoint proves a session; only the routes guard.rs::is_public lets through unauthenticated are excluded. Knock-on: with the report now a no-op on a cold load, the chat's reconnect loop no longer stopped on it. Retry only in the native shell, which authenticates on its own — everywhere else something is already asking for a password.
This commit is contained in:
+10
-4
@@ -2,7 +2,7 @@ import { html, nothing } from 'lit';
|
||||
import { LightElement } from './base.js';
|
||||
import { InboxCardsMixin } from './inbox-cards.js';
|
||||
import { t } from './i18n.js';
|
||||
import { isSessionExpired, notifySessionExpired, probeSession } from './session-expiry.js';
|
||||
import { isSessionExpired, isNativeShell, notifySessionExpired, probeSession } from './session-expiry.js';
|
||||
|
||||
// Slash commands handled entirely server-side: they reply with a `Done` and never
|
||||
// echo back as a `user_message`, so they are the only commands rendered
|
||||
@@ -492,9 +492,15 @@ export class ChatSession extends InboxCardsMixin(LightElement) {
|
||||
if (isSessionExpired()) return; // the dialog is already up
|
||||
if ((await probeSession()) === 'expired') {
|
||||
notifySessionExpired();
|
||||
// A shell that handles auth itself (native mobile) ignores the report;
|
||||
// there is no dialog coming, so keep retrying as before.
|
||||
if (isSessionExpired()) return;
|
||||
// Only the native shell keeps retrying: it authenticates in the background,
|
||||
// so a refused upgrade there really can be transient. Everywhere else the
|
||||
// server has just told us this browser is nobody, and something is already
|
||||
// asking for a password — the re-login dialog if a session died under the
|
||||
// tab, or the shell's boot check showing the login screen on a cold load
|
||||
// (where `notifySessionExpired` is deliberately a no-op). Retrying past
|
||||
// that is pure noise; the socket comes back on `auth-restored`, or the
|
||||
// login page reloads the whole page.
|
||||
if (!isNativeShell()) return;
|
||||
}
|
||||
setTimeout(() => this._connectWS(), 2000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user