mirror of
https://github.com/fastapi-users/fastapi-users.git
synced 2025-08-14 18:58:10 +08:00
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
import secrets
|
|
from typing import Optional, Protocol, Union
|
|
|
|
from pwdlib import PasswordHash
|
|
from pwdlib.hashers.argon2 import Argon2Hasher
|
|
from pwdlib.hashers.bcrypt import BcryptHasher
|
|
|
|
|
|
class PasswordHelperProtocol(Protocol):
|
|
def verify_and_update(
|
|
self, plain_password: str, hashed_password: str
|
|
) -> tuple[bool, Union[str, None]]: ... # pragma: no cover
|
|
|
|
def hash(self, password: str) -> str: ... # pragma: no cover
|
|
|
|
def generate(self) -> str: ... # pragma: no cover
|
|
|
|
|
|
class PasswordHelper(PasswordHelperProtocol):
|
|
def __init__(self, password_hash: Optional[PasswordHash] = None) -> None:
|
|
if password_hash is None:
|
|
self.password_hash = PasswordHash(
|
|
(
|
|
Argon2Hasher(),
|
|
BcryptHasher(),
|
|
)
|
|
)
|
|
else:
|
|
self.password_hash = password_hash # pragma: no cover
|
|
|
|
def verify_and_update(
|
|
self, plain_password: str, hashed_password: str
|
|
) -> tuple[bool, Union[str, None]]:
|
|
return self.password_hash.verify_and_update(plain_password, hashed_password)
|
|
|
|
def hash(self, password: str) -> str:
|
|
return self.password_hash.hash(password)
|
|
|
|
def generate(self) -> str:
|
|
return secrets.token_urlsafe()
|