mirror of
https://github.com/rjNemo/pass-gen
synced 2026-06-06 02:26:42 +00:00
feat: password service
This commit is contained in:
parent
668ac34dbc
commit
d3116898e6
10 changed files with 90 additions and 66 deletions
19
Pipfile
19
Pipfile
|
|
@ -4,17 +4,18 @@ verify_ssl = true
|
|||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
pydantic = "==1.8.2"
|
||||
typer = "==0.3.2"
|
||||
pydantic = "~=1.8.2"
|
||||
typer = "~=0.3.2"
|
||||
|
||||
[dev-packages]
|
||||
bandit = "==1.7.0"
|
||||
black = "==21.6b0"
|
||||
flake8 = "==3.9.2"
|
||||
mypy = "==0.910"
|
||||
pytest = "==6.2.4"
|
||||
pytest-cov = "==2.12.1"
|
||||
vulture = "==2.3"
|
||||
bandit = "~=1.7.0"
|
||||
black = "~=21.6b0"
|
||||
faker = "~=8.11.0"
|
||||
flake8 = "~=3.9.2"
|
||||
mypy = "~=0.910"
|
||||
pytest = "~=6.2.4"
|
||||
pytest-cov = "~=2.12.1"
|
||||
vulture = "~=2.3"
|
||||
|
||||
[scripts]
|
||||
passgen = "python -m app"
|
||||
|
|
|
|||
101
Pipfile.lock
generated
101
Pipfile.lock
generated
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "b1bba35cf3809622ba68e5c6d3e45856f177c2de92180eba2caf325ff287149c"
|
||||
"sha256": "e020691d3e4002190842b05b21ca5fcdc744e8b61f204413510cb82fd0aebdac"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
|
@ -145,6 +145,14 @@
|
|||
"markers": "python_version >= '3.6'",
|
||||
"version": "==6.0b1"
|
||||
},
|
||||
"faker": {
|
||||
"hashes": [
|
||||
"sha256:3e737576ff50cd98dfed643d6b3fd63194eca9df00e7f595960fe7da5220723d",
|
||||
"sha256:b9e81e9da3dda3ac54189e034cfb943de576a259caeb226ccab43fcbcf6a7891"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==8.11.0"
|
||||
},
|
||||
"flake8": {
|
||||
"hashes": [
|
||||
"sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b",
|
||||
|
|
@ -298,6 +306,14 @@
|
|||
"index": "pypi",
|
||||
"version": "==2.12.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
|
||||
|
|
@ -335,49 +351,41 @@
|
|||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f",
|
||||
"sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad",
|
||||
"sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a",
|
||||
"sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf",
|
||||
"sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59",
|
||||
"sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d",
|
||||
"sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895",
|
||||
"sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4",
|
||||
"sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3",
|
||||
"sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222",
|
||||
"sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0",
|
||||
"sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c",
|
||||
"sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417",
|
||||
"sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d",
|
||||
"sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d",
|
||||
"sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761",
|
||||
"sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0",
|
||||
"sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026",
|
||||
"sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854",
|
||||
"sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb",
|
||||
"sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d",
|
||||
"sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068",
|
||||
"sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde",
|
||||
"sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d",
|
||||
"sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec",
|
||||
"sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa",
|
||||
"sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd",
|
||||
"sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b",
|
||||
"sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26",
|
||||
"sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2",
|
||||
"sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f",
|
||||
"sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694",
|
||||
"sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0",
|
||||
"sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407",
|
||||
"sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874",
|
||||
"sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035",
|
||||
"sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d",
|
||||
"sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c",
|
||||
"sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5",
|
||||
"sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985",
|
||||
"sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58"
|
||||
"sha256:026beb631097a4a3def7299aa5825e05e057de3c6d72b139c37813bfa351274b",
|
||||
"sha256:14caacd1853e40103f59571f169704367e79fb78fac3d6d09ac84d9197cadd16",
|
||||
"sha256:16d9eaa8c7e91537516c20da37db975f09ac2e7772a0694b245076c6d68f85da",
|
||||
"sha256:18fdc51458abc0a974822333bd3a932d4e06ba2a3243e9a1da305668bd62ec6d",
|
||||
"sha256:28e8af338240b6f39713a34e337c3813047896ace09d51593d6907c66c0708ba",
|
||||
"sha256:3835de96524a7b6869a6c710b26c90e94558c31006e96ca3cf6af6751b27dca1",
|
||||
"sha256:3905c86cc4ab6d71635d6419a6f8d972cab7c634539bba6053c47354fd04452c",
|
||||
"sha256:3c09d88a07483231119f5017904db8f60ad67906efac3f1baa31b9b7f7cca281",
|
||||
"sha256:4551728b767f35f86b8e5ec19a363df87450c7376d7419c3cac5b9ceb4bce576",
|
||||
"sha256:459bbe342c5b2dec5c5223e7c363f291558bc27982ef39ffd6569e8c082bdc83",
|
||||
"sha256:4f421e3cdd3a273bace013751c345f4ebeef08f05e8c10757533ada360b51a39",
|
||||
"sha256:577737ec3d4c195c4aef01b757905779a9e9aee608fa1cf0aec16b5576c893d3",
|
||||
"sha256:57fece29f7cc55d882fe282d9de52f2f522bb85290555b49394102f3621751ee",
|
||||
"sha256:7976d410e42be9ae7458c1816a416218364e06e162b82e42f7060737e711d9ce",
|
||||
"sha256:85f568892422a0e96235eb8ea6c5a41c8ccbf55576a2260c0160800dbd7c4f20",
|
||||
"sha256:8764a78c5464ac6bde91a8c87dd718c27c1cabb7ed2b4beaf36d3e8e390567f9",
|
||||
"sha256:8935937dad2c9b369c3d932b0edbc52a62647c2afb2fafc0c280f14a8bf56a6a",
|
||||
"sha256:8fe58d9f6e3d1abf690174fd75800fda9bdc23d2a287e77758dc0e8567e38ce6",
|
||||
"sha256:937b20955806381e08e54bd9d71f83276d1f883264808521b70b33d98e4dec5d",
|
||||
"sha256:9569da9e78f0947b249370cb8fadf1015a193c359e7e442ac9ecc585d937f08d",
|
||||
"sha256:a3b73390511edd2db2d34ff09aa0b2c08be974c71b4c0505b4a048d5dc128c2b",
|
||||
"sha256:a4eddbe2a715b2dd3849afbdeacf1cc283160b24e09baf64fa5675f51940419d",
|
||||
"sha256:a5c6dbe09aff091adfa8c7cfc1a0e83fdb8021ddb2c183512775a14f1435fe16",
|
||||
"sha256:b63e3571b24a7959017573b6455e05b675050bbbea69408f35f3cb984ec54363",
|
||||
"sha256:bb350eb1060591d8e89d6bac4713d41006cd4d479f5e11db334a48ff8999512f",
|
||||
"sha256:bf6d987edd4a44dd2fa2723fca2790f9442ae4de2c8438e53fcb1befdf5d823a",
|
||||
"sha256:bfa6a679410b394600eafd16336b2ce8de43e9b13f7fb9247d84ef5ad2b45e91",
|
||||
"sha256:c856ec9b42e5af4fe2d8e75970fcc3a2c15925cbcc6e7a9bcb44583b10b95e80",
|
||||
"sha256:cea56288eeda8b7511d507bbe7790d89ae7049daa5f51ae31a35ae3c05408531",
|
||||
"sha256:ea212df6e5d3f60341aef46401d32fcfded85593af1d82b8b4a7a68cd67fdd6b",
|
||||
"sha256:f35567470ee6dbfb946f069ed5f5615b40edcbb5f1e6e1d3d2b114468d505fc6",
|
||||
"sha256:fbc20975eee093efa2071de80df7f972b7b35e560b213aafabcec7c0bd00bd8c",
|
||||
"sha256:ff4a8ad9638b7ca52313d8732f37ecd5fd3c8e3aff10a8ccb93176fd5b3812f6"
|
||||
],
|
||||
"version": "==2021.7.6"
|
||||
"version": "==2021.8.3"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
|
@ -403,6 +411,13 @@
|
|||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.3.0"
|
||||
},
|
||||
"text-unidecode": {
|
||||
"hashes": [
|
||||
"sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8",
|
||||
"sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"
|
||||
],
|
||||
"version": "==1.3"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ class DB:
|
|||
self.connection = sqlite3.connect(db_str)
|
||||
self.cursor = self.connection.cursor()
|
||||
self.execute(
|
||||
"CREATE TABLE IF NOT EXISTS passwords (id integer PRIMARY KEY , service text UNIQUE NOT NULL, "
|
||||
"password text NOT NULL)"
|
||||
"CREATE TABLE IF NOT EXISTS passwords (id integer PRIMARY KEY, "
|
||||
"service text UNIQUE NOT NULL, password text NOT NULL)"
|
||||
)
|
||||
|
||||
def commit(self) -> None:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ app = typer.Typer()
|
|||
|
||||
@app.command()
|
||||
def save(
|
||||
service: str = typer.Argument(..., help="Name of the service associated to the password"),
|
||||
length: int = typer.Option(
|
||||
8,
|
||||
"--length",
|
||||
|
|
@ -41,6 +42,7 @@ def save(
|
|||
sqlite_repo = sqlite.get_instance()
|
||||
seed = r.randint(0, 100) if random else 0
|
||||
options = pass_gen.PassGenOptions(
|
||||
service=service,
|
||||
seed=seed,
|
||||
length=length,
|
||||
symbols=symbols,
|
||||
|
|
@ -63,4 +65,4 @@ def save(
|
|||
def read() -> None:
|
||||
sqlite_repo = sqlite.get_instance()
|
||||
stored_passwords = sqlite_repo.list_all()
|
||||
typer.echo(*[f"{p.service}: {p.password.get_secret_value()}" for p in stored_passwords])
|
||||
typer.echo([f"{p.service}: {p.password.get_secret_value()}" for p in stored_passwords])
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from app.models.password import Password
|
|||
|
||||
|
||||
class FakeRepository:
|
||||
def save(self, password: str) -> None:
|
||||
def save(self, service: str, password: str) -> None:
|
||||
...
|
||||
|
||||
def list_all(self) -> list[Password]:
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ class PasswordRepository:
|
|||
def __init__(self, db: DBConnector) -> None:
|
||||
self.db = db
|
||||
|
||||
def save(self, password: str) -> None:
|
||||
def save(self, service: str, password: str) -> None:
|
||||
try:
|
||||
self.db.execute(
|
||||
"INSERT INTO passwords VALUES (null, :service, :password)",
|
||||
{"service": "service", "password": password},
|
||||
{"service": service, "password": password},
|
||||
)
|
||||
|
||||
self.db.commit()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from app.models.password import Password
|
|||
|
||||
|
||||
class Repository(Protocol):
|
||||
def save(self, password: str) -> None:
|
||||
def save(self, service: str, password: str) -> None:
|
||||
...
|
||||
|
||||
def list_all(self) -> list[Password]:
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ from typing import Protocol
|
|||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.models.password import Password
|
||||
from app.repositories.type import Repository
|
||||
|
||||
|
||||
class PassGenOptions(BaseModel):
|
||||
service: str
|
||||
seed: int
|
||||
length: int = 8
|
||||
symbols: bool = False
|
||||
|
|
@ -18,7 +20,7 @@ def generate_password(repo: Repository, options: PassGenOptions) -> str:
|
|||
characters = _build_characters(symbols=options.symbols, numbers=options.numbers)
|
||||
random_generator = _new_random_generator(options.seed)
|
||||
password = "".join(random_generator.sample(characters, options.length))
|
||||
repo.save(password)
|
||||
repo.save(options.service, password)
|
||||
return password
|
||||
|
||||
|
||||
|
|
@ -41,5 +43,5 @@ def _build_characters(symbols: bool, numbers: bool) -> str:
|
|||
)
|
||||
|
||||
|
||||
def list_all_saved_passwords(repo: Repository) -> list[str]:
|
||||
def list_all_saved_passwords(repo: Repository) -> list[Password]:
|
||||
return repo.list_all()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
from typing import Any
|
||||
|
||||
from faker import Factory
|
||||
|
||||
from app.main import app
|
||||
from typer.testing import CliRunner, Result
|
||||
|
||||
|
||||
runner = CliRunner()
|
||||
faker = Factory.create()
|
||||
|
||||
|
||||
def test_cli_print_password() -> None:
|
||||
|
|
@ -47,7 +50,7 @@ def test_cli_can_save_to_db() -> None:
|
|||
|
||||
|
||||
def _run_cli(*args: Any) -> Result:
|
||||
result = runner.invoke(app, ["save", "--no-random", *args])
|
||||
result = runner.invoke(app, ["save", faker.pystr(), "--no-random", *args])
|
||||
assert result.exit_code == 0
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from app.repositories.fake import FakeRepository
|
|||
from app.usecases.pass_gen import PassGenOptions, generate_password, list_all_saved_passwords
|
||||
|
||||
fake_repo = FakeRepository.get_instance()
|
||||
service = "service_name"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -16,7 +17,7 @@ fake_repo = FakeRepository.get_instance()
|
|||
],
|
||||
)
|
||||
def test_can_generate_random_password(seed: int, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed)
|
||||
options = PassGenOptions(seed=seed, service=service)
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -28,7 +29,7 @@ def test_can_generate_random_password(seed: int, expected: str) -> None:
|
|||
],
|
||||
)
|
||||
def test_control_password_length(seed: int, length: int, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, length=length)
|
||||
options = PassGenOptions(seed=seed, length=length, service=service)
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ def test_control_password_length(seed: int, length: int, expected: str) -> None:
|
|||
],
|
||||
)
|
||||
def test_password_can_contain_symbols(seed: int, symbols: bool, expected: str) -> None:
|
||||
options = PassGenOptions(seed=seed, symbols=symbols)
|
||||
options = PassGenOptions(seed=seed, symbols=symbols, service=service)
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ 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:
|
||||
options = PassGenOptions(seed=seed, numbers=numbers)
|
||||
options = PassGenOptions(seed=seed, numbers=numbers, service=service)
|
||||
assert generate_password(fake_repo, options) == expected
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue