Files
deerflow-code/frontend-web/src/core/auth/account-api.ts
T

80 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { apiFetch } from "@/core/api/fetch-client";
import { getBackendBaseURL } from "@/core/config";
import type { LoginByUsernameResponse } from "./index";
export interface AuthenticationOptions {
password_login_enabled: boolean;
registration_enabled: boolean;
sso_enabled: boolean;
single_session_enabled?: boolean;
needs_setup?: boolean;
}
function accountError(body: unknown, fallback: string): string {
const detail = (body as { detail?: unknown } | null)?.detail ?? body;
if (typeof detail === "string") return detail;
if (Array.isArray(detail)) {
return detail.map((item) => item?.msg).filter(Boolean).join(";") || fallback;
}
if (detail && typeof detail === "object") {
const value = detail as { message?: string; msg?: string };
return value.message || value.msg || fallback;
}
return fallback;
}
/** Bound unauthenticated requests so an unreachable gateway offers a retry. */
async function accountRequest<T>(path: string, init: RequestInit = {}): Promise<T> {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 20_000);
try {
const response = await apiFetch(`${getBackendBaseURL()}/api/v1/auth${path}`, {
...init,
signal: controller.signal,
});
const body: unknown = await response.json().catch(() => null);
if (!response.ok) throw new Error(accountError(body, "请求失败,请稍后重试"));
return body as T;
} catch (error) {
if (controller.signal.aborted) throw new Error("连接超时,请检查网络后重试");
if (error instanceof TypeError) throw new Error("无法连接服务器,请检查网络后重试");
throw error;
} finally {
clearTimeout(timer);
}
}
export async function fetchAuthenticationOptions(): Promise<AuthenticationOptions> {
const options = await accountRequest<AuthenticationOptions>("/options", { cache: "no-store" });
if (!options || [options.password_login_enabled, options.registration_enabled, options.sso_enabled]
.some((value) => typeof value !== "boolean")) {
throw new Error("无法读取登录设置,请联系管理员或重试");
}
return options;
}
export function loginWithPassword(username: string, password: string): Promise<LoginByUsernameResponse> {
return accountRequest("/login/local", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ username, password }),
});
}
export function registerAccount(username: string, password: string): Promise<LoginByUsernameResponse> {
return accountRequest("/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
}
export function initializeAdministrator(email: string, password: string): Promise<LoginByUsernameResponse> {
return accountRequest<LoginByUsernameResponse>("/initialize", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
}