fix(auth): a Google connect names its tab's account too, and a refused tab says why
- /auth/google/connect is a navigation and carries no headers: the tab names the account it was built for in `expect`, checked by the same comparison as the request header (built_for_another_account); a mismatch lands on /?account=changed - the link marker names the OAuth state of its own flow: an older flow coming back no longer spends the marker of the connect still open (which then returned as a plain sign-in) - a 401 account_changed reloads the tab with a one-time flag, and the reloaded tab says it now shows the account signed in - a refused switch to a suspended or not-yet-approved account says so in the signed-in app's words, naming the address a request was recorded for - the prefs merge locks FOR NO KEY UPDATE, so a transaction that only added a row referring to the account does not hold the save up; a test pins the lock - giving up a lost page closes a channel page open over it - e2e README names the chromium-only specs
This commit is contained in:
+10
-16
@@ -7,7 +7,8 @@ import { api, setUnauthorizedHandler, type Me } from "./lib/api";
|
||||
import { notifyActionError } from "./lib/actionErrors";
|
||||
import { setLanguage, type LangCode } from "./i18n";
|
||||
import { clearParams } from "./lib/urlState";
|
||||
import { refusedSwitchNotice } from "./lib/entryUrl";
|
||||
import { reloadAfterRefusal } from "./lib/entryUrl";
|
||||
import { useAccountSwitchNotice } from "./lib/useAccountSwitchNotice";
|
||||
import {
|
||||
PREF_KEY,
|
||||
saveLayoutLocal,
|
||||
@@ -231,26 +232,19 @@ export default function App() {
|
||||
if (signedIn) clearParams("access", "verify", "reset");
|
||||
}, [signedIn]);
|
||||
|
||||
// A sign-in as someone else that the server refused (an account not approved, or suspended) came
|
||||
// back here as the account still signed in — say so, once.
|
||||
const switchAnswered = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!signedIn || switchAnswered.current) return;
|
||||
switchAnswered.current = true;
|
||||
const notice = refusedSwitchNotice();
|
||||
if (notice) notify({ level: notice.level, message: t(notice.key) });
|
||||
}, [signedIn, t]);
|
||||
// A sign-in as someone else that the server refused, or a reload as another account: say so, once.
|
||||
useAccountSwitchNotice(signedIn);
|
||||
|
||||
// Any request that 401s means the session ended server-side. If we were signed in (cached
|
||||
// `me` is a user object), reload to the login page at once (also covers any click that hits
|
||||
// the API). Guarded on a cached user so a stray 401 while logged out (cached `me` is null)
|
||||
// can't loop the public landing.
|
||||
// can't loop the public landing. A tab showing another account than the one signed in now
|
||||
// reloads as that one instead, and says why (`reloadAfterRefusal`).
|
||||
useEffect(() => {
|
||||
setUnauthorizedHandler(() => {
|
||||
if (queryClient.getQueryData(qk.me())) {
|
||||
queryClient.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
setUnauthorizedHandler((err) => {
|
||||
if (!queryClient.getQueryData(qk.me())) return;
|
||||
queryClient.clear();
|
||||
reloadAfterRefusal(err);
|
||||
});
|
||||
return () => setUnauthorizedHandler(null);
|
||||
}, [queryClient]);
|
||||
|
||||
Reference in New Issue
Block a user