feat(auth): согласие на обработку персональных данных при регистрации
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled

Отключаемый модуль (instance_settings.consent_policy): галочка + ссылка на
публичную страницу регламента на форме регистрации, редактируемый в админке
текст с типовым шаблоном по умолчанию (плейсхолдеры под организацию, не
проходил юридическую проверку), версия текста растёт при каждой правке.
Факт согласия хранится в users (consent_version, consent_given_at) — второй
эшелон проверки на сервере, как и для отключаемых модулей ранее. Дефолт
(выключено) сохраняет поведение существующих инсталляций, у уже
зарегистрированных пользователей согласие не запрашивается.
This commit is contained in:
2026-08-04 22:20:00 +03:00
parent 0e029a2bf8
commit 4f82ebe17a
19 changed files with 615 additions and 9 deletions

View File

@@ -62,6 +62,7 @@ from services.email import EmailSendError, create_email_backend
from services.instance_settings import (
InstanceSettingsService,
InvalidAiLevelError,
InvalidConsentPolicyError,
InvalidContactEmailError,
InvalidEmailDomainError,
InvalidTimezoneError,
@@ -404,6 +405,7 @@ async def update_settings(
InvalidTimezoneError,
InvalidEmailDomainError,
InvalidContactEmailError,
InvalidConsentPolicyError,
) as exc:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
queue_served = await anyio.to_thread.run_sync(transcription_queue_served)
@@ -470,6 +472,9 @@ def _to_settings_out(cfg: InstanceConfig, *, transcription_queue_served: bool) -
contact_email=cfg.contact_email,
publish_quality_cap=cfg.media_limits.publish_quality_cap,
stage_max_tiles=cfg.media_limits.stage_max_tiles,
consent_required=cfg.consent_required,
consent_policy_text=cfg.consent_policy_text,
consent_policy_version=cfg.consent_policy_version,
)

View File

@@ -21,6 +21,7 @@ from schemas.auth import (
)
from services.auth import (
AuthService,
ConsentRequiredError,
EmailAlreadyRegisteredError,
EmailNotVerifiedError,
InvalidCredentialsError,
@@ -63,7 +64,12 @@ async def registration_options(
teams = [RegistrationTeamOptionOut(id=team.id, name=team.name) for team in items]
email_domains = cfg.registration_email_domains if cfg.registration_email_domain_enabled else []
return RegistrationOptionsOut(
team_choice_enabled=cfg.registration_team_choice, teams=teams, email_domains=email_domains
team_choice_enabled=cfg.registration_team_choice,
teams=teams,
email_domains=email_domains,
consent_required=cfg.consent_required,
consent_text=cfg.consent_policy_text,
consent_version=cfg.consent_policy_version,
)
@@ -78,6 +84,7 @@ async def register(
name_user=data.name_user,
password=data.password,
team_id=data.team_id,
consent_accepted=data.consent_accepted,
)
except EmailAlreadyRegisteredError as exc:
raise HTTPException(
@@ -91,6 +98,10 @@ async def register(
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail="invalid_email_domain"
) from exc
except ConsentRequiredError as exc:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail="consent_required"
) from exc
@router.post("/verify-email", status_code=status.HTTP_204_NO_CONTENT)