main
Сергей Ванюшкин 2024-04-04 10:51:51 +00:00
parent b04eba9bc4
commit f8f5bf80c1
6 changed files with 74 additions and 37 deletions

View File

@ -1,22 +1,23 @@
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
from sqlalchemy.ext.asyncio import (AsyncEngine, AsyncSession,
async_sessionmaker)
from api.application.abstractions.uow import UnitOfWork
from api.application.protocols.date_time import DateTimeProvider
from api.application.protocols.jwt import JwtTokenProcessor
from api.application.protocols.password_hasher import PasswordHasher
from api.application.usecase.auth.auth_user import LoginUser
from api.application.usecase.auth.create_user import CreateUser
from api.domain.user.repository import UserRepository
from api.infrastructure.dependencies.adapters import (
create_engine,
create_session_maker,
new_session,
new_unit_of_work,
)
from api.infrastructure.dependencies.adapters import (create_engine,
create_session_maker,
new_session,
new_unit_of_work)
from api.infrastructure.dependencies.configs import app_settings
from api.infrastructure.dependencies.protocols import (
get_date_time_provider,
get_password_hasher,
)
from api.infrastructure.dependencies.protocols import (get_date_time_provider,
get_jwt_token_processor,
get_password_hasher,
get_user_login)
from api.infrastructure.dependencies.repositories import get_user_repository
from api.infrastructure.dependencies.usecases import provide_create_user
from api.infrastructure.settings import Settings
@ -34,6 +35,9 @@ def init_dependencies(app: FastAPI) -> None:
app.dependency_overrides[DateTimeProvider] = get_date_time_provider
app.dependency_overrides[PasswordHasher] = get_password_hasher
app.dependency_overrides[JwtTokenProcessor] = get_jwt_token_processor
app.dependency_overrides[LoginUser] = get_user_login
app.dependency_overrides[UserRepository] = get_user_repository
app.dependency_overrides[CreateUser] = provide_create_user

View File

@ -15,12 +15,16 @@ class LoginUser:
self.hasher = password_hasher
async def __call__(self, request: LoginRequest) -> AuthenticationResponse:
print("__call__ request", request)
user = await self.user_repository.get_user(filter={"email": request.email})
print("__call__ user from repo", user)
error = UserInvalidCredentialsError("Email or password is incorrect")
if user is None:
print("user is none in LoginUser __call__")
raise error
if not self.hasher.verify_password(request.password, user.hashed_password):
print("wrong pass in LoginUser __call__")
raise error
return AuthenticationResponse(

View File

@ -1,7 +1,17 @@
from typing import Annotated
from fastapi import Depends
from api.application.protocols.date_time import DateTimeProvider
from api.application.protocols.jwt import JwtTokenProcessor
from api.application.protocols.password_hasher import PasswordHasher
from api.application.usecase.auth.auth_user import LoginUser
from api.domain.user.repository import UserRepository
from api.infrastructure.auth.jwt_processor import JoseJwtTokenProcessor
from api.infrastructure.date_time import SystemDateTimeProvider, Timezone
from api.infrastructure.dependencies.stub import Stub
from api.infrastructure.security.password_hasher import Pbkdf2PasswordHasher
from api.infrastructure.settings import Settings
def get_password_hasher() -> PasswordHasher:
@ -10,3 +20,19 @@ def get_password_hasher() -> PasswordHasher:
def get_date_time_provider() -> DateTimeProvider:
return SystemDateTimeProvider(Timezone.UTC)
def get_jwt_token_processor(
settings: Annotated[Settings, Depends(Stub(Settings))],
date_time_provider: Annotated[DateTimeProvider, Depends(Stub(DateTimeProvider))],
) -> JwtTokenProcessor:
return JoseJwtTokenProcessor(
jwt_options=settings.jwt, date_time_provider=date_time_provider
)
def get_user_login(
user_repository: Annotated[UserRepository, Depends(Stub(UserRepository))],
password_hasher: Annotated[PasswordHasher, Depends(Stub(PasswordHasher))],
) -> LoginUser:
return LoginUser(user_repository=user_repository, password_hasher=password_hasher)

View File

@ -2,6 +2,7 @@ from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from api.domain.user import User, UserRepository
from api.domain.user.model import UserEmail, UserFirstName, UserId
class SqlAlchemyUserRepository(UserRepository):
@ -25,7 +26,17 @@ class SqlAlchemyUserRepository(UserRepository):
)
async def get_user(self, filter: dict) -> User | None:
pass
stmt = text("""SELECT * FROM users WHERE email = :val""")
result = await self.session.execute(stmt, {"val": filter["email"]})
if not result:
return None
result = result.mappings().one()
return User(
id=UserId(result.id),
name=UserFirstName(result.name),
email=UserEmail(result.email),
hashed_password=result.hashed_password,
)
async def get_users(self) -> list[User]:
return []

40
poetry.lock generated
View File

@ -618,19 +618,6 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "jose"
version = "1.0.0"
description = "An implementation of the JOSE draft"
optional = false
python-versions = "*"
files = [
{file = "jose-1.0.0.tar.gz", hash = "sha256:8436c3617cd94e1ba97828fbb1ce27c129f66c78fb855b4bb47e122b5f345fba"},
]
[package.dependencies]
pycrypto = ">=2.6"
[[package]]
name = "magic-filter"
version = "1.0.12"
@ -991,16 +978,6 @@ files = [
{file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"},
]
[[package]]
name = "pycrypto"
version = "2.6.1"
description = "Cryptographic modules for Python."
optional = false
python-versions = "*"
files = [
{file = "pycrypto-2.6.1.tar.gz", hash = "sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c"},
]
[[package]]
name = "pydantic"
version = "2.5.3"
@ -1180,6 +1157,20 @@ cryptography = ["cryptography (>=3.4.0)"]
pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"]
pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"]
[[package]]
name = "python-multipart"
version = "0.0.9"
description = "A streaming multipart parser for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
{file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
]
[package.extras]
dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"]
[[package]]
name = "pyyaml"
version = "6.0.1"
@ -1205,6 +1196,7 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
@ -1573,4 +1565,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "cb90b25778130dc1445290f65ee84f37029b7db4838a16b510a9f2efaf5ae841"
content-hash = "586dbb5fd80f9999d39a1cb960a06bc8f15e3b103f1c273e4d954fca0b1ffc75"

View File

@ -7,8 +7,8 @@ readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10"
jose = "^1.0.0"
python-jose = "^3.3.0"
python-multipart = "^0.0.9"