mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 22:26:13 +00:00
fix(auth): leave for single sign-on even when the cache wipe hangs
The sign-in page and the profile take-over page waited for the offline copies to be cleared before leaving for the identity provider, with no limit. WebKit can leave an IndexedDB open unsettled after the installed app returns from the background, and the button then did nothing. The wait is now capped at one and a half seconds.
This commit is contained in:
1 parent
444e1eaca8
commit
12a23bf779
3 files changed
+38
-4
No files matched your search
@@ -63,6 +63,21 @@ describe("sign-in page, single sign-on", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("sign-in page, single sign-on with a stuck cache", () => {
|
||||
it("still leaves for the identity provider when the wipe never settles", async () => {
|
||||
// WebKit can leave an IndexedDB open hanging after the app returns from
|
||||
// the background; the button did nothing then.
|
||||
clearOffline.mockImplementationOnce(() => new Promise(() => {}));
|
||||
const { screen } = await renderWithApp(<LoginPage />, { user: null });
|
||||
await screen.getByRole("button", { name: "Example ID" }).click();
|
||||
|
||||
await expect
|
||||
.poll(() => loadDocument.mock.calls.length, { timeout: 4000 })
|
||||
.toBe(1);
|
||||
expect(clearOffline).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sign-in page, password", () => {
|
||||
it("replaces itself with the page asked for", async () => {
|
||||
api.on("POST", "/api/auth/login", { data: { id: "signed-in" } });
|
||||
|
||||
@@ -24,6 +24,7 @@ import { OIDC_MFA_COOKIE, OIDC_MFA_COOKIE_PATH } from "@/lib/auth/oidc-cookie";
|
||||
import { isDashboardSnapshotEnabled } from "@/lib/dashboard/snapshot-flag";
|
||||
import { prefetchDashboardSnapshot } from "@/lib/queries/use-dashboard-snapshot";
|
||||
import { clearOfflineCachesForSessionEnd } from "@/lib/pwa/query-persister";
|
||||
import { settleWithin } from "@/lib/async/settle-within";
|
||||
import { sanitizeSameOriginPath } from "@/lib/url-safety";
|
||||
import { localizedSignInError } from "@/lib/api/localized-error";
|
||||
import { formatDate } from "@/lib/format";
|
||||
@@ -51,6 +52,9 @@ function deletionPendingMessage(t: Translate, purgeAt: unknown): string {
|
||||
: t("auth.deletionPendingNoDate");
|
||||
}
|
||||
|
||||
/** How long the single-sign-on start waits for the offline copies to go. */
|
||||
const SSO_CLEANUP_WAIT_MS = 1_500;
|
||||
|
||||
/** The message for the `?error=` a sign-in redirect (the SSO callback) set. */
|
||||
function signInRedirectError(
|
||||
searchParams: URLSearchParams,
|
||||
@@ -183,8 +187,14 @@ export default function LoginPage() {
|
||||
params.set("client_proto", clientTransport.protocol);
|
||||
params.set("client_host", clientTransport.host);
|
||||
}
|
||||
// The session starts on the way back; the last account's copies go first.
|
||||
await clearOfflineCachesForSessionEnd();
|
||||
// The session starts on the way back; the last account's copies go
|
||||
// first. Bounded: WebKit can leave an IndexedDB open hanging after the
|
||||
// app returns from the background, and the button must still work.
|
||||
await settleWithin(
|
||||
clearOfflineCachesForSessionEnd(),
|
||||
SSO_CLEANUP_WAIT_MS,
|
||||
undefined,
|
||||
);
|
||||
loadDocument(`/api/auth/oidc/login?${params}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,16 @@ import { showErrorToast } from "@/lib/errors/error-toast";
|
||||
import { useFormatters, useTranslations } from "@/lib/i18n/context";
|
||||
import { loadDocument } from "@/lib/navigation/load-document";
|
||||
import { clearOfflineCachesForSessionEnd } from "@/lib/pwa/query-persister";
|
||||
import { settleWithin } from "@/lib/async/settle-within";
|
||||
import {
|
||||
useClaimProfile,
|
||||
useClaimProfileSso,
|
||||
useProfileClaimPreview,
|
||||
} from "@/lib/queries/use-profile-claim";
|
||||
|
||||
/** How long the single-sign-on claim waits for the offline copies to go. */
|
||||
const SSO_CLEANUP_WAIT_MS = 1_500;
|
||||
|
||||
/**
|
||||
* v1.42 (#959) — the person a managed profile describes takes it over as
|
||||
* their own account (`/auth/claim?token=hlp_…`).
|
||||
@@ -111,8 +115,13 @@ export function ClaimProfile({
|
||||
next.searchParams.set("client_proto", clientTransport.protocol);
|
||||
next.searchParams.set("client_host", clientTransport.host);
|
||||
}
|
||||
// The session starts on the way back; the last account's copies go first.
|
||||
await clearOfflineCachesForSessionEnd();
|
||||
// The session starts on the way back; the last account's copies
|
||||
// go first, waited on no longer than on the sign-in page.
|
||||
await settleWithin(
|
||||
clearOfflineCachesForSessionEnd(),
|
||||
SSO_CLEANUP_WAIT_MS,
|
||||
undefined,
|
||||
);
|
||||
loadDocument(`${next.pathname}${next.search}`);
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user