Files
vidconf/backend/services/profile.py

71 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Профиль пользователя: сборка ответа, правка данных, аватар.
Переиспользуется `api/users.py` (свой профиль) и `api/admin.py` (карточка
профиля любого пользователя администратором) — правила одни и те же (задача
4c: «те же данные, редактирование по тем же правилам»).
"""
import uuid
from pathlib import Path
from fastapi import UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from models.team import Team
from models.user import User
from repositories.admin import TeamRepository
from services.avatars import delete_avatar, read_and_validate_avatar, save_avatar
class TeamNotFoundError(Exception):
"""Команда с указанным `team_id` не найдена."""
async def resolve_team_name(session: AsyncSession, team_id: uuid.UUID | None) -> str | None:
"""Имя команды пользователя (`None`, если команда не привязана или была удалена)."""
if team_id is None:
return None
team = await session.get(Team, team_id)
return team.name if team is not None else None
async def update_profile_fields(
session: AsyncSession,
user: User,
*,
name_user: str | None,
team_id: uuid.UUID | None,
team_id_is_set: bool,
) -> User:
"""Изменить ФИО и/или команду пользователя.
`team_id_is_set` — поле присутствовало в теле запроса (в т.ч. явный
`null`, различаем через `model_fields_set` на стороне роутера) — тот же
приём, что и `summary_recipients`/`team_id` в других PATCH-эндпоинтах
(`services/conferences.py`, `api/admin.py`). Email НЕ принимается —
read-only поле профиля.
"""
if name_user is not None:
user.name_user = name_user
if team_id_is_set:
if team_id is not None and await TeamRepository(session).get(team_id) is None:
raise TeamNotFoundError
user.team_id = team_id
return user
async def set_avatar(media_root: Path, user: User, file: UploadFile) -> User:
"""Загрузить, провалидировать и сохранить новый аватар пользователя.
Бросает `AvatarTooLargeError`/`AvatarInvalidTypeError` (см. `services/avatars.py`).
"""
content, ext = await read_and_validate_avatar(file)
user.avatar_path = save_avatar(media_root, user.id, content, ext, old_path=user.avatar_path)
return user
def clear_avatar(media_root: Path, user: User) -> None:
"""Удалить файл аватара пользователя с диска и очистить `avatar_path`."""
delete_avatar(media_root, user.avatar_path)
user.avatar_path = None