feat: add secure secret provider
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import unittest
|
||||
|
||||
from keyring.errors import PasswordDeleteError
|
||||
|
||||
from javis.interface.cli import run_secrets
|
||||
from javis.security.secrets import GEMINI_ACCOUNT, SERVICE_NAME, SecretProvider
|
||||
|
||||
|
||||
class _FakeBackend:
|
||||
def __init__(self) -> None:
|
||||
self.values: dict[tuple[str, str], str] = {}
|
||||
|
||||
def get_password(self, service: str, account: str) -> str | None:
|
||||
return self.values.get((service, account))
|
||||
|
||||
def set_password(self, service: str, account: str, value: str) -> None:
|
||||
self.values[(service, account)] = value
|
||||
|
||||
def delete_password(self, service: str, account: str) -> None:
|
||||
try:
|
||||
del self.values[(service, account)]
|
||||
except KeyError as exc:
|
||||
raise PasswordDeleteError("missing") from exc
|
||||
|
||||
|
||||
class SecretProviderTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.backend = _FakeBackend()
|
||||
self.provider = SecretProvider(self.backend)
|
||||
|
||||
def test_key_is_initially_not_available(self) -> None:
|
||||
self.assertFalse(self.provider.gemini_key_available())
|
||||
|
||||
def test_set_and_delete_key(self) -> None:
|
||||
self.provider.set_gemini_key("test-secret-value")
|
||||
self.assertTrue(self.provider.gemini_key_available())
|
||||
self.assertEqual(
|
||||
self.backend.values[(SERVICE_NAME, GEMINI_ACCOUNT)],
|
||||
"test-secret-value",
|
||||
)
|
||||
|
||||
self.assertTrue(self.provider.delete_gemini_key())
|
||||
self.assertFalse(self.provider.gemini_key_available())
|
||||
|
||||
def test_cli_set_uses_hidden_input_and_never_outputs_value(self) -> None:
|
||||
output: list[str] = []
|
||||
secret = "test-secret-value"
|
||||
|
||||
result = run_secrets(
|
||||
"set",
|
||||
provider=self.provider,
|
||||
password_fn=lambda _prompt: secret,
|
||||
output=output.append,
|
||||
)
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
self.assertTrue(self.provider.gemini_key_available())
|
||||
self.assertNotIn(secret, "\n".join(output))
|
||||
|
||||
def test_cli_status_only_reports_availability(self) -> None:
|
||||
output: list[str] = []
|
||||
self.provider.set_gemini_key("test-secret-value")
|
||||
|
||||
result = run_secrets("status", provider=self.provider, output=output.append)
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
self.assertEqual(output, ["Gemini-Schlüssel: verfügbar"])
|
||||
self.assertNotIn("test-secret-value", "\n".join(output))
|
||||
|
||||
def test_cli_delete_handles_missing_key(self) -> None:
|
||||
output: list[str] = []
|
||||
|
||||
result = run_secrets("delete", provider=self.provider, output=output.append)
|
||||
|
||||
self.assertEqual(result, 0)
|
||||
self.assertEqual(output, ["Gemini-Schlüssel war nicht verfügbar."])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user