feat(auth): проверка устройств на входе — запрос доступа и превью камеры
Отключаемый модуль (instance_settings.device_check, дефолт выключен): запрос доступа к камере/микрофону на LoginPage и в карточке "Как вас зовут?" (JoinPage), живое зеркальное превью и кнопки вкл/выкл камеры и микрофона там же. На JoinPage кнопки определяют, с чем гость войдёт в конференцию (RoomPage.LiveKitRoom audio/video вместо жёстких false) — на LoginPage только пре-авторизуют разрешение, без UI (карточка ведёт в лобби, применить выбор некуда). Вход в комнату по умолчанию, как и раньше, с выключенными микрофоном/камерой. Публичный GET /api/v1/public/settings отдаёт флаг модуля обеим страницам до аутентификации.
This commit is contained in:
@@ -55,6 +55,7 @@ _KEY_REGISTRATION_EMAIL_DOMAIN = "registration_email_domain"
|
||||
_KEY_CONTACT_EMAIL = "contact_email"
|
||||
_KEY_MEDIA_LIMITS = "media_limits"
|
||||
_KEY_CONSENT_POLICY = "consent_policy"
|
||||
_KEY_DEVICE_CHECK = "device_check"
|
||||
|
||||
BOOTSTRAP_MANAGED_KEYS: tuple[str, ...] = (
|
||||
_KEY_CHAT,
|
||||
@@ -79,6 +80,7 @@ _DEFAULT_REGISTRATION_EMAIL_DOMAIN_VALUE: dict[str, Any] = {"enabled": False, "d
|
||||
`update()` значение переписывается в новую форму (см. `update`)."""
|
||||
_DEFAULT_CONTACT_EMAIL_VALUE: dict[str, Any] = {"enabled": False, "email": None}
|
||||
_DEFAULT_MEDIA_LIMITS_VALUE: dict[str, Any] = {"publish_quality_cap": "off", "stage_max_tiles": 25}
|
||||
_DEFAULT_DEVICE_CHECK_VALUE = {"enabled": False}
|
||||
|
||||
DEFAULT_CONSENT_POLICY_TEXT = """Это типовой шаблон для предварительной демонстрации. Текст не проходил проверку юриста и не может использоваться как окончательная редакция без такой проверки. Администратор обязан заменить плейсхолдеры в квадратных скобках и, при необходимости, весь текст — под свою организацию и юрисдикцию.
|
||||
|
||||
@@ -151,6 +153,7 @@ class SettingsUpdateIn(BaseModel):
|
||||
stage_max_tiles: StageMaxTiles | None = None
|
||||
consent_required: bool | None = None
|
||||
consent_policy_text: str | None = None
|
||||
device_check_enabled: bool | None = None
|
||||
|
||||
|
||||
class BootstrapOverrides(BaseModel):
|
||||
@@ -203,6 +206,7 @@ def build_bootstrap_defaults(
|
||||
_KEY_CONTACT_EMAIL: dict(_DEFAULT_CONTACT_EMAIL_VALUE),
|
||||
_KEY_MEDIA_LIMITS: dict(_DEFAULT_MEDIA_LIMITS_VALUE),
|
||||
_KEY_CONSENT_POLICY: dict(_DEFAULT_CONSENT_POLICY_VALUE),
|
||||
_KEY_DEVICE_CHECK: dict(_DEFAULT_DEVICE_CHECK_VALUE),
|
||||
}
|
||||
if overrides is None:
|
||||
return defaults
|
||||
@@ -337,6 +341,10 @@ class InstanceSettingsService:
|
||||
cfg.hand_queue = HandQueueConfig(enabled=patch.hand_queue_enabled)
|
||||
await self._set(_KEY_HAND_QUEUE, cfg.hand_queue.model_dump(mode="json"))
|
||||
|
||||
if patch.device_check_enabled is not None:
|
||||
cfg.device_check_enabled = patch.device_check_enabled
|
||||
await self._set(_KEY_DEVICE_CHECK, {"enabled": patch.device_check_enabled})
|
||||
|
||||
if patch.registration_team_choice is not None:
|
||||
cfg.registration_team_choice = patch.registration_team_choice
|
||||
await self._set(
|
||||
@@ -605,4 +613,7 @@ def _build_config(rows: dict[str, Any]) -> InstanceConfig:
|
||||
consent_policy_version=rows.get(_KEY_CONSENT_POLICY, _DEFAULT_CONSENT_POLICY_VALUE).get(
|
||||
"version", 1
|
||||
),
|
||||
device_check_enabled=rows.get(_KEY_DEVICE_CHECK, _DEFAULT_DEVICE_CHECK_VALUE).get(
|
||||
"enabled", False
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user