[password_helper] implement
This commit is contained in:
parent
e970bdf3dc
commit
20ffc18044
7 changed files with 53 additions and 14 deletions
|
|
@ -22,11 +22,11 @@ AsyncSessionDependency = Annotated[async_sessionmaker, Depends(get_db_session)]
|
||||||
TokenDependency = Annotated[str, Depends(oauth2_scheme)]
|
TokenDependency = Annotated[str, Depends(oauth2_scheme)]
|
||||||
|
|
||||||
|
|
||||||
def verify_password(plain_password: str, hashed_password: str) -> bool:
|
def verify(plain_password: str, hashed_password: str) -> bool:
|
||||||
return pwd_context.verify(plain_password, hashed_password)
|
return pwd_context.verify(plain_password, hashed_password)
|
||||||
|
|
||||||
|
|
||||||
def get_password_hash(password: str) -> str:
|
def hash(password: str) -> str:
|
||||||
return pwd_context.hash(password)
|
return pwd_context.hash(password)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ class Context:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, repo: Repository) -> None:
|
def __init__(self, repo: Repository) -> None:
|
||||||
self.repo = Repository
|
self.repo = repo
|
||||||
|
|
||||||
|
|
||||||
class ContextDependency:
|
class ContextDependency:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from sqlalchemy.orm import DeclarativeBase, Mapped, declared_attr, mapped_column
|
from sqlalchemy.orm import DeclarativeBase, Mapped, declared_attr, mapped_column
|
||||||
|
from ..utils.password_helper import password_helper
|
||||||
|
|
||||||
|
|
||||||
class Base(DeclarativeBase):
|
class Base(DeclarativeBase):
|
||||||
|
|
@ -30,13 +31,8 @@ class PasswordMixin:
|
||||||
|
|
||||||
hashed_password: Mapped[str]
|
hashed_password: Mapped[str]
|
||||||
|
|
||||||
def set_password(self, password) -> None:
|
def set_password(self, password: str) -> None:
|
||||||
"""set_password.
|
|
||||||
|
|
||||||
:param password:
|
|
||||||
:rtype: None
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ..auth import password_helper
|
|
||||||
|
|
||||||
self.hashed_password = password_helper.hash(password)
|
self.hashed_password = password_helper.hash(password)
|
||||||
|
|
||||||
|
def verify_password(self, password: str) -> bool:
|
||||||
|
return password_helper.verify(password, self.hashed_password)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import List
|
from typing import Any
|
||||||
|
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
|
@ -15,9 +15,11 @@ class Settings(BaseSettings):
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
||||||
REFRESH_TOKEN_EXPIRE_DAYS: int = 120
|
REFRESH_TOKEN_EXPIRE_DAYS: int = 120
|
||||||
|
|
||||||
ALLOWED_ORIGINS: List[str] = ["*"]
|
ALLOWED_ORIGINS: list[str] = ["*"]
|
||||||
|
|
||||||
API_KEY: str
|
API_KEY: str
|
||||||
|
|
||||||
|
PASSWORD_SCHEMES: list[str] = ["bcrypt"]
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
|
||||||
0
fooder/test/utils/__init__.py
Normal file
0
fooder/test/utils/__init__.py
Normal file
25
fooder/test/utils/test_password_helper.py
Normal file
25
fooder/test/utils/test_password_helper.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
from fooder.utils.password_helper import password_helper
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_password_hash_and_verify(faker):
|
||||||
|
password = faker.password()
|
||||||
|
hash = password_helper.hash(password)
|
||||||
|
|
||||||
|
assert password_helper.verify(password, hash)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wrong_password_doesnt_verify(faker):
|
||||||
|
password = faker.password()
|
||||||
|
hash = password_helper.hash(password)
|
||||||
|
|
||||||
|
password2 = faker.password()
|
||||||
|
assert not password_helper.verify(password2, hash)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wrong_hash_breaks(faker):
|
||||||
|
password = faker.password()
|
||||||
|
hash = password_helper.hash(password)
|
||||||
|
|
||||||
|
with pytest.raises(Exception, match="malformed"):
|
||||||
|
assert not password_helper.verify(password, hash + password)
|
||||||
16
fooder/utils/password_helper.py
Normal file
16
fooder/utils/password_helper.py
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
from passlib.context import CryptContext
|
||||||
|
from ..settings import settings
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordHelper:
|
||||||
|
def __init__(self, pwd_context: CryptContext):
|
||||||
|
self.pwd_context = pwd_context
|
||||||
|
|
||||||
|
def verify(self, plain_password: str, hashed_password: str) -> bool:
|
||||||
|
return self.pwd_context.verify(plain_password, hashed_password)
|
||||||
|
|
||||||
|
def hash(self, password: str) -> str:
|
||||||
|
return self.pwd_context.hash(password)
|
||||||
|
|
||||||
|
|
||||||
|
password_helper = PasswordHelper(CryptContext(settings.PASSWORD_SCHEMES))
|
||||||
Loading…
Reference in a new issue