diff --git a/archon-ui-main/src/components/settings/APIKeysSection.tsx b/archon-ui-main/src/components/settings/APIKeysSection.tsx index 2b61305b..729b2397 100644 --- a/archon-ui-main/src/components/settings/APIKeysSection.tsx +++ b/archon-ui-main/src/components/settings/APIKeysSection.tsx @@ -16,6 +16,7 @@ interface CustomCredential { is_encrypted?: boolean; showValue?: boolean; // Track per-credential visibility isNew?: boolean; // Track if this is a new unsaved credential + isFromBackend?: boolean; // Track if credential came from backend (write-only once encrypted) } export const APIKeysSection = () => { @@ -51,17 +52,22 @@ export const APIKeysSection = () => { }); // Convert to UI format - const uiCredentials = apiKeys.map(cred => ({ - key: cred.key, - value: cred.value || '', - description: cred.description || '', - originalValue: cred.value || '', - originalKey: cred.key, // Track original key for updates - hasChanges: false, - is_encrypted: cred.is_encrypted || false, - showValue: false, - isNew: false - })); + const uiCredentials = apiKeys.map(cred => { + const isEncryptedFromBackend = cred.is_encrypted && cred.value === '[ENCRYPTED]'; + + return { + key: cred.key, + value: cred.value || '', + description: cred.description || '', + originalValue: cred.value || '', + originalKey: cred.key, // Track original key for updates + hasChanges: false, + is_encrypted: cred.is_encrypted || false, + showValue: false, + isNew: false, + isFromBackend: !cred.isNew, // Mark as from backend unless it's a new credential + }; + }); setCustomCredentials(uiCredentials); } catch (err) { @@ -81,7 +87,8 @@ export const APIKeysSection = () => { hasChanges: true, is_encrypted: true, // Default to encrypted showValue: true, // Show value for new entries - isNew: true + isNew: true, + isFromBackend: false // New credentials are not from backend }; setCustomCredentials([...customCredentials, newCred]); @@ -95,6 +102,12 @@ export const APIKeysSection = () => { if (field === 'key' || field === 'value' || field === 'is_encrypted') { updated.hasChanges = true; } + // If user is editing the value of an encrypted credential from backend, make it editable + if (field === 'value' && cred.isFromBackend && cred.is_encrypted && cred.value === '[ENCRYPTED]') { + updated.isFromBackend = false; // Now it's being edited, treat like new credential + updated.showValue = false; // Keep it hidden by default since it was encrypted + updated.value = ''; // Clear the [ENCRYPTED] placeholder so they can enter new value + } return updated; } return cred; @@ -102,11 +115,21 @@ export const APIKeysSection = () => { }; const toggleValueVisibility = (index: number) => { - updateCredential(index, 'showValue', !customCredentials[index].showValue); + const cred = customCredentials[index]; + if (cred.isFromBackend && cred.is_encrypted && cred.value === '[ENCRYPTED]') { + showToast('Encrypted credentials cannot be viewed. Edit to make changes.', 'warning'); + return; + } + updateCredential(index, 'showValue', !cred.showValue); }; const toggleEncryption = (index: number) => { - updateCredential(index, 'is_encrypted', !customCredentials[index].is_encrypted); + const cred = customCredentials[index]; + if (cred.isFromBackend && cred.is_encrypted && cred.value === '[ENCRYPTED]') { + showToast('Edit the credential value to make changes.', 'warning'); + return; + } + updateCredential(index, 'is_encrypted', !cred.is_encrypted); }; const deleteCredential = async (index: number) => { @@ -242,15 +265,31 @@ export const APIKeysSection = () => { value={cred.value} onChange={(e) => updateCredential(index, 'value', e.target.value)} placeholder={cred.is_encrypted && !cred.value ? 'Enter new value (encrypted)' : 'Enter value'} - className="w-full px-3 py-2 pr-20 rounded-md bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 text-sm" + className={`w-full px-3 py-2 pr-20 rounded-md border text-sm ${ + cred.isFromBackend && cred.is_encrypted && cred.value === '[ENCRYPTED]' + ? 'bg-gray-100 dark:bg-gray-800 border-gray-200 dark:border-gray-600 text-gray-500 dark:text-gray-400' + : 'bg-white dark:bg-gray-900 border-gray-300 dark:border-gray-700' + }`} + title={cred.isFromBackend && cred.is_encrypted && cred.value === '[ENCRYPTED]' + ? 'Click to edit this encrypted credential' + : undefined} /> {/* Show/Hide value button */}