mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 01:09:56 -05:00
79 lines
3.0 KiB
TypeScript
79 lines
3.0 KiB
TypeScript
import { store, updateSettings } from "@store/state.svelte";
|
|
|
|
export type AuthMode = "NONE" | "BASIC_AUTH" | "SIMPLE_LOGIN" | "UI_LOGIN";
|
|
|
|
export const authSession = {
|
|
clearTokens() {},
|
|
hasSession(): boolean { return true; },
|
|
};
|
|
|
|
function getServerBase(): string {
|
|
const url = store.settings.serverUrl;
|
|
return typeof url === "string" && url.trim() ? url.replace(/\/$/, "") : "http://127.0.0.1:4567";
|
|
}
|
|
|
|
function basicHeader(user: string, pass: string): Record<string, string> {
|
|
return { Authorization: `Basic ${btoa(`${user}:${pass}`)}` };
|
|
}
|
|
|
|
export function fetchAuthenticated(url: string, init: RequestInit, signal?: AbortSignal): Promise<Response> {
|
|
const mode = store.settings.serverAuthMode ?? "NONE";
|
|
if (mode === "BASIC_AUTH") {
|
|
const user = store.settings.serverAuthUser?.trim() ?? "";
|
|
const pass = store.settings.serverAuthPass?.trim() ?? "";
|
|
return fetch(url, {
|
|
...init, signal, credentials: "omit",
|
|
headers: { ...(init.headers as Record<string, string> ?? {}), ...(user && pass ? basicHeader(user, pass) : {}) },
|
|
});
|
|
}
|
|
return fetch(url, { ...init, signal, credentials: "omit" });
|
|
}
|
|
|
|
export async function loginBasic(user: string, pass: string): Promise<void> {
|
|
const res = await fetch(`${getServerBase()}/api/graphql`, {
|
|
method: "POST", credentials: "omit",
|
|
headers: { "Content-Type": "application/json", ...basicHeader(user, pass) },
|
|
body: JSON.stringify({ query: "{ __typename }" }),
|
|
signal: AbortSignal.timeout(5000),
|
|
});
|
|
if (!res.ok) throw new Error(`Authentication failed (${res.status})`);
|
|
updateSettings({ serverAuthMode: "BASIC_AUTH", serverAuthUser: user, serverAuthPass: pass });
|
|
}
|
|
|
|
export async function logout(): Promise<void> {
|
|
updateSettings({ serverAuthPass: "" });
|
|
}
|
|
|
|
export async function probeServer(): Promise<"ok" | "auth_required" | "unsupported_mode" | "unreachable"> {
|
|
const base = getServerBase();
|
|
const mode = store.settings.serverAuthMode ?? "NONE";
|
|
const s = store.settings;
|
|
try {
|
|
const headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
if (mode === "BASIC_AUTH") {
|
|
const user = s.serverAuthUser?.trim() ?? "";
|
|
const pass = s.serverAuthPass?.trim() ?? "";
|
|
if (user && pass) Object.assign(headers, basicHeader(user, pass));
|
|
}
|
|
const res = await fetch(`${base}/api/graphql`, {
|
|
method: "POST", credentials: "omit", headers,
|
|
body: JSON.stringify({ query: "{ __typename }" }),
|
|
signal: AbortSignal.timeout(5000),
|
|
});
|
|
if (res.ok) return "ok";
|
|
if (res.status === 401) {
|
|
const wwwAuth = res.headers.get("WWW-Authenticate") ?? "";
|
|
if (/basic/i.test(wwwAuth)) {
|
|
if (mode !== "BASIC_AUTH") updateSettings({ serverAuthMode: "BASIC_AUTH" });
|
|
return "auth_required";
|
|
}
|
|
if (/bearer/i.test(wwwAuth)) {
|
|
if (mode !== "UI_LOGIN") updateSettings({ serverAuthMode: "UI_LOGIN" });
|
|
} else if (mode === "NONE") {
|
|
updateSettings({ serverAuthMode: "SIMPLE_LOGIN" });
|
|
}
|
|
return "unsupported_mode";
|
|
}
|
|
return "unreachable";
|
|
} catch { return "unreachable"; }
|
|
} |