From aabea07293b923285b6027fd6a8da37961fb3a21 Mon Sep 17 00:00:00 2001 From: Noloquideus Date: Thu, 4 Jun 2026 18:09:06 +0300 Subject: [PATCH] feat: add import --- .../repositories/i_admin_user_repository.py | 2 +- src/application/commands/admin_login.py | 12 +++++++----- src/application/domain/dto/admin_auth.py | 2 +- src/application/domain/entities/admin_user.py | 2 +- src/infrastructure/database/models/admin_user.py | 2 +- .../database/repositories/admin_user_repository.py | 6 +++--- src/presentation/routing/auth.py | 6 +++--- src/presentation/schemas/admin_auth.py | 8 ++++---- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/application/abstractions/repositories/i_admin_user_repository.py b/src/application/abstractions/repositories/i_admin_user_repository.py index 8c914bc..2f42e49 100644 --- a/src/application/abstractions/repositories/i_admin_user_repository.py +++ b/src/application/abstractions/repositories/i_admin_user_repository.py @@ -5,7 +5,7 @@ from src.application.domain.entities.admin_user import AdminUserEntity class IAdminUserRepository(ABC): @abstractmethod - async def get_by_email(self, email: str) -> AdminUserEntity: + async def get_by_login(self, login: str) -> AdminUserEntity: raise NotImplementedError @abstractmethod diff --git a/src/application/commands/admin_login.py b/src/application/commands/admin_login.py index 17ff2dc..7ae4853 100644 --- a/src/application/commands/admin_login.py +++ b/src/application/commands/admin_login.py @@ -23,16 +23,18 @@ class AdminLoginCommand: self._logger = logger @transactional - async def __call__(self, *, email: str, password: str) -> AdminLoginDto: - email = (email or '').strip().lower() - admin = await self._unit_of_work.admin_user_repository.get_by_email(email) + async def __call__(self, *, login: str, password: str) -> AdminLoginDto: + login = (login or '').strip() + if not login: + raise ApplicationException(status_code=400, message='Login is required') + admin = await self._unit_of_work.admin_user_repository.get_by_login(login) if not admin.is_active: raise ApplicationException(status_code=403, message='Admin account is inactive') ok = await self._hash_service.verify(plain_value=password, hashed_value=admin.password_hash) if not ok: - self._logger.warning(f'Admin login failed for {email}') + self._logger.warning(f'Admin login failed for {login}') raise ApplicationException(status_code=401, message='Invalid credentials') now = datetime.now(timezone.utc) @@ -47,7 +49,7 @@ class AdminLoginCommand: return AdminLoginDto( id=admin.id, - email=admin.email, + login=admin.login, first_name=admin.first_name, last_name=admin.last_name, role=admin.role, diff --git a/src/application/domain/dto/admin_auth.py b/src/application/domain/dto/admin_auth.py index cc2eed2..a2d6cf4 100644 --- a/src/application/domain/dto/admin_auth.py +++ b/src/application/domain/dto/admin_auth.py @@ -7,7 +7,7 @@ from datetime import datetime @dataclass class AdminLoginDto: id: str - email: str + login: str first_name: str | None last_name: str | None role: str diff --git a/src/application/domain/entities/admin_user.py b/src/application/domain/entities/admin_user.py index 2900b6a..de8d747 100644 --- a/src/application/domain/entities/admin_user.py +++ b/src/application/domain/entities/admin_user.py @@ -7,7 +7,7 @@ from datetime import datetime @dataclass class AdminUserEntity: id: str - email: str + login: str password_hash: str first_name: str | None last_name: str | None diff --git a/src/infrastructure/database/models/admin_user.py b/src/infrastructure/database/models/admin_user.py index c201166..8b4c8df 100644 --- a/src/infrastructure/database/models/admin_user.py +++ b/src/infrastructure/database/models/admin_user.py @@ -12,7 +12,7 @@ from src.infrastructure.database.models.mixins import AuditTimestampsMixin, Ulid class AdminUserModel(Base, UlidPrimaryKeyMixin, AuditTimestampsMixin): __tablename__ = 'admin_users' - email: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True) + login: Mapped[str] = mapped_column(String(255), nullable=False, unique=True, index=True) password_hash: Mapped[str] = mapped_column(String(255), nullable=False) first_name: Mapped[str | None] = mapped_column(String(128), nullable=True) last_name: Mapped[str | None] = mapped_column(String(128), nullable=True) diff --git a/src/infrastructure/database/repositories/admin_user_repository.py b/src/infrastructure/database/repositories/admin_user_repository.py index 406d908..b240574 100644 --- a/src/infrastructure/database/repositories/admin_user_repository.py +++ b/src/infrastructure/database/repositories/admin_user_repository.py @@ -22,7 +22,7 @@ class AdminUserRepository(IAdminUserRepository): def _to_entity(self, m: AdminUserModel) -> AdminUserEntity: return AdminUserEntity( id=m.id, - email=m.email, + login=m.login, password_hash=m.password_hash, first_name=m.first_name, last_name=m.last_name, @@ -33,9 +33,9 @@ class AdminUserRepository(IAdminUserRepository): updated_at=m.updated_at, ) - async def get_by_email(self, email: str) -> AdminUserEntity: + async def get_by_login(self, login: str) -> AdminUserEntity: try: - stmt = select(AdminUserModel).where(func.lower(AdminUserModel.email) == email.lower()) + stmt = select(AdminUserModel).where(func.lower(AdminUserModel.login) == login.lower()) result = await self._session.execute(stmt) user = result.scalar_one_or_none() if user is None: diff --git a/src/presentation/routing/auth.py b/src/presentation/routing/auth.py index 49ac9f6..9187da2 100644 --- a/src/presentation/routing/auth.py +++ b/src/presentation/routing/auth.py @@ -15,11 +15,11 @@ async def admin_login( body: AdminLoginRequest, command: AdminLoginCommand = Depends(get_admin_login_command), ): - dto = await command(email=str(body.email), password=body.password) + dto = await command(login=body.login, password=body.password) return AdminLoginResponse( access_token=dto.access_token, id=dto.id, - email=dto.email, + login=dto.login, first_name=dto.first_name, last_name=dto.last_name, role=dto.role, @@ -40,7 +40,7 @@ async def admin_me( admin = await command(auth.admin_user_id) return AdminMeResponse( id=admin.id, - email=admin.email, + login=admin.login, first_name=admin.first_name, last_name=admin.last_name, role=admin.role, diff --git a/src/presentation/schemas/admin_auth.py b/src/presentation/schemas/admin_auth.py index 7f9d624..2a9cb29 100644 --- a/src/presentation/schemas/admin_auth.py +++ b/src/presentation/schemas/admin_auth.py @@ -1,8 +1,8 @@ -from pydantic import BaseModel, EmailStr, Field +from pydantic import BaseModel, Field class AdminLoginRequest(BaseModel): - email: EmailStr + login: str = Field(min_length=3, max_length=255) password: str = Field(min_length=8) @@ -10,7 +10,7 @@ class AdminLoginResponse(BaseModel): access_token: str token_type: str = 'Bearer' id: str - email: str + login: str first_name: str | None last_name: str | None role: str @@ -18,7 +18,7 @@ class AdminLoginResponse(BaseModel): class AdminMeResponse(BaseModel): id: str - email: str + login: str first_name: str | None last_name: str | None role: str