from typing import List, Optional from fastapi import HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.application.users_repository import UsersRepository from app.core.constants import UserRoles from app.domain.entities.users import UserRead, UserActivate, UserUpdate, PasswordChangeRequest from app.domain.models import User from app.infrastructure.register_service import RegisterService class UsersService: def __init__(self, db: AsyncSession): self.users_repository = UsersRepository(db) self.user_roles = UserRoles() async def get_all(self) -> List[UserRead]: users = await self.users_repository.get_all() response = [] for user in users: response.append(UserRead.model_validate(user)) return response async def get_by_id(self, user_id: int) -> UserRead: user = await self.users_repository.get_by_id(user_id) if not user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пользователь не найден', ) return UserRead.model_validate(user) async def set_activate(self, activate_data: UserActivate, current_user: User) -> UserRead: user = await self.users_repository.get_by_id(activate_data.user_id) if not user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пользователь не найден', ) if user.id == current_user.id: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Нельзя заблокировать самого себя' ) if user.role.title == UserRoles.MODERATOR and user.is_admin: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Нельзя заблокировать даминистратора' ) user.is_activated = activate_data.is_activated user = await self.users_repository.update(user) return UserRead.model_validate(user) async def update(self, user_id: int, user: UserUpdate, current_user: User): user_model = await self.users_repository.get_by_id(user_id) if not user_model: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пользователь не найден', ) if current_user.id != user_model.id and not ( current_user.role.title == self.user_roles.MODERATOR and current_user.is_admin ): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail='Доступ запрещен', ) user_model.first_name = user.first_name user_model.last_name = user.last_name user_model.patronymic = user.patronymic user_model.email = str(user.email) user_model.birthdate = user.birthdate user_model = await self.users_repository.update(user_model) return UserRead.model_validate(user_model) async def change_password( self, user_id: int, password_data: PasswordChangeRequest, current_user: User ) -> Optional[UserRead]: user_model = await self.users_repository.get_by_id(user_id) if not user_model: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пользователь не найден', ) if current_user.id != user_model.id and not ( current_user.role.title == self.user_roles.MODERATOR and current_user.is_admin ): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail='Доступ запрещен', ) if password_data.password != password_data.repeat_password: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пароли не совпадают', ) if not RegisterService.is_strong_password(password_data.repeat_password): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пароль слишком слабый. Пароль должен содержать не менее 8 символов, включая хотя бы одну букву и одну цифру и один специальный символ.' ) user_model.set_password(password_data.password) user_model = await self.users_repository.update(user_model) return UserRead.model_validate(user_model)