sync: 鍚屾灞€鍩熺綉鏈€鏂颁唬鐮?(source master @ b69568e4)
This commit is contained in:
1 parent
4f7f07504a
commit
8bc8b0e082
1651 files changed
+278599
-11416
No files matched your search
@@ -0,0 +1,79 @@
|
||||
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 }),
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user