From 207038f0ea33514aba4fc000db808748d2a2cee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E5=8D=83=E9=87=8C?= Date: Wed, 24 Jun 2026 09:05:35 +0800 Subject: [PATCH] Guard settings API key entries --- .../components/settings/SettingsPage.test.ts | 5 ++++ .../src/components/settings/SettingsPage.tsx | 30 +++++++++++-------- .../src/components/settings/apiKeys.ts | 5 ++++ 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 static/frontend/src/components/settings/apiKeys.ts diff --git a/static/frontend/src/components/settings/SettingsPage.test.ts b/static/frontend/src/components/settings/SettingsPage.test.ts index 8b32837c..dc281309 100644 --- a/static/frontend/src/components/settings/SettingsPage.test.ts +++ b/static/frontend/src/components/settings/SettingsPage.test.ts @@ -10,6 +10,7 @@ vi.mock("@tanstack/react-query", () => ({ })); import { useQuery } from "@tanstack/react-query"; +import { getApiKeyValue } from "./apiKeys"; interface ServerStatus { status: string; @@ -160,6 +161,10 @@ describe("SettingsPage ApiKeysSection Logic", () => { expect(truncated).toBe("short..."); }); + it("normalizes object key entries", () => { + expect(getApiKeyValue({ key: "sk-object-key" })).toBe("sk-object-key"); + }); + it("checks if keys array has items", () => { const data = { keys: ["key1", "key2"] }; const hasKeys = data?.keys?.length > 0; diff --git a/static/frontend/src/components/settings/SettingsPage.tsx b/static/frontend/src/components/settings/SettingsPage.tsx index 31644af2..8980ab44 100644 --- a/static/frontend/src/components/settings/SettingsPage.tsx +++ b/static/frontend/src/components/settings/SettingsPage.tsx @@ -20,6 +20,7 @@ import { useI18n } from '@/contexts'; import { ProxySettings } from './ProxySettings'; import { AuthManager } from './AuthManager'; import { PortConfiguration } from './PortConfig'; +import { type ApiKeyEntry, getApiKeyValue } from './apiKeys'; import styles from './SettingsPage.module.css'; // API functions @@ -164,7 +165,7 @@ function StatusBar() { function ApiKeysSection() { const { t } = useI18n(); - const { data, isLoading, refetch } = useQuery<{ keys: string[] }>({ + const { data, isLoading, refetch } = useQuery<{ keys: ApiKeyEntry[] }>({ queryKey: ['apiKeys'], queryFn: fetchApiKeys, }); @@ -229,17 +230,22 @@ function ApiKeysSection() {

{data?.keys?.length ? ( - data.keys.map((key) => ( -
- {key.substring(0, 16)}... - -
- )) + data.keys.map((entry) => { + const key = getApiKeyValue(entry); + if (!key) return null; + + return ( +
+ {key.substring(0, 16)}... + +
+ ); + }) ) : (
{t.settingsPage.noApiKeys}
)} diff --git a/static/frontend/src/components/settings/apiKeys.ts b/static/frontend/src/components/settings/apiKeys.ts new file mode 100644 index 00000000..d88daffc --- /dev/null +++ b/static/frontend/src/components/settings/apiKeys.ts @@ -0,0 +1,5 @@ +export type ApiKeyEntry = string | { key?: string; value?: string }; + +export function getApiKeyValue(key: ApiKeyEntry) { + return typeof key === 'string' ? key : key.key || key.value || ''; +}