feat: gate admin ui with optional access key

This commit is contained in:
2026-06-30 19:46:03 +08:00
parent 41357f5e7a
commit d90a1cd94f
4 changed files with 300 additions and 22 deletions
+21 -1
View File
@@ -7,6 +7,8 @@ type GatewayConfig = {
profile_name?: string;
listen_host?: string;
listen_port?: number;
management_access_key?: string;
management_access_key_configured?: boolean;
upstream_base_url?: string;
upstream_auth_mode?: string;
upstream_auth_env?: string | null;
@@ -227,6 +229,8 @@ const api = {
restore: "/__codex_retry_gateway/api/restore",
};
const ACCESS_KEY_STORAGE_KEY = "codex_retry_gateway_access_key";
const REQUEST_PAGE_SIZE = 20;
const LOG_PAGE_SIZE = 200;
@@ -403,7 +407,12 @@ function splitLines(value: string) {
}
async function fetchJson<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(url, { cache: "no-store", ...options });
const headers = new Headers(options?.headers || {});
const accessKey = window.localStorage.getItem(ACCESS_KEY_STORAGE_KEY)?.trim();
if (accessKey && !headers.has("x-codex-retry-gateway-key")) {
headers.set("x-codex-retry-gateway-key", accessKey);
}
const response = await fetch(url, { cache: "no-store", ...options, headers });
const payload = await response.json();
if (!response.ok) {
throw new Error(payload?.error?.message || "请求失败");
@@ -499,6 +508,17 @@ function ruleFormFromStatus(status: StatusPayload | null): RuleFormState {
}
export default function App() {
useEffect(() => {
const url = new URL(window.location.href);
const accessKey = url.searchParams.get("key")?.trim();
if (!accessKey) {
return;
}
window.localStorage.setItem(ACCESS_KEY_STORAGE_KEY, accessKey);
url.searchParams.delete("key");
window.history.replaceState({}, "", url.toString());
}, []);
const [page, setPage] = useState<PageKey>(() => {
const hash = window.location.hash.replace("#", "") as PageKey;
return pageCopy[hash] ? hash : "overview";