Refactor: rename user secrets table to custom secrets (#11525)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Rohit Malhotra
2025-10-27 12:58:07 -04:00
committed by GitHub
parent 26c636d63e
commit eb616dfae4
34 changed files with 180 additions and 143 deletions

View File

@@ -9,8 +9,8 @@ from openhands.integrations.provider import (
ProviderToken,
ProviderType,
)
from openhands.storage.data_models.secrets import Secrets
from openhands.storage.data_models.settings import Settings
from openhands.storage.data_models.user_secrets import UserSecrets
def test_provider_token_immutability():
@@ -34,8 +34,8 @@ def test_provider_token_immutability():
def test_secret_store_immutability():
"""Test that UserSecrets is immutable"""
store = UserSecrets(
"""Test that Secrets is immutable"""
store = Secrets(
provider_tokens={ProviderType.GITHUB: ProviderToken(token=SecretStr('test'))}
)
@@ -69,7 +69,7 @@ def test_secret_store_immutability():
def test_settings_immutability():
"""Test that Settings secrets_store is immutable"""
settings = Settings(
secrets_store=UserSecrets(
secrets_store=Secrets(
provider_tokens={
ProviderType.GITHUB: ProviderToken(token=SecretStr('test'))
}
@@ -78,7 +78,7 @@ def test_settings_immutability():
# Test direct modification of secrets_store
with pytest.raises(ValidationError):
settings.secrets_store = UserSecrets()
settings.secrets_store = Secrets()
# Test nested modification attempts
with pytest.raises((TypeError, AttributeError)):
@@ -87,7 +87,7 @@ def test_settings_immutability():
)
# Test model_copy creates new instance
new_store = UserSecrets(
new_store = Secrets(
provider_tokens={
ProviderType.GITHUB: ProviderToken(token=SecretStr('new_token'))
}
@@ -140,10 +140,10 @@ def test_provider_handler_immutability():
def test_token_conversion():
"""Test token conversion in UserSecrets.create"""
"""Test token conversion in Secrets.create"""
# Test with string token
store1 = Settings(
secrets_store=UserSecrets(
secrets_store=Secrets(
provider_tokens={
ProviderType.GITHUB: ProviderToken(token=SecretStr('test_token'))
}
@@ -159,7 +159,7 @@ def test_token_conversion():
assert store1.secrets_store.provider_tokens[ProviderType.GITHUB].user_id is None
# Test with dict token
store2 = UserSecrets(
store2 = Secrets(
provider_tokens={'github': {'token': 'test_token', 'user_id': 'user1'}}
)
assert (
@@ -170,14 +170,14 @@ def test_token_conversion():
# Test with ProviderToken
token = ProviderToken(token=SecretStr('test_token'), user_id='user2')
store3 = UserSecrets(provider_tokens={ProviderType.GITHUB: token})
store3 = Secrets(provider_tokens={ProviderType.GITHUB: token})
assert (
store3.provider_tokens[ProviderType.GITHUB].token.get_secret_value()
== 'test_token'
)
assert store3.provider_tokens[ProviderType.GITHUB].user_id == 'user2'
store4 = UserSecrets(
store4 = Secrets(
provider_tokens={
ProviderType.GITHUB: 123 # Invalid type
}
@@ -186,10 +186,10 @@ def test_token_conversion():
assert ProviderType.GITHUB not in store4.provider_tokens
# Test with empty/None token
store5 = UserSecrets(provider_tokens={ProviderType.GITHUB: None})
store5 = Secrets(provider_tokens={ProviderType.GITHUB: None})
assert ProviderType.GITHUB not in store5.provider_tokens
store6 = UserSecrets(
store6 = Secrets(
provider_tokens={
'invalid_provider': 'test_token' # Invalid provider type
}

View File

@@ -82,7 +82,7 @@ def test_client():
def create_new_test_conversation(
test_request: InitSessionRequest, auth_type: AuthType | None = None
):
# Create a mock UserSecrets object with the required custom_secrets attribute
# Create a mock Secrets object with the required custom_secrets attribute
mock_user_secrets = MagicMock()
mock_user_secrets.custom_secrets = MappingProxyType({})

View File

@@ -18,7 +18,7 @@ from openhands.server.routes.secrets import (
app as secrets_app,
)
from openhands.storage import get_file_store
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.data_models.secrets import Secrets
from openhands.storage.secrets.file_secrets_store import FileSecretsStore
@@ -62,7 +62,7 @@ async def test_load_custom_secrets_names(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(
user_secrets = Secrets(
custom_secrets=custom_secrets, provider_tokens=provider_tokens
)
@@ -101,7 +101,7 @@ async def test_load_custom_secrets_names_empty(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(provider_tokens=provider_tokens, custom_secrets={})
user_secrets = Secrets(provider_tokens=provider_tokens, custom_secrets={})
# Store the initial settings
await file_secrets_store.store(user_secrets)
@@ -123,7 +123,7 @@ async def test_add_custom_secret(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(provider_tokens=provider_tokens)
user_secrets = Secrets(provider_tokens=provider_tokens)
# Store the initial settings
await file_secrets_store.store(user_secrets)
@@ -184,7 +184,7 @@ async def test_update_existing_custom_secret(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(
user_secrets = Secrets(
custom_secrets=custom_secrets, provider_tokens=provider_tokens
)
@@ -223,7 +223,7 @@ async def test_add_multiple_custom_secrets(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(
user_secrets = Secrets(
custom_secrets=custom_secrets, provider_tokens=provider_tokens
)
@@ -285,7 +285,7 @@ async def test_delete_custom_secret(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(
user_secrets = Secrets(
custom_secrets=custom_secrets, provider_tokens=provider_tokens
)
@@ -323,7 +323,7 @@ async def test_delete_nonexistent_custom_secret(test_client, file_secrets_store)
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(
user_secrets = Secrets(
custom_secrets=custom_secrets, provider_tokens=provider_tokens
)
@@ -355,7 +355,7 @@ async def test_add_git_providers_with_host(test_client, file_secrets_store):
provider_tokens = {
ProviderType.GITHUB: ProviderToken(token=SecretStr('github-token'))
}
user_secrets = UserSecrets(provider_tokens=provider_tokens)
user_secrets = Secrets(provider_tokens=provider_tokens)
await file_secrets_store.store(user_secrets)
# Mock check_provider_tokens to return empty string (no error)
@@ -394,7 +394,7 @@ async def test_add_git_providers_update_host_only(test_client, file_secrets_stor
token=SecretStr('github-token'), host='github.com'
)
}
user_secrets = UserSecrets(provider_tokens=provider_tokens)
user_secrets = Secrets(provider_tokens=provider_tokens)
await file_secrets_store.store(user_secrets)
# Mock check_provider_tokens to return empty string (no error)
@@ -433,7 +433,7 @@ async def test_add_git_providers_invalid_token_with_host(
):
"""Test adding an invalid token with a host."""
# Create initial user secrets
user_secrets = UserSecrets()
user_secrets = Secrets()
await file_secrets_store.store(user_secrets)
# Mock validate_provider_token to return None (invalid token)
@@ -456,7 +456,7 @@ async def test_add_git_providers_invalid_token_with_host(
async def test_add_multiple_git_providers_with_hosts(test_client, file_secrets_store):
"""Test adding multiple git providers with different hosts."""
# Create initial user secrets
user_secrets = UserSecrets()
user_secrets = Secrets()
await file_secrets_store.store(user_secrets)
# Mock check_provider_tokens to return empty string (no error)

View File

@@ -9,7 +9,7 @@ from pydantic import SecretStr
from openhands.integrations.provider import ProviderToken, ProviderType
from openhands.server.app import app
from openhands.server.user_auth.user_auth import UserAuth
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.data_models.secrets import Secrets
from openhands.storage.memory import InMemoryFileStore
from openhands.storage.secrets.secrets_store import SecretsStore
from openhands.storage.settings.file_settings_store import FileSettingsStore
@@ -43,7 +43,7 @@ class MockUserAuth(UserAuth):
async def get_secrets_store(self) -> SecretsStore | None:
return None
async def get_user_secrets(self) -> UserSecrets | None:
async def get_secrets(self) -> Secrets | None:
return None
@classmethod

View File

@@ -14,8 +14,8 @@ from openhands.server.routes.secrets import (
from openhands.server.routes.settings import store_llm_settings
from openhands.server.settings import POSTProviderModel
from openhands.storage import get_file_store
from openhands.storage.data_models.secrets import Secrets
from openhands.storage.data_models.settings import Settings
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.secrets.file_secrets_store import FileSecretsStore
@@ -220,9 +220,9 @@ async def test_store_provider_tokens_new_tokens(test_client, file_secrets_store)
mock_store = MagicMock()
mock_store.load = AsyncMock(return_value=None) # No existing settings
UserSecrets()
Secrets()
user_secrets = await file_secrets_store.store(UserSecrets())
user_secrets = await file_secrets_store.store(Secrets())
response = test_client.post('/api/add-git-providers', json=provider_tokens)
assert response.status_code == 200
@@ -242,8 +242,8 @@ async def test_store_provider_tokens_update_existing(test_client, file_secrets_s
github_token = ProviderToken(token=SecretStr('old-token'))
provider_tokens = {ProviderType.GITHUB: github_token}
# Create a UserSecrets with the provider tokens
user_secrets = UserSecrets(provider_tokens=provider_tokens)
# Create a Secrets with the provider tokens
user_secrets = Secrets(provider_tokens=provider_tokens)
await file_secrets_store.store(user_secrets)
@@ -268,7 +268,7 @@ async def test_store_provider_tokens_keep_existing(test_client, file_secrets_sto
# Create existing secrets with a GitHub token
github_token = ProviderToken(token=SecretStr('existing-token'))
provider_tokens = {ProviderType.GITHUB: github_token}
user_secrets = UserSecrets(provider_tokens=provider_tokens)
user_secrets = Secrets(provider_tokens=provider_tokens)
await file_secrets_store.store(user_secrets)

View File

@@ -9,7 +9,7 @@ from pydantic import SecretStr
from openhands.integrations.provider import ProviderToken, ProviderType
from openhands.server.app import app
from openhands.server.user_auth.user_auth import UserAuth
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.data_models.secrets import Secrets
from openhands.storage.memory import InMemoryFileStore
from openhands.storage.secrets.secrets_store import SecretsStore
from openhands.storage.settings.file_settings_store import FileSettingsStore
@@ -43,7 +43,7 @@ class MockUserAuth(UserAuth):
async def get_secrets_store(self) -> SecretsStore | None:
return None
async def get_user_secrets(self) -> UserSecrets | None:
async def get_secrets(self) -> Secrets | None:
return None
@classmethod

View File

@@ -10,12 +10,12 @@ from openhands.integrations.provider import (
ProviderToken,
ProviderType,
)
from openhands.storage.data_models.user_secrets import UserSecrets
from openhands.storage.data_models.secrets import Secrets
class TestUserSecrets:
class TestSecrets:
def test_adding_only_provider_tokens(self):
"""Test adding only provider tokens to the UserSecrets."""
"""Test adding only provider tokens to the Secrets."""
# Create provider tokens
github_token = ProviderToken(
token=SecretStr('github-token-123'), user_id='user1'
@@ -31,7 +31,7 @@ class TestUserSecrets:
}
# Initialize the store with a dict that will be converted to MappingProxyType
store = UserSecrets(provider_tokens=provider_tokens)
store = Secrets(provider_tokens=provider_tokens)
# Verify the tokens were added correctly
assert isinstance(store.provider_tokens, MappingProxyType)
@@ -52,7 +52,7 @@ class TestUserSecrets:
assert len(store.custom_secrets) == 0
def test_adding_only_custom_secrets(self):
"""Test adding only custom secrets to the UserSecrets."""
"""Test adding only custom secrets to the Secrets."""
# Create custom secrets
custom_secrets = {
'API_KEY': CustomSecret(
@@ -64,7 +64,7 @@ class TestUserSecrets:
}
# Initialize the store with custom secrets
store = UserSecrets(custom_secrets=custom_secrets)
store = Secrets(custom_secrets=custom_secrets)
# Verify the custom secrets were added correctly
assert isinstance(store.custom_secrets, MappingProxyType)
@@ -95,7 +95,7 @@ class TestUserSecrets:
custom_secrets_proxy = MappingProxyType({'API_KEY': custom_secret})
# Test with dict for provider_tokens and MappingProxyType for custom_secrets
store1 = UserSecrets(
store1 = Secrets(
provider_tokens=provider_tokens_dict, custom_secrets=custom_secrets_proxy
)
@@ -120,7 +120,7 @@ class TestUserSecrets:
'API_KEY': {'secret': 'api-key-123', 'description': 'API key'}
}
store2 = UserSecrets(
store2 = Secrets(
provider_tokens=provider_tokens_proxy, custom_secrets=custom_secrets_dict
)
@@ -146,7 +146,7 @@ class TestUserSecrets:
)
}
initial_store = UserSecrets(
initial_store = Secrets(
provider_tokens=MappingProxyType({ProviderType.GITHUB: github_token}),
custom_secrets=MappingProxyType(custom_secret),
)
@@ -212,7 +212,7 @@ class TestUserSecrets:
)
def test_serialization_with_expose_secrets(self):
"""Test serializing the UserSecrets with expose_secrets=True."""
"""Test serializing the Secrets with expose_secrets=True."""
# Create a store with both provider tokens and custom secrets
github_token = ProviderToken(
token=SecretStr('github-token-123'), user_id='user1'
@@ -223,7 +223,7 @@ class TestUserSecrets:
)
}
store = UserSecrets(
store = Secrets(
provider_tokens=MappingProxyType({ProviderType.GITHUB: github_token}),
custom_secrets=MappingProxyType(custom_secrets),
)
@@ -290,7 +290,7 @@ class TestUserSecrets:
}
# Initialize the store
store = UserSecrets(provider_tokens=mixed_provider_tokens)
store = Secrets(provider_tokens=mixed_provider_tokens)
# Verify all tokens are converted to SecretStr
assert isinstance(store.provider_tokens, MappingProxyType)
@@ -322,7 +322,7 @@ class TestUserSecrets:
}
# Initialize the store
store = UserSecrets(custom_secrets=custom_secrets_dict)
store = Secrets(custom_secrets=custom_secrets_dict)
# Verify all secrets are converted to CustomSecret objects
assert isinstance(store.custom_secrets, MappingProxyType)