81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import uuid
|
|
|
|
from sqlalchemy import Select, select
|
|
from sqlalchemy.exc import IntegrityError
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from cpv3.modules.users.models import User
|
|
from cpv3.modules.users.schemas import UserCreate, UserRegister, UserUpdate
|
|
from cpv3.infrastructure.security import hash_password
|
|
|
|
|
|
class UserRepository:
|
|
"""Repository for User database operations."""
|
|
|
|
def __init__(self, session: AsyncSession) -> None:
|
|
self._session = session
|
|
|
|
async def get_by_id(self, user_id: uuid.UUID) -> User | None:
|
|
result = await self._session.execute(select(User).where(User.id == user_id))
|
|
return result.scalar_one_or_none()
|
|
|
|
async def get_by_username(self, username: str) -> User | None:
|
|
result = await self._session.execute(
|
|
select(User).where(User.username == username)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def list_all(self, *, requester: User) -> list[User]:
|
|
stmt: Select[tuple[User]] = select(User)
|
|
if not requester.is_staff:
|
|
stmt = stmt.where(User.id == requester.id)
|
|
|
|
result = await self._session.execute(stmt.order_by(User.created_at.desc()))
|
|
return list(result.scalars().all())
|
|
|
|
async def create(self, *, data: UserCreate | UserRegister) -> User:
|
|
user = User(
|
|
username=data.username,
|
|
email=data.email,
|
|
password_hash=hash_password(data.password),
|
|
first_name=data.first_name,
|
|
last_name=data.last_name,
|
|
phone_number=data.phone_number,
|
|
avatar=data.avatar,
|
|
)
|
|
|
|
self._session.add(user)
|
|
try:
|
|
await self._session.commit()
|
|
except IntegrityError as e:
|
|
await self._session.rollback()
|
|
raise ValueError("Пользователь уже существует или нарушены ограничения") from e
|
|
|
|
await self._session.refresh(user)
|
|
return user
|
|
|
|
async def update(self, user: User, data: UserUpdate) -> User:
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
for key, value in update_data.items():
|
|
if value is not None:
|
|
setattr(user, key, value)
|
|
|
|
try:
|
|
await self._session.commit()
|
|
except IntegrityError as e:
|
|
await self._session.rollback()
|
|
raise ValueError("Обновление нарушает ограничения") from e
|
|
|
|
await self._session.refresh(user)
|
|
return user
|
|
|
|
async def update_password(self, user: User, new_hash: str) -> None:
|
|
user.password_hash = new_hash
|
|
await self._session.commit()
|
|
|
|
async def deactivate(self, user: User) -> None:
|
|
user.is_active = False
|
|
await self._session.commit()
|