maestral/tests/offline/test_keyring.py
2024-07-27 11:02:34 +02:00

121 lines
3.6 KiB
Python

from unittest import mock
import pytest
from keyring.backend import KeyringBackend
from keyring.backends.SecretService import Keyring as SecretServiceKeyring
from keyring.errors import KeyringLocked
from keyrings.alt.file import PlaintextKeyring
from maestral.config import MaestralConfig, remove_configuration
from maestral.exceptions import KeyringAccessError
from maestral.keyring import CredentialStorage
@pytest.fixture
def cred_storage():
storage = CredentialStorage("test-config")
yield storage
storage.delete_creds()
remove_configuration("test-config")
def test_unlinked_state(cred_storage: CredentialStorage) -> None:
"""Test unlinked state"""
conf = MaestralConfig("test-config")
assert not cred_storage.loaded
assert cred_storage.account_id is None
assert cred_storage.token is None
assert cred_storage.keyring is None
assert conf.get("auth", "account_id") == ""
assert conf.get("auth", "keyring") == "automatic"
def test_save_creds(cred_storage: CredentialStorage) -> None:
"""Test linked state"""
conf = MaestralConfig("test-config")
cred_storage.save_creds("account_id", "token")
assert cred_storage.loaded
assert cred_storage.account_id == "account_id"
assert cred_storage.token == "token"
assert isinstance(cred_storage.keyring, KeyringBackend)
assert conf.get("auth", "account_id") == "account_id"
assert conf.get("auth", "keyring") != "automatic"
def test_load_creds(cred_storage: CredentialStorage) -> None:
"""Test linked state"""
cred_storage.save_creds("account_id", "token")
cred_storage2 = CredentialStorage("test-config")
cred_storage2.load_creds()
assert cred_storage2.loaded
assert cred_storage2.account_id == "account_id"
assert cred_storage2.token == "token"
assert isinstance(cred_storage2.keyring, KeyringBackend)
def test_delete_creds(cred_storage: CredentialStorage) -> None:
"""Test resetting state on `delete_creds`"""
conf = MaestralConfig("test-config")
cred_storage.save_creds("account_id", "token")
cred_storage.delete_creds()
assert not cred_storage.loaded
assert cred_storage.account_id is None
assert cred_storage.token is None
assert cred_storage.keyring is None
assert conf.get("auth", "account_id") == ""
assert conf.get("auth", "keyring") == "automatic"
def test_plaintext_fallback(cred_storage: CredentialStorage) -> None:
conf = MaestralConfig("test-config")
cred_storage.set_keyring_backend(SecretServiceKeyring())
with mock.patch.object(
cred_storage.keyring, "set_password", side_effect=KeyringLocked("")
):
cred_storage.save_creds("account_id", "token")
assert isinstance(cred_storage.keyring, PlaintextKeyring)
assert conf.get("auth", "keyring") == "keyrings.alt.file.PlaintextKeyring"
def test_load_error(cred_storage: CredentialStorage) -> None:
"""Test loading state from config file and keyring"""
cred_storage.save_creds("account_id", "token")
cred_storage2 = CredentialStorage("test-config")
cred_storage2.set_keyring_backend(PlaintextKeyring())
with mock.patch.object(
cred_storage2.keyring, "get_password", side_effect=KeyringLocked("")
):
with pytest.raises(KeyringAccessError):
cred_storage2.token
def test_delete_error(cred_storage: CredentialStorage) -> None:
"""Test loading state from config file and keyring"""
cred_storage.save_creds("account_id", "token")
with mock.patch.object(
cred_storage.keyring, "delete_password", side_effect=KeyringLocked("")
):
with pytest.raises(KeyringAccessError):
cred_storage.delete_creds()