mirror of
https://github.com/rjNemo/pass-gen
synced 2026-06-06 02:26:42 +00:00
50 lines
1.3 KiB
Python
50 lines
1.3 KiB
Python
import random
|
|
import string
|
|
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
|
|
numbers: bool = True
|
|
|
|
|
|
def generate_password(repo: Repository, options: PassGenOptions) -> str:
|
|
if repo.exists(options.service):
|
|
raise ValueError("password for this service has already been set")
|
|
|
|
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(options.service, password)
|
|
return password
|
|
|
|
|
|
class RandomSampler(Protocol):
|
|
def sample(self, population: str, k: int) -> list[str]:
|
|
... # pragma nocover
|
|
|
|
|
|
def _new_random_generator(seed: int) -> RandomSampler:
|
|
return random.Random(seed)
|
|
|
|
|
|
def _build_characters(symbols: bool, numbers: bool) -> str:
|
|
return "".join(
|
|
[
|
|
string.ascii_letters,
|
|
string.punctuation if symbols else "",
|
|
string.digits if numbers else "",
|
|
]
|
|
)
|
|
|
|
|
|
def list_all_saved_passwords(repo: Repository) -> list[Password]:
|
|
return repo.list_all()
|