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 || '';
+}