mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-12 09:28:31 +02:00
Fix for new test from develop branch
There was a new test added for re-encrypting a journal. This updates the refactor to match the old (previously untested) behavior of jrnl. Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
parent
12bcc644d8
commit
33b0de862f
6 changed files with 75 additions and 16 deletions
|
@ -107,13 +107,16 @@ def postconfig_encrypt(
|
||||||
)
|
)
|
||||||
|
|
||||||
# If journal is encrypted, create new password
|
# If journal is encrypted, create new password
|
||||||
|
logging.debug("Clearing encryption method...")
|
||||||
|
|
||||||
if journal.config["encrypt"] is True:
|
if journal.config["encrypt"] is True:
|
||||||
logging.debug("Journal already encrypted. Re-encrypting...")
|
logging.debug("Journal already encrypted. Re-encrypting...")
|
||||||
print(f"Journal {journal.name} is already encrypted. Create a new password.")
|
print(f"Journal {journal.name} is already encrypted. Create a new password.")
|
||||||
|
journal.encryption_method.clear()
|
||||||
|
else:
|
||||||
|
journal.config["encrypt"] = True
|
||||||
|
journal.encryption_method = None
|
||||||
|
|
||||||
logging.debug("Clearing encryption method...")
|
|
||||||
journal.encryption_method = None
|
|
||||||
journal.config["encrypt"] = True
|
|
||||||
journal.write(args.filename)
|
journal.write(args.filename)
|
||||||
|
|
||||||
print_msg(
|
print_msg(
|
||||||
|
|
|
@ -17,6 +17,9 @@ class BaseEncryption(ABC):
|
||||||
self._journal_name: str = journal_name
|
self._journal_name: str = journal_name
|
||||||
self._config: dict = config
|
self._config: dict = config
|
||||||
|
|
||||||
|
def clear(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
def encrypt(self, text: str) -> bytes:
|
def encrypt(self, text: str) -> bytes:
|
||||||
logging.debug("encrypting")
|
logging.debug("encrypting")
|
||||||
return self._encrypt(text)
|
return self._encrypt(text)
|
||||||
|
|
|
@ -19,30 +19,51 @@ class BasePasswordEncryption(BaseEncryption):
|
||||||
self._attempts: int = 0
|
self._attempts: int = 0
|
||||||
self._max_attempts: int = 3
|
self._max_attempts: int = 3
|
||||||
self._password: str = ""
|
self._password: str = ""
|
||||||
|
self._check_keyring: bool = True
|
||||||
# Check keyring first for password.
|
|
||||||
# That way we'll have it.
|
|
||||||
if keyring_pw := get_keyring_password(self._journal_name):
|
|
||||||
self.password = keyring_pw
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def password(self) -> str:
|
def check_keyring(self) -> bool:
|
||||||
|
return self._check_keyring
|
||||||
|
|
||||||
|
@check_keyring.setter
|
||||||
|
def check_keyring(self, value: bool) -> None:
|
||||||
|
self._check_keyring = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def password(self) -> str | None:
|
||||||
return self._password
|
return self._password
|
||||||
|
|
||||||
@password.setter
|
@password.setter
|
||||||
def password(self, value: str) -> None:
|
def password(self, value: str) -> None:
|
||||||
self._password = value
|
self._password = value
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.password = None
|
||||||
|
self.check_keyring = False
|
||||||
|
|
||||||
def encrypt(self, text: str) -> bytes:
|
def encrypt(self, text: str) -> bytes:
|
||||||
logging.debug("encrypting")
|
logging.debug("encrypting")
|
||||||
if not self.password:
|
if not self.password:
|
||||||
self.password = create_password(self._journal_name)
|
if self.check_keyring and (
|
||||||
|
keyring_pw := get_keyring_password(self._journal_name)
|
||||||
|
):
|
||||||
|
self.password = keyring_pw
|
||||||
|
|
||||||
|
if not self.password:
|
||||||
|
self.password = create_password(self._journal_name)
|
||||||
|
|
||||||
return self._encrypt(text)
|
return self._encrypt(text)
|
||||||
|
|
||||||
def decrypt(self, text: bytes) -> str:
|
def decrypt(self, text: bytes) -> str:
|
||||||
logging.debug("decrypting")
|
logging.debug("decrypting")
|
||||||
if not self.password:
|
if not self.password:
|
||||||
self._prompt_password()
|
if self.check_keyring and (
|
||||||
|
keyring_pw := get_keyring_password(self._journal_name)
|
||||||
|
):
|
||||||
|
self.password = keyring_pw
|
||||||
|
|
||||||
|
if not self.password:
|
||||||
|
self._prompt_password()
|
||||||
|
|
||||||
while (result := self._decrypt(text)) is None:
|
while (result := self._decrypt(text)) is None:
|
||||||
self._prompt_password()
|
self._prompt_password()
|
||||||
|
|
|
@ -26,11 +26,15 @@ class Jrnlv2Encryption(BasePasswordEncryption):
|
||||||
return self._password
|
return self._password
|
||||||
|
|
||||||
@password.setter
|
@password.setter
|
||||||
def password(self, value):
|
def password(self, value: str | None):
|
||||||
self._password = value
|
self._password = value
|
||||||
self._make_key()
|
self._make_key()
|
||||||
|
|
||||||
def _make_key(self) -> None:
|
def _make_key(self) -> None:
|
||||||
|
if self._password is None:
|
||||||
|
# Password was removed after being set
|
||||||
|
self._key = None
|
||||||
|
return
|
||||||
password = self.password.encode(self._encoding)
|
password = self.password.encode(self._encoding)
|
||||||
kdf = PBKDF2HMAC(
|
kdf = PBKDF2HMAC(
|
||||||
algorithm=hashes.SHA256(),
|
algorithm=hashes.SHA256(),
|
||||||
|
|
|
@ -48,6 +48,7 @@ Feature: Encrypting and decrypting journals
|
||||||
|
|
||||||
Scenario: Encrypt journal twice and get prompted each time
|
Scenario: Encrypt journal twice and get prompted each time
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
|
And we don't have a keyring
|
||||||
When we run "jrnl --encrypt" and enter
|
When we run "jrnl --encrypt" and enter
|
||||||
swordfish
|
swordfish
|
||||||
swordfish
|
swordfish
|
||||||
|
@ -56,7 +57,26 @@ Feature: Encrypting and decrypting journals
|
||||||
And the output should contain "Journal encrypted"
|
And the output should contain "Journal encrypted"
|
||||||
When we run "jrnl --encrypt" and enter
|
When we run "jrnl --encrypt" and enter
|
||||||
swordfish
|
swordfish
|
||||||
|
tuna
|
||||||
|
tuna
|
||||||
|
y
|
||||||
|
Then we should get no error
|
||||||
|
And the output should contain "Journal default is already encrypted. Create a new password."
|
||||||
|
And we should be prompted for a password
|
||||||
|
And the config for journal "default" should contain "encrypt: true"
|
||||||
|
|
||||||
|
Scenario: Encrypt journal twice and get prompted each time with keyring
|
||||||
|
Given we use the config "simple.yaml"
|
||||||
|
And we have a keyring
|
||||||
|
When we run "jrnl --encrypt" and enter
|
||||||
swordfish
|
swordfish
|
||||||
|
swordfish
|
||||||
|
y
|
||||||
|
Then we should get no error
|
||||||
|
And the output should contain "Journal encrypted"
|
||||||
|
When we run "jrnl --encrypt" and enter
|
||||||
|
tuna
|
||||||
|
tuna
|
||||||
y
|
y
|
||||||
Then we should get no error
|
Then we should get no error
|
||||||
And the output should contain "Journal default is already encrypted. Create a new password."
|
And the output should contain "Journal default is already encrypted. Create a new password."
|
||||||
|
|
|
@ -17,6 +17,7 @@ from pytest_bdd.parsers import parse
|
||||||
from jrnl import __version__
|
from jrnl import __version__
|
||||||
from jrnl.time import __get_pdt_calendar
|
from jrnl.time import __get_pdt_calendar
|
||||||
from tests.lib.fixtures import FailedKeyring
|
from tests.lib.fixtures import FailedKeyring
|
||||||
|
from tests.lib.fixtures import NoKeyring
|
||||||
from tests.lib.fixtures import TestKeyring
|
from tests.lib.fixtures import TestKeyring
|
||||||
from tests.lib.helpers import get_fixture
|
from tests.lib.helpers import get_fixture
|
||||||
|
|
||||||
|
@ -67,13 +68,20 @@ def now_is_str(date_str, mock_factories):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@given("we don't have a keyring", target_fixture="keyring")
|
||||||
|
def we_dont_have_keyring(keyring_type):
|
||||||
|
return NoKeyring()
|
||||||
|
|
||||||
|
|
||||||
@given("we have a keyring", target_fixture="keyring")
|
@given("we have a keyring", target_fixture="keyring")
|
||||||
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
|
@given(parse("we have a {keyring_type} keyring"), target_fixture="keyring")
|
||||||
def we_have_type_of_keyring(keyring_type):
|
def we_have_type_of_keyring(keyring_type):
|
||||||
if keyring_type == "failed":
|
match keyring_type:
|
||||||
return FailedKeyring()
|
case "failed":
|
||||||
else:
|
return FailedKeyring()
|
||||||
return TestKeyring()
|
|
||||||
|
case _:
|
||||||
|
return TestKeyring()
|
||||||
|
|
||||||
|
|
||||||
@given(parse('we use the config "{config_file}"'), target_fixture="config_path")
|
@given(parse('we use the config "{config_file}"'), target_fixture="config_path")
|
||||||
|
|
Loading…
Add table
Reference in a new issue