mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 17:29:55 -05:00
Fix: Re-Try UI Login Token + GQL Wait
This commit is contained in:
+38
-19
@@ -4,6 +4,19 @@ import { boot } from "@store/boot.svelte";
|
|||||||
|
|
||||||
const DEFAULT_URL = "http://127.0.0.1:4567";
|
const DEFAULT_URL = "http://127.0.0.1:4567";
|
||||||
|
|
||||||
|
type ReauthResolver = () => void;
|
||||||
|
let _reauthQueue: ReauthResolver[] = [];
|
||||||
|
|
||||||
|
export function notifyReauthSuccess() {
|
||||||
|
const queue = _reauthQueue;
|
||||||
|
_reauthQueue = [];
|
||||||
|
queue.forEach(resolve => resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForReauth(): Promise<void> {
|
||||||
|
return new Promise(resolve => { _reauthQueue.push(resolve); });
|
||||||
|
}
|
||||||
|
|
||||||
export function getServerUrl(): string {
|
export function getServerUrl(): string {
|
||||||
const url = store.settings.serverUrl;
|
const url = store.settings.serverUrl;
|
||||||
return typeof url === "string" && url.trim() ? url.replace(/\/$/, "") : DEFAULT_URL;
|
return typeof url === "string" && url.trim() ? url.replace(/\/$/, "") : DEFAULT_URL;
|
||||||
@@ -95,24 +108,30 @@ export async function gql<T>(
|
|||||||
variables?: Record<string, unknown>,
|
variables?: Record<string, unknown>,
|
||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const res = await fetchWithRetry(
|
const attempt = async (): Promise<T> => {
|
||||||
`${getServerUrl()}/api/graphql`,
|
const res = await fetchWithRetry(
|
||||||
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables }) },
|
`${getServerUrl()}/api/graphql`,
|
||||||
signal,
|
{ method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, variables }) },
|
||||||
);
|
signal,
|
||||||
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
);
|
||||||
if (!res.ok) throw new Error(`Suwayomi HTTP ${res.status}`);
|
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
||||||
const json: GQLResponse<T> = await res.json();
|
if (!res.ok) throw new Error(`Suwayomi HTTP ${res.status}`);
|
||||||
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
const json: GQLResponse<T> = await res.json();
|
||||||
if (json.errors?.length) {
|
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
||||||
const isAuthError = json.errors.some(e => /unauthorized|unauthenticated/i.test(e.message));
|
if (json.errors?.length) {
|
||||||
if (isAuthError && !boot.skipped) {
|
const isAuthError = json.errors.some(e => /unauthorized|unauthenticated/i.test(e.message));
|
||||||
boot.sessionExpired = true;
|
if (isAuthError && !boot.skipped) {
|
||||||
boot.loginRequired = true;
|
boot.sessionExpired = true;
|
||||||
boot.loginUser = store.settings.serverAuthUser ?? "";
|
boot.loginRequired = true;
|
||||||
throw new AuthRequiredError(json.errors[0].message);
|
boot.loginUser = store.settings.serverAuthUser ?? "";
|
||||||
|
await waitForReauth();
|
||||||
|
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
||||||
|
return attempt();
|
||||||
|
}
|
||||||
|
throw new Error(json.errors[0].message);
|
||||||
}
|
}
|
||||||
throw new Error(json.errors[0].message);
|
return json.data;
|
||||||
}
|
};
|
||||||
return json.data;
|
|
||||||
|
return attempt();
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import { store } from "@store/state.svelte";
|
|||||||
import { probeServer, loginBasic, loginUI } from "@core/auth";
|
import { probeServer, loginBasic, loginUI } from "@core/auth";
|
||||||
import { trackingState } from "@features/tracking/store/trackingState.svelte";
|
import { trackingState } from "@features/tracking/store/trackingState.svelte";
|
||||||
import { loadAllStores } from "@core/persistence/persist";
|
import { loadAllStores } from "@core/persistence/persist";
|
||||||
|
import { notifyReauthSuccess } from "@api/client";
|
||||||
|
|
||||||
const MAX_ATTEMPTS = 40;
|
const MAX_ATTEMPTS = 40;
|
||||||
|
|
||||||
@@ -107,6 +108,7 @@ export async function submitLogin(onSuccess: () => void): Promise<void> {
|
|||||||
boot.skipped = false;
|
boot.skipped = false;
|
||||||
boot.loginPass = "";
|
boot.loginPass = "";
|
||||||
boot.loginError = null;
|
boot.loginError = null;
|
||||||
|
notifyReauthSuccess();
|
||||||
trackingState.bootSync().catch(() => {});
|
trackingState.bootSync().catch(() => {});
|
||||||
onSuccess();
|
onSuccess();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user