Files
vidconf/backend/alembic/versions/a37c1b9e0f42_user_virtual_background_images.py
Max Ronzhin fec9255baa feat(backend): модуль «замена фона» и хранилище своих картинок
Отключаемый в админке модуль `virtual_background` (дефолт — выключен, чтобы
обновление не меняло продукт у тех, кто ничего не просил). Флаг едет клиенту
двумя путями: на публичные страницы входа — через `GET /public/settings`,
участнику комнаты — в join-ответе (`JoinOut`), потому что значение нужно на
руках ДО первого рендера комнаты, а `/admin/settings` доступен только админу.

Свои картинки пользователя (`/users/me/backgrounds`, GET/POST/DELETE):
файлы на диске (`backgrounds/{user_id}/{id}.{ext}`), в БД только путь — как у
аватаров, «чтобы не грузили БД». Лимит в 10 штук проверяется на сервере под
блокировкой строки пользователя: две одновременные загрузки иначе обе увидели
бы «уже девять» и обе прошли бы. Удаление сносит и запись, и файл; чужую
картинку по её id удалить нельзя — владелец в условии запроса.

Валидация загрузки (допустимые форматы, магические байты, реальный размер)
выделена из `services/avatars.py` в общий `services/images.py`: правила у
аватара и фона одни и те же, а разъехавшись, они дали бы дыру ровно там, ради
чего проверка и написана. Публичный API аватаров не изменился.

Сжимает картинку клиент (Pillow на бэкенде нет), но серверная валидация
остаётся полноценной — запрос может прийти и мимо интерфейса.

Новый ключ настройки вписан в `_MANAGED_KEYS` тестов: без этого включённый
в общей dev-БД модуль ронял чужие тесты, которые считают себя изолированными.
2026-08-10 08:59:16 +03:00

62 lines
2.4 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.
"""user virtual background images
Свои картинки пользователя для замены фона видео (сессия 35):
- таблица `user_backgrounds` — id, владелец (`ON DELETE CASCADE`), путь к файлу
относительно `MEDIA_ROOT`, время загрузки.
Сами файлы лежат на диске в томе `media` (`backgrounds/{user_id}/{id}.{ext}`),
в БД только путь — как у аватаров (`users.avatar_path`). Лимит «не более 10
картинок на пользователя» — политика продукта, проверяется в
`services/backgrounds.py`, а не ограничением БД.
Настройка отключаемого модуля (`instance_settings.virtual_background`)
миграции не требует: `instance_settings` — key-value JSONB, новая настройка
это новая строка (см. `services/instance_settings.py`).
Revision ID: a37c1b9e0f42
Revises: 4d08a44ad153
Create Date: 2026-08-09 23:30:00.000000
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = 'a37c1b9e0f42'
down_revision: Union[str, Sequence[str], None] = '4d08a44ad153'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
op.create_table(
'user_backgrounds',
sa.Column(
'id',
postgresql.UUID(as_uuid=True),
server_default=sa.text('gen_random_uuid()'),
nullable=False,
),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('path', sa.String(length=512), nullable=False),
sa.Column(
'created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False
),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
)
op.create_index(
'ix_user_backgrounds_user_created', 'user_backgrounds', ['user_id', 'created_at']
)
def downgrade() -> None:
"""Downgrade schema."""
op.drop_index('ix_user_backgrounds_user_created', table_name='user_backgrounds')
op.drop_table('user_backgrounds')