(Hotfix): Handle cases where user secrets store doesn't exist (#8745)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Rohit Malhotra 2025-05-27 18:26:36 -04:00 committed by GitHub
parent c3ab4b480b
commit 0023eb0982
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 24 deletions

View File

@ -188,10 +188,7 @@ async def load_custom_secrets_names(
) -> GETCustomSecrets | JSONResponse:
try:
if not user_secrets:
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content={'error': 'User secrets not found'},
)
return GETCustomSecrets(custom_secrets=[])
custom_secrets: list[CustomSecretWithoutValueModel] = []
if user_secrets.custom_secrets:
@ -220,31 +217,30 @@ async def create_custom_secret(
) -> JSONResponse:
try:
existing_secrets = await secrets_store.load()
if existing_secrets:
custom_secrets = dict(existing_secrets.custom_secrets)
custom_secrets = dict(existing_secrets.custom_secrets) if existing_secrets else {}
secret_name = incoming_secret.name
secret_value = incoming_secret.value
secret_description = incoming_secret.description
secret_name = incoming_secret.name
secret_value = incoming_secret.value
secret_description = incoming_secret.description
if secret_name in custom_secrets:
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={'message': f'Secret {secret_name} already exists'},
)
custom_secrets[secret_name] = CustomSecret(
secret=secret_value,
description=secret_description or '',
if secret_name in custom_secrets:
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={'message': f'Secret {secret_name} already exists'},
)
# Create a new UserSecrets that preserves provider tokens
updated_user_secrets = UserSecrets(
custom_secrets=custom_secrets,
provider_tokens=existing_secrets.provider_tokens,
)
custom_secrets[secret_name] = CustomSecret(
secret=secret_value,
description=secret_description or '',
)
await secrets_store.store(updated_user_secrets)
# Create a new UserSecrets that preserves provider tokens
updated_user_secrets = UserSecrets(
custom_secrets=custom_secrets,
provider_tokens=existing_secrets.provider_tokens if existing_secrets else {},
)
await secrets_store.store(updated_user_secrets)
return JSONResponse(
status_code=status.HTTP_201_CREATED,

View File

@ -138,6 +138,39 @@ async def test_add_custom_secret(test_client, file_secrets_store):
)
@pytest.mark.asyncio
async def test_create_custom_secret_with_no_existing_secrets(
test_client, file_secrets_store
):
"""Test creating a custom secret when there are no existing secrets at all."""
# Don't store any initial settings - this simulates a completely new user
# or a situation where the secrets store is empty
# Make the POST request to add a custom secret
add_secret_data = {
'name': 'NEW_API_KEY',
'value': 'new-api-key-value',
'description': 'Test API Key',
}
response = test_client.post('/api/secrets', json=add_secret_data)
assert response.status_code == 201
# Verify that the settings were stored with the new secret
stored_settings = await file_secrets_store.load()
# Check that the secret was added
assert 'NEW_API_KEY' in stored_settings.custom_secrets
assert (
stored_settings.custom_secrets['NEW_API_KEY'].secret.get_secret_value()
== 'new-api-key-value'
)
assert stored_settings.custom_secrets['NEW_API_KEY'].description == 'Test API Key'
# Check that provider_tokens is an empty dict, not None
assert stored_settings.provider_tokens == {}
@pytest.mark.asyncio
async def test_update_existing_custom_secret(test_client, file_secrets_store):
"""Test updating an existing custom secret's name and description (cannot change value once set)."""