mirror of
https://github.com/rjNemo/pass-gen
synced 2026-06-12 13:26:42 +00:00
feat: can read stored passwords
This commit is contained in:
parent
bcf359950d
commit
a1d4ef498b
9 changed files with 47 additions and 6 deletions
|
|
@ -11,5 +11,5 @@ class DB:
|
||||||
def commit(self) -> None:
|
def commit(self) -> None:
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
|
|
||||||
def execute(self, query: str, *args: Any) -> None:
|
def execute(self, query: str, *args: Any) -> sqlite3.Cursor:
|
||||||
self.cursor.execute(query, *args)
|
return self.cursor.execute(query, *args)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from sqlite3 import Cursor
|
||||||
from typing import Any, Protocol
|
from typing import Any, Protocol
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,5 +6,5 @@ class DBConnector(Protocol):
|
||||||
def commit(self) -> None:
|
def commit(self) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
def execute(self, query: str, *args: Any) -> None:
|
def execute(self, query: str, *args: Any) -> Cursor:
|
||||||
...
|
...
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ app = typer.Typer()
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def main(
|
def save(
|
||||||
length: int = typer.Option(
|
length: int = typer.Option(
|
||||||
8,
|
8,
|
||||||
"--length",
|
"--length",
|
||||||
|
|
@ -57,3 +57,10 @@ def main(
|
||||||
|
|
||||||
utils.copy_to_clipboard(password)
|
utils.copy_to_clipboard(password)
|
||||||
return typer.echo("The password has been copied to your clipboard 😉\nPaste it using cmd + v")
|
return typer.echo("The password has been copied to your clipboard 😉\nPaste it using cmd + v")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def read() -> None:
|
||||||
|
sqlite_repo = sqlite.get_instance()
|
||||||
|
stored_passwords = sqlite_repo.list_all()
|
||||||
|
typer.echo(stored_passwords)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ class FakeRepository:
|
||||||
def save(self, password: str) -> None:
|
def save(self, password: str) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def list_all(self) -> list[str]:
|
||||||
|
return ["2yW4AcqG", "iK2ZWeqh"]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance(cls) -> FakeRepository:
|
def get_instance(cls) -> FakeRepository:
|
||||||
return FakeRepository()
|
return FakeRepository()
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ class PasswordRepository:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
def list_all(self) -> list[str]:
|
||||||
|
return [row[0] for row in self.db.execute("SELECT * FROM passwords").fetchall()]
|
||||||
|
|
||||||
|
|
||||||
def get_instance() -> PasswordRepository:
|
def get_instance() -> PasswordRepository:
|
||||||
db = sqlite.DB()
|
db = sqlite.DB()
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,6 @@ from typing import Protocol
|
||||||
class Repository(Protocol):
|
class Repository(Protocol):
|
||||||
def save(self, password: str) -> None:
|
def save(self, password: str) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def list_all(self) -> list[str]:
|
||||||
|
...
|
||||||
|
|
|
||||||
|
|
@ -39,3 +39,7 @@ def _build_characters(symbols: bool, numbers: bool) -> str:
|
||||||
string.digits if numbers else "",
|
string.digits if numbers else "",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def list_all_saved_passwords(repo: Repository) -> list[str]:
|
||||||
|
return repo.list_all()
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,19 @@ def test_cli_can_save_to_file() -> None:
|
||||||
assert "2yW4AcqG" in content
|
assert "2yW4AcqG" in content
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli_can_save_to_db() -> None:
|
||||||
|
_run_cli()
|
||||||
|
result = _run_cli_read()
|
||||||
|
assert "2yW4AcqG" in result.stdout
|
||||||
|
|
||||||
|
|
||||||
def _run_cli(*args: Any) -> Result:
|
def _run_cli(*args: Any) -> Result:
|
||||||
result = runner.invoke(app, ["--no-random", *args])
|
result = runner.invoke(app, ["save", "--no-random", *args])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _run_cli_read(*args: Any) -> Result:
|
||||||
|
result = runner.invoke(app, ["read", *args])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from app.repositories.fake import FakeRepository
|
from app.repositories.fake import FakeRepository
|
||||||
from app.usecases.pass_gen import PassGenOptions, generate_password
|
from app.usecases.pass_gen import PassGenOptions, generate_password, list_all_saved_passwords
|
||||||
|
|
||||||
fake_repo = FakeRepository.get_instance()
|
fake_repo = FakeRepository.get_instance()
|
||||||
|
|
||||||
|
|
@ -52,3 +52,11 @@ def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -
|
||||||
def test_password_can_contain_numbers(seed: int, numbers: bool, expected: str) -> None:
|
def test_password_can_contain_numbers(seed: int, numbers: bool, expected: str) -> None:
|
||||||
options = PassGenOptions(seed=seed, numbers=numbers)
|
options = PassGenOptions(seed=seed, numbers=numbers)
|
||||||
assert generate_password(fake_repo, options) == expected
|
assert generate_password(fake_repo, options) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"expected",
|
||||||
|
[["2yW4AcqG", "iK2ZWeqh"]],
|
||||||
|
)
|
||||||
|
def test_can_read_all_saved_passwords(expected: list[str]) -> None:
|
||||||
|
assert list_all_saved_passwords(fake_repo) == expected
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue