Added ability to auto-prompt for password for encrypted journals

Only uses password when prompted, and doesn't get in the way of other
input prompts. This allows us to run the same scenarios on both
encrypted journals and other journal types.

Co-authored-by: Micah Jerome Ellison <micah.jerome.ellison@gmail.com>
This commit is contained in:
Jonathan Wren 2020-09-26 14:52:31 -07:00
parent fda3fe2357
commit cf369f3f84
No known key found for this signature in database
GPG key ID: 43D5FF8722E7F68A
5 changed files with 42 additions and 28 deletions

View file

@ -6,7 +6,7 @@ colors:
default_hour: 9 default_hour: 9
default_minute: 0 default_minute: 0
editor: "" editor: ""
encrypt: false encrypt: true
highlight: true highlight: true
journals: journals:
default: features/journals/basic_encrypted.journal default: features/journals/basic_encrypted.journal

View file

@ -1,7 +1,8 @@
Feature: Delete entries from journal Feature: Delete entries from journal
Scenario Outline: Delete flag allows deletion of single entry Scenario Outline: Delete flag allows deletion of single entry
Given we use the config "<config>.yaml" Given we use the config "<config>.yaml"
When we run "jrnl -n 1" And we use the password "test" if prompted
When we run "jrnl -1"
Then the output should contain "2020-09-24 09:14 The third entry finally" Then the output should contain "2020-09-24 09:14 The third entry finally"
When we run "jrnl --delete" and enter When we run "jrnl --delete" and enter
""" """
@ -20,6 +21,7 @@ Feature: Delete entries from journal
Examples: Configs Examples: Configs
| config | | config |
| basic_onefile | | basic_onefile |
| basic_encrypted |
# | basic_folder | @todo # | basic_folder | @todo
# | basic_dayone | @todo # | basic_dayone | @todo

View file

@ -130,6 +130,16 @@ def set_config(context, config_file):
cf.write("version: {}".format(__version__)) cf.write("version: {}".format(__version__))
@given('we use the password "{password}" if prompted')
def use_password_forever(context, password):
context.password = password
@given('we use the password "{password}" {num:d} times if prompted')
def use_password(context, password, num=1):
context.password = iter([password] * num)
@given("we have a keyring") @given("we have a keyring")
def set_keyring(context): def set_keyring(context):
keyring.set_keyring(TestKeyring()) keyring.set_keyring(TestKeyring())
@ -210,8 +220,9 @@ def matches_editor_arg(context, regex):
def _mock_getpass(inputs): def _mock_getpass(inputs):
def prompt_return(prompt="Password: "): def prompt_return(prompt=""):
print(prompt) if type(inputs) == str:
return inputs
try: try:
return next(inputs) return next(inputs)
except StopIteration: except StopIteration:
@ -251,11 +262,16 @@ def run_with_input(context, command, inputs=""):
context.editor_file = tmpfile context.editor_file = tmpfile
Path(tmpfile).touch() Path(tmpfile).touch()
if "password" in context:
password = context.password
else:
password = text
# fmt: off # fmt: off
# see: https://github.com/psf/black/issues/664 # see: https://github.com/psf/black/issues/664
with \ with \
patch("builtins.input", side_effect=_mock_input(text)) as mock_input, \ patch("builtins.input", side_effect=_mock_input(text)) as mock_input, \
patch("getpass.getpass", side_effect=_mock_getpass(text)) as mock_getpass, \ patch("getpass.getpass", side_effect=_mock_getpass(password)) as mock_getpass, \
patch("sys.stdin.read", side_effect=text) as mock_read, \ patch("sys.stdin.read", side_effect=text) as mock_read, \
patch("subprocess.call", side_effect=_mock_editor) as mock_editor \ patch("subprocess.call", side_effect=_mock_editor) as mock_editor \
: :
@ -323,12 +339,23 @@ def run(context, command, text="", cache_dir=None):
def _mock_editor(command): def _mock_editor(command):
context.editor_command = command context.editor_command = command
if "password" in context:
password = context.password
else:
password = iter(text)
try: try:
with patch("sys.argv", args), patch( # fmt: off
"subprocess.call", side_effect=_mock_editor # see: https://github.com/psf/black/issues/664
), patch("sys.stdin.read", side_effect=lambda: text): with \
patch("sys.argv", args), \
patch("getpass.getpass", side_effect=_mock_getpass(password)), \
patch("subprocess.call", side_effect=_mock_editor), \
patch("sys.stdin.read", side_effect=lambda: text) \
:
cli(args[1:]) cli(args[1:])
context.exit_status = 0 context.exit_status = 0
# fmt: on
except SystemExit as e: except SystemExit as e:
context.exit_status = e.code context.exit_status = e.code

View file

@ -21,7 +21,7 @@ Feature: Upgrading Journals from 1.x.x to 2.x.x
bad doggie no biscuit bad doggie no biscuit
bad doggie no biscuit bad doggie no biscuit
""" """
Then the output should contain "Password" Then we should be prompted for a password
And the output should contain "2013-06-10 15:40 Life is good" And the output should contain "2013-06-10 15:40 Life is good"
Scenario: Upgrading a config without colors to colors Scenario: Upgrading a config without colors to colors

View file

@ -93,6 +93,7 @@ Feature: Writing new entries.
Scenario Outline: Writing an empty entry from the editor should yield nothing Scenario Outline: Writing an empty entry from the editor should yield nothing
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>.yaml"
And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl" and enter nothing When we run "jrnl" and enter nothing
Then the output should be empty Then the output should be empty
And the error output should contain "[Nothing saved to file]" And the error output should contain "[Nothing saved to file]"
@ -103,13 +104,7 @@ Feature: Writing new entries.
| editor | | editor |
| editor_empty_folder | | editor_empty_folder |
| dayone | | dayone |
| editor_encrypted |
Scenario: Writing an empty entry from the editor should yield nothing in encrypted journal
Given we use the config "editor_encrypted.yaml"
When we run "jrnl" and enter "bad doggie no biscuit"
Then the output should be "Password:"
And the error output should contain "[Nothing saved to file]"
And the editor should have been called
Scenario Outline: Writing an entry does not print the entire journal Scenario Outline: Writing an entry does not print the entire journal
# https://github.com/jrnl-org/jrnl/issues/87 # https://github.com/jrnl-org/jrnl/issues/87
@ -184,6 +179,7 @@ Feature: Writing new entries.
Scenario Outline: Writing an entry at the prompt (no editor) should store the entry Scenario Outline: Writing an entry at the prompt (no editor) should store the entry
Given we use the config "<config_file>.yaml" Given we use the config "<config_file>.yaml"
And we use the password "bad doggie no biscuit" if prompted
When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive." When we run "jrnl" and enter "25 jul 2013: I saw Elvis. He's alive."
Then we should get no error Then we should get no error
When we run "jrnl -on '2013-07-25'" When we run "jrnl -on '2013-07-25'"
@ -194,22 +190,11 @@ Feature: Writing new entries.
| config_file | | config_file |
| simple | | simple |
| empty_folder | | empty_folder |
| encrypted |
@todo # Need to test DayOne w/out an editor @todo # Need to test DayOne w/out an editor
Scenario: Writing an entry at the prompt (no editor) in DayOne journal Scenario: Writing an entry at the prompt (no editor) in DayOne journal
Scenario: Writing an entry at the prompt (no editor) in encrypted journal
Given we use the config "encrypted.yaml"
When we run "jrnl" and enter
"""
bad doggie no biscuit
25 jul 2013: I saw Elvis. He's alive.
"""
Then we should get no error
When we run "jrnl -on '2013-07-25'" and enter "bad doggie no biscuit"
Then the output should contain "2013-07-25 09:00 I saw Elvis."
And the output should contain "| He's alive."
Scenario: Writing into Dayone Scenario: Writing into Dayone
Given we use the config "dayone.yaml" Given we use the config "dayone.yaml"
When we run "jrnl 01 may 1979: Being born hurts." When we run "jrnl 01 may 1979: Being born hurts."