feat(storage): serve media through backend and add local FS backend
- introduce storage.Backend with S3 and local file-system implementations - deliver all blobs via signed GET/HEAD /api/objects/<key> (Range, Content-Type) - stream S3 objects through the backend; remove presigned URL path - share shared HMAC Signer between backends - remove S3_PUBLIC_URL; rename S3_PRESIGN_TTL to OBJECT_URL_TTL - make storage label in health dynamic; nginx proxy_buffering off for objects
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Spec Delta
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Получение фото по требованию
|
||||
Клиент SHALL иметь возможность получить актуальные данные фото с подписанным URL,
|
||||
обслуживаемым бэкендом, независимо от бэкенда хранения.
|
||||
|
||||
#### Scenario: Выдача свежего URL
|
||||
- **WHEN** клиент запрашивает фото по id
|
||||
- **THEN** система возвращает свежий подписанный URL бэкенда (срок до 1 часа) для просмотра
|
||||
|
||||
### Requirement: Скачивание одиночного фото
|
||||
Любой участник, включая viewer, SHALL иметь возможность скачать одиночное фото.
|
||||
|
||||
#### Scenario: Скачивание фото
|
||||
- **WHEN** участник запрашивает скачивание фото
|
||||
- **THEN** система возвращает подписанный URL оригинала, обслуживаемый бэкендом
|
||||
|
||||
### Requirement: Перенос и копирование фото между альбомами
|
||||
Пользователь с правом удаления в исходном альбоме и правом загрузки в целевом SHALL иметь
|
||||
возможность перенести или скопировать фото в другой альбом. Операции SHALL изменять только
|
||||
метаданные и SHALL не изменять объекты хранилища.
|
||||
|
||||
#### Scenario: Перенос
|
||||
- **WHEN** пользователь переносит фото в другой альбом
|
||||
- **THEN** фото исчезает из исходного альбома и появляется в целевом, объекты хранилища не меняются
|
||||
|
||||
#### Scenario: Копирование
|
||||
- **WHEN** пользователь копирует фото в другой альбом
|
||||
- **THEN** в целевом альбоме появляется новая запись, ссылающаяся на те же объекты хранилища
|
||||
@@ -0,0 +1,14 @@
|
||||
# Spec Delta
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Просмотр альбома по ссылке
|
||||
Пользователь без авторизации SHALL иметь возможность просматривать альбом по действующему токену (сетка, лайтбокс, скачивание одиночного фото).
|
||||
|
||||
#### Scenario: Просмотр по действующей ссылке
|
||||
- **WHEN** аноним открывает ссылку с действующим токеном
|
||||
- **THEN** система возвращает фото альбома со свежими подписанными URL, обслуживаемыми бэкендом
|
||||
|
||||
#### Scenario: Истёкшая или отозванная ссылка
|
||||
- **WHEN** аноним открывает ссылку с истёкшим или отозванным токеном
|
||||
- **THEN** система отклоняет доступ
|
||||
@@ -0,0 +1,108 @@
|
||||
# Spec Delta
|
||||
|
||||
## Purpose
|
||||
|
||||
Выбор и работа объектного хранилища: S3-совместимое (Garage) или локальная файловая
|
||||
система. Блобы всегда отдаются через бэкенд по подписанному URL, хранилище клиенту не
|
||||
раскрывается.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Выбор бэкенда хранилища
|
||||
Система SHALL поддерживать выбор бэкенда объектного хранилища параметром конфигурации,
|
||||
при этом S3-совместимый бэкенд SHALL оставаться значением по умолчанию.
|
||||
|
||||
#### Scenario: Выбор S3-совместимого бэкенда
|
||||
- **WHEN** в конфигурации задан S3-совместимый бэкенд
|
||||
- **THEN** система хранит и отдаёт блобы через S3-совместимое хранилище
|
||||
|
||||
#### Scenario: Выбор локальной ФС
|
||||
- **WHEN** в конфигурации задан бэкенд локальной ФС
|
||||
- **THEN** система хранит и отдаёт блобы из каталога локальной файловой системы
|
||||
|
||||
#### Scenario: Неполная конфигурация
|
||||
- **WHEN** конфигурация выбранного бэкенда неполна
|
||||
- **THEN** система отказывается стартовать с явной ошибкой конфигурации
|
||||
|
||||
### Requirement: Единая абстракция хранилища
|
||||
Операции записи, чтения, удаления и проверки доступности SHALL выполняться через единый
|
||||
интерфейс хранилища, одинаковый для всех бэкендов; ключи объектов SHALL оставаться
|
||||
непрозрачными и независимыми от бэкенда.
|
||||
|
||||
#### Scenario: Ключи переносимы между бэкендами
|
||||
- **WHEN** один и тот же ключ объекта используется на разных бэкендах
|
||||
- **THEN** он адресует тот же логический блоб без изменения формата
|
||||
|
||||
#### Scenario: Удаление объекта
|
||||
- **WHEN** система удаляет объект через интерфейс хранилища
|
||||
- **THEN** блоб удаляется выбранным бэкендом
|
||||
|
||||
### Requirement: Отдача блобов через бэкенд
|
||||
Клиент SHALL получать любой блоб по URL, обслуживаемому бэкендом, с ограниченным сроком
|
||||
действия; ни один бэкенд SHALL не отдавать клиенту ссылку напрямую на объектное
|
||||
хранилище. Для анонимного доступа по share-ссылке подписанный URL SHALL быть действителен
|
||||
без пользовательской сессии.
|
||||
|
||||
#### Scenario: Свежий URL просмотра
|
||||
- **WHEN** клиент запрашивает фото
|
||||
- **THEN** система возвращает подписанный URL бэкенда со сроком действия до 1 часа
|
||||
|
||||
#### Scenario: Доступ по share-ссылке
|
||||
- **WHEN** аноним открывает альбом по действующей share-ссылке
|
||||
- **THEN** полученные подписанные URL позволяют загрузить фото без сессии
|
||||
|
||||
#### Scenario: Истёкшая подпись
|
||||
- **WHEN** клиент обращается к URL с истёкшей или неверной подписью
|
||||
- **THEN** система отказывает в доступе
|
||||
|
||||
### Requirement: Хранилище не раскрывается клиенту
|
||||
Адрес и учётные данные объектного хранилища SHALL оставаться внутренними; клиент SHALL
|
||||
взаимодействовать с медиа только через бэкенд, независимо от бэкенда хранения.
|
||||
|
||||
#### Scenario: S3-совместимый бэкенд
|
||||
- **WHEN** хранилищем выбран S3-совместимый бэкенд
|
||||
- **THEN** выдаваемый клиенту URL указывает на бэкенд, а не на S3-эндпоинт
|
||||
|
||||
#### Scenario: Локальная ФС
|
||||
- **WHEN** хранилищем выбрана локальная ФС
|
||||
- **THEN** выдаваемый клиенту URL указывает на бэкенд
|
||||
|
||||
#### Scenario: Хранилище недоступно извне
|
||||
- **WHEN** объектное хранилище недоступно из внешней сети
|
||||
- **THEN** просмотр и скачивание медиа продолжают работать
|
||||
|
||||
### Requirement: Локальное хранение на ФС
|
||||
Бэкенд локальной ФС SHALL хранить блобы в пределах заданного корневого каталога по
|
||||
непрозрачным ключам объектов и SHALL отвергать ключи, выводящие за пределы корня.
|
||||
|
||||
#### Scenario: Запись и чтение блоба
|
||||
- **WHEN** система сохраняет объект с ключом
|
||||
- **THEN** блоб размещается под корневым каталогом и позже читается по тому же ключу
|
||||
|
||||
#### Scenario: Попытка выхода из корня
|
||||
- **WHEN** ключ содержит элементы обхода каталога
|
||||
- **THEN** система отвергает операцию и не обращается за пределы корня
|
||||
|
||||
### Requirement: Диапазонные запросы и тип содержимого
|
||||
При отдаче блоба система SHALL возвращать корректный тип содержимого и SHALL
|
||||
поддерживать диапазонные запросы для докачки и больших файлов.
|
||||
|
||||
#### Scenario: Запрос диапазона
|
||||
- **WHEN** клиент запрашивает часть блоба через диапазон
|
||||
- **THEN** система возвращает запрошенный диапазон и соответствующий статус
|
||||
|
||||
#### Scenario: Тип содержимого
|
||||
- **WHEN** клиент загружает блоб
|
||||
- **THEN** ответ содержит тип содержимого, соответствующий объекту
|
||||
|
||||
### Requirement: Доступность выбранного хранилища
|
||||
Система SHALL сообщать о доступности выбранного бэкенда хранилища и отражать его в
|
||||
состоянии здоровья сервиса.
|
||||
|
||||
#### Scenario: Хранилище доступно
|
||||
- **WHEN** выбранный бэкенд отвечает на проверку
|
||||
- **THEN** состоянии здоровья отражает хранилище как доступное
|
||||
|
||||
#### Scenario: Хранилище недоступно
|
||||
- **WHEN** выбранный бэкенд не отвечает на проверку
|
||||
- **THEN** состояние здоровья отражает деградацию
|
||||
Reference in New Issue
Block a user