Files
vidconf/backend/services/conference_access.py

79 lines
3.6 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.
"""Проверка права входа в конференцию (статус/пароль) и генерация ответа join.
Заменяет `services/room_access.py`: комнаты больше не конкурируют за
время («правило часа» удалено вместе с бронированием, ADR-001, п.5), но
пароль закрытой конференции по-прежнему проверяется здесь же — для обычного
пользователя и гостя одинаково.
"""
import json
from core.config import get_settings
from core.security import verify_password
from models.conference import Conference
from schemas.conferences import JoinOut
from services.livekit_tokens import create_room_access_token
class ConferenceEndedError(Exception):
"""Конференция завершена (терминальный статус) — повторный вход невозможен."""
class PasswordRequiredError(Exception):
"""Конференция закрыта паролем; пароль не передан."""
class InvalidPasswordError(Exception):
"""Указанный пароль не совпадает с паролем закрытой конференции."""
def ensure_joinable(conference: Conference, *, password: str | None) -> None:
"""Проверить, что в конференцию можно войти прямо сейчас.
Бросает `ConferenceEndedError` для терминального статуса `ended`
(история и саммари остаются, но повторный вход невозможен — ADR-001,
п.2), либо `PasswordRequiredError`/`InvalidPasswordError` для закрытой
паролем конференции. Ничего не бросает для открытой конференции в
статусе `scheduled`/`active`.
"""
if conference.status == "ended":
raise ConferenceEndedError
if not conference.is_closed:
return
if conference.password_hash is None or password is None:
raise PasswordRequiredError
if not verify_password(password, conference.password_hash):
raise InvalidPasswordError
def build_join(
conference: Conference,
*,
identity: str,
name: str,
chat_enabled: bool,
avatar_url: str | None = None,
) -> JoinOut:
"""Построить ответ join: LiveKit access-токен для входа в комнату конференции.
Имя LiveKit-комнаты всегда равно `conference.slug` (ADR-001, п.4).
`chat_enabled` — снятый вызывающей стороной тоггл `instance_settings`:
читается здесь параметром, а не заново из БД, чтобы не плодить
отдельный запрос настроек на каждый join. `avatar_url` прокидывается
в метаданные токена как JSON
`{"avatar_url": ...}`; `None` (гость либо пользователь без аватара) —
метаданные не выставляются вовсе.
"""
settings = get_settings()
metadata = json.dumps({"avatar_url": avatar_url}) if avatar_url else None
token = create_room_access_token(
room_name=conference.slug, identity=identity, name=name, metadata=metadata
)
return JoinOut(
livekit_url=settings.livekit_public_url,
token=token,
room_name=conference.slug,
conference_id=conference.id,
chat_enabled=chat_enabled,
)