Repository: jugmac00/hibpcli

Issue:
Enable single password testing
One should be able to check single password against the hibp API for being leaked or not.

Also see #17 for more information about the new interface.


Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30cb6e7..569bdf2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
 
 ## unreleased
 
+- add new subcommand "password" for checking a single password
+
 ## 0.2.0 (02.11.2019)
 
 ### added
diff --git a/README.md b/README.md
index cf2b4e5..e414da2 100644
--- a/README.md
+++ b/README.md
@@ -9,33 +9,29 @@ A command line interface for the "haveibeenpwned.com" API - speaks keepass.
 
 ## current state
 
-Very alpha.
+A little bit alpha.
 
 ## usage
 
 ```
-$ hibpcli keepass
+$ hibpcli keepass --path PATHTOKEEPASSDB --password PASSWORDFORKEEPASSDB
 
-Please enter the path to the database: tests/test.kdbx
-Please enter the master password for the database:
 The passwords of following entries are leaked:
 [Entry: "test_title (test_user)"]
 ```
 
-or
-
 ```
-$ hibpcli keepass --path PATHTOKEEPASSDB --password PASSWORDFORKEEPASSDB
+$ hibpcli password --password test
 
-The passwords of following entries are leaked:
-[Entry: "test_title (test_user)"]
+Please change your password!
 ```
 
+
 ## scope
 
 - check passwords in db via hibp online API (currently)
 - check passwords in db via offline check (future)
-- enter passwords manually (future)
+- enter passwords manually (currently)
 
 ## contributions, feature requests, bug reports
 
diff --git a/hibpcli/cli.py b/hibpcli/cli.py
index 0c8236c..d82084e 100644
--- a/hibpcli/cli.py
+++ b/hibpcli/cli.py
@@ -1,6 +1,7 @@
 import click
 
 from hibpcli.keepass import check_passwords_from_db
+from hibpcli.password import Password
 
 
 @click.group()
@@ -31,7 +32,23 @@ def keepass(path, password):
         click.echo("Hooray, everything is safe!")
 
 
+@click.command()
+@click.option('--password', default=None, help='Password which should be checked.')
+def password(password):
+    """Check a single password."""
+    #breakpoint()
+    if password is None:
+         password = click.prompt(
+            "Please enter a password which should be checked", hide_input=True
+        )
+    p = Password(password)
+    if p.is_leaked():
+        click.echo("Please change your password!")
+    else:
+        click.echo("Your password is safe!")
+
 main.add_command(keepass)
+main.add_command(password)
 
 
 if __name__ == "__main__":


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index f6245f6..d58f909 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -4,6 +4,7 @@ from click.testing import CliRunner
 from unittest.mock import patch
 
 from hibpcli.cli import main
+from hibpcli.password import Password
 
 
 @patch("hibpcli.cli.check_passwords_from_db")
@@ -64,3 +65,36 @@ def test_keepass_subcommand_with_path_and_password_options(mock_check):
         [b'Entry: "test_title (test_user)"']
     """
     assert result.output == textwrap.dedent(expected_output)
+
+
+@patch.object(Password, "is_leaked", return_value=True)
+def test_password_subcommand_for_leaked_password(mock_password):
+    runner = CliRunner()
+    result = runner.invoke(
+        main, ["password", "--password", "test"]
+    )
+    expected_output = "Please change your password!\n"
+    assert result.output == expected_output
+
+
+@patch.object(Password, "is_leaked", return_value=False)
+def test_password_subcommand_for_safe_password(mock_password):
+    runner = CliRunner()
+    result = runner.invoke(
+        main, ["password", "--password", "test"]
+    )
+    expected_output = "Your password is safe!\n"
+    assert result.output == expected_output
+
+
+@patch.object(Password, "is_leaked", return_value=False)
+def test_password_subcommand_with_prompt(mock_password):
+    runner = CliRunner()
+    result = runner.invoke(
+        main, ["password"], input="test"
+    )
+    expected_output = """\
+        Please enter a password which should be checked: 
+        Your password is safe!
+    """
+    assert result.output == textwrap.dedent(expected_output)