This commit is contained in:
Your Name
2026-08-12 11:03:28 +08:00
parent 09d3fcbf82
commit bc9ad1d3cd
32 changed files with 4586 additions and 2341 deletions
+52 -3
View File
@@ -215,21 +215,43 @@ def test_invalid_envelope_raises_protocol_error() -> None:
client.get("broken")
def test_token_store_file_fallback_never_persists_password(tmp_path: Path) -> None:
"""The fallback contains only an access token and an optional account name."""
def test_token_store_file_fallback_never_persists_plaintext_password(tmp_path: Path) -> None:
"""The fallback may contain a Windows DPAPI blob, but never plaintext."""
path = tmp_path / "credentials.json"
store = TokenStore(path, keyring_backend=None)
store.save_token("token-value", account="doctor")
password_saved = store.save_password(
"must-not-reach-disk",
account="doctor",
scope="https://example.test/adminapi",
)
assert store.load_token() == "token-value"
assert store.load_account() == "doctor"
restored = store.load_password(account="doctor", scope="https://example.test/adminapi")
if password_saved:
assert restored == "must-not-reach-disk"
else:
assert restored is None
payload = json.loads(path.read_text(encoding="utf-8"))
assert payload == {"token": "token-value", "account": "doctor"}
assert payload["token"] == "token-value"
assert payload["account"] == "doctor"
assert "password" not in path.read_text(encoding="utf-8").lower()
assert "must-not-reach-disk" not in path.read_text(encoding="utf-8")
store.clear_token()
assert store.load_token() is None
assert store.load_account() == "doctor"
after_logout = store.load_password(
account="doctor",
scope="https://example.test/adminapi",
)
if password_saved:
assert after_logout == "must-not-reach-disk"
else:
assert after_logout is None
store.clear_account()
assert store.load_password(account="doctor", scope="https://example.test/adminapi") is None
class _MemoryKeyring:
@@ -267,6 +289,33 @@ def test_token_store_prefers_available_keyring(tmp_path: Path) -> None:
assert json.loads(path.read_text(encoding="utf-8")) == {"account": "doctor"}
def test_token_store_keeps_login_password_in_scoped_keyring_only(tmp_path: Path) -> None:
backend = _MemoryKeyring()
path = tmp_path / "credentials.json"
store = TokenStore(path, keyring_backend=backend)
scope = "https://example.test/adminapi/"
assert store.save_password("secret-value", account="doctor", scope=scope)
assert (
store.load_password(account="doctor", scope="https://example.test/adminapi")
== "secret-value"
)
assert store.load_password(account="doctor", scope="https://other.test/adminapi") is None
assert "secret-value" not in path.read_text(encoding="utf-8")
assert json.loads(path.read_text(encoding="utf-8")) == {
"account": "doctor",
"scope": "https://example.test/adminapi",
}
next_scope = "https://next.test/adminapi"
assert store.save_password("next-secret", account="doctor", scope=next_scope)
assert store.load_password(account="doctor", scope=scope) is None
assert store.load_password(account="doctor", scope=next_scope) == "next-secret"
store.clear_password(account="doctor", scope=next_scope)
assert store.load_password(account="doctor", scope=next_scope) is None
def test_token_store_scopes_automatic_restore_and_forgets_account(tmp_path: Path) -> None:
"""Automatic restore never returns a token issued for another API base."""