diff --git a/features/password.feature b/features/password.feature index 86fa7f6b..332ba86e 100644 --- a/features/password.feature +++ b/features/password.feature @@ -24,6 +24,7 @@ Feature: Using the installed keyring n """ Then we should get no error + And we should not see the message "Failed to retrieve keyring" Scenario: Encrypt journal with no keyring backend and do store in keyring Given we use the config "simple.yaml" @@ -36,25 +37,53 @@ Feature: Using the installed keyring y """ Then we should get no error + And we should not see the message "Failed to retrieve keyring" # @todo add step to check contents of keyring @todo Scenario: Open an encrypted journal with wrong password in keyring # This should ask the user for the password after the keyring fails - @todo - Scenario: Open encrypted journal when keyring exists but fails - # This should ask the user for the password after the keyring fails - @todo Scenario: Decrypt journal with password in keyring @todo Scenario: Decrypt journal without a keyring - @todo + Scenario: Encrypt journal when keyring exists but fails + Given we use the config "simple.yaml" + And we have a failed keyring + When we run "jrnl --encrypt" and enter + """ + this password will not be saved in keyring + this password will not be saved in keyring + y + """ + Then we should see the message "Failed to retrieve keyring" + And we should get no error + And we should be prompted for a password + And the config for journal "default" should have "encrypt" set to "bool:True" + Scenario: Decrypt journal when keyring exists but fails + Given we use the config "encrypted.yaml" + And we have a failed keyring + When we run "jrnl --decrypt" and enter "bad doggie no biscuit" + Then we should see the message "Failed to retrieve keyring" + And we should get no error + And we should be prompted for a password + And we should see the message "Journal decrypted" + And the config for journal "default" should have "encrypt" set to "bool:False" + And the journal should have 2 entries + + Scenario: Open encrypted journal when keyring exists but fails # This should ask the user for the password after the keyring fails + Given we use the config "encrypted.yaml" + And we have a failed keyring + When we run "jrnl -n 1" and enter "bad doggie no biscuit" + Then we should see the message "Failed to retrieve keyring" + And we should get no error + And we should be prompted for a password + And the output should contain "2013-06-10 15:40 Life is good" Scenario: Mistyping your password Given we use the config "simple.yaml" diff --git a/features/steps/core.py b/features/steps/core.py index af22c0cd..2f72a473 100644 --- a/features/steps/core.py +++ b/features/steps/core.py @@ -69,21 +69,19 @@ class NoKeyring(keyring.backend.KeyringBackend): class FailedKeyring(keyring.backend.KeyringBackend): """ - A keyring that simulates an environment with a keyring that has passwords, but fails - to return them. + A keyring that cannot be retrieved. """ priority = 2 - keys = defaultdict(dict) def set_password(self, servicename, username, password): - self.keys[servicename][username] = password + raise keyring.errors.KeyringError def get_password(self, servicename, username): - raise keyring.errors.NoKeyringError + raise keyring.errors.KeyringError def delete_password(self, servicename, username): - self.keys[servicename][username] = None + raise keyring.errors.KeyringError # set a default keyring @@ -148,8 +146,12 @@ def use_password(context, password, num=1): @given("we have a keyring") -def set_keyring(context): - keyring.set_keyring(TestKeyring()) +@given("we have a {type} keyring") +def set_keyring(context, type=""): + if type == "failed": + keyring.set_keyring(FailedKeyring()) + else: + keyring.set_keyring(TestKeyring()) @given("we do not have a keyring") diff --git a/jrnl/EncryptedJournal.py b/jrnl/EncryptedJournal.py index e1d248aa..7354e7a2 100644 --- a/jrnl/EncryptedJournal.py +++ b/jrnl/EncryptedJournal.py @@ -176,7 +176,9 @@ def get_keychain(journal_name): try: return keyring.get_password("jrnl", journal_name) - except RuntimeError: + except keyring.errors.KeyringError as e: + if not isinstance(e, keyring.errors.NoKeyringError): + print("Failed to retrieve keyring", file=sys.stderr) return "" @@ -186,13 +188,16 @@ def set_keychain(journal_name, password): if password is None: try: keyring.delete_password("jrnl", journal_name) - except keyring.errors.PasswordDeleteError: + except keyring.errors.KeyringError: pass else: try: keyring.set_password("jrnl", journal_name, password) - except keyring.errors.NoKeyringError: - print( - "Keyring backend not found. Please install one of the supported backends by visiting: https://pypi.org/project/keyring/", - file=sys.stderr, - ) + except keyring.errors.KeyringError as e: + if isinstance(e, keyring.errors.NoKeyringError): + print( + "Keyring backend not found. Please install one of the supported backends by visiting: https://pypi.org/project/keyring/", + file=sys.stderr, + ) + else: + print("Failed to retrieve keyring", file=sys.stderr)