From 49518300dcd3db1cf5d01108408bd48f76470570 Mon Sep 17 00:00:00 2001 From: Lingxuan Zuo Date: Fri, 10 Apr 2026 15:15:29 +0800 Subject: [PATCH] Fix provider API key validation trimming (#810) --- src/components/settings/ProvidersSettings.tsx | 18 +++-- src/lib/providers.ts | 6 +- src/pages/Setup/index.tsx | 16 +++- src/stores/providers.ts | 4 +- tests/e2e/provider-lifecycle.spec.ts | 79 +++++++++++++++++++ tests/unit/provider-store-validation.test.ts | 42 ++++++++++ tests/unit/providers.test.ts | 2 + 7 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 tests/unit/provider-store-validation.test.ts diff --git a/src/components/settings/ProvidersSettings.tsx b/src/components/settings/ProvidersSettings.tsx index a9199e03d..78055ad33 100644 --- a/src/components/settings/ProvidersSettings.tsx +++ b/src/components/settings/ProvidersSettings.tsx @@ -34,6 +34,7 @@ import { getProviderDocsUrl, type ProviderType, getProviderIconUrl, + normalizeProviderApiKeyInput, resolveProviderApiKeyForSave, resolveProviderModelForSave, shouldShowProviderModelId, @@ -424,10 +425,11 @@ function ProviderCard({ try { const payload: { newApiKey?: string; updates?: Partial } = {}; const normalizedFallbackModels = normalizeFallbackModels(fallbackModelsText.split('\n')); + const normalizedNewKey = normalizeProviderApiKeyInput(newKey); - if (newKey.trim()) { + if (normalizedNewKey) { setValidating(true); - const result = await onValidateKey(newKey, { + const result = await onValidateKey(normalizedNewKey, { baseUrl: baseUrl.trim() || undefined, apiProtocol: (account.vendorId === 'custom' || account.vendorId === 'ollama') ? apiProtocol : undefined, }); @@ -437,7 +439,7 @@ function ProviderCard({ setSaving(false); return; } - payload.newApiKey = newKey.trim(); + payload.newApiKey = normalizedNewKey; } { @@ -1164,13 +1166,14 @@ function AddProviderDialog({ try { // Validate key first if the provider requires one and a key was entered const requiresKey = typeInfo?.requiresApiKey ?? false; - if (requiresKey && !apiKey.trim()) { + const normalizedApiKey = normalizeProviderApiKeyInput(apiKey); + if (requiresKey && !normalizedApiKey) { setValidationError(t('aiProviders.toast.invalidKey')); // reusing invalid key msg or should add 'required' msg? null checks setSaving(false); return; } - if (requiresKey && apiKey) { - const result = await onValidateKey(selectedType, apiKey, { + if (requiresKey && normalizedApiKey) { + const result = await onValidateKey(selectedType, normalizedApiKey, { baseUrl: baseUrl.trim() || undefined, apiProtocol: (selectedType === 'custom' || selectedType === 'ollama') ? apiProtocol : undefined, }); @@ -1191,7 +1194,7 @@ function AddProviderDialog({ await onAdd( selectedType, name || (typeInfo?.id === 'custom' ? t('aiProviders.custom') : typeInfo?.name) || selectedType, - apiKey.trim(), + normalizedApiKey, { baseUrl: baseUrl.trim() || undefined, apiProtocol: (selectedType === 'custom' || selectedType === 'ollama') ? apiProtocol : undefined, @@ -1655,6 +1658,7 @@ function AddProviderDialog({