v1.2
This commit is contained in:
288
EventHubBackSpec.md
Normal file
288
EventHubBackSpec.md
Normal file
@@ -0,0 +1,288 @@
|
||||
ТЕХНИЧЕСКОЕ ЗАДАНИЕ (ТЗ) НА ПЛАТФОРМУ EVENTHUB
|
||||
Версия: 1.2 (расширенная гибридная модель + ролевая модель администрирования)
|
||||
|
||||
1. ЦЕЛИ И НАЗНАЧЕНИЕ
|
||||
EventHub — платформа для управления событиями с поддержкой календарей, записи участников (включая специалистов), гибкого подтверждения, рейтингов, отзывов, модерации, встроенного баг-трекера и платной подписки. Целевая аудитория: владельцы календарей (бизнес), участники (клиенты), администраторы.
|
||||
|
||||
2. ФУНКЦИОНАЛЬНЫЕ ТРЕБОВАНИЯ
|
||||
|
||||
2.1. Календари
|
||||
- CRUD календаря (название, описание, теги, владелец)
|
||||
- Расшаривание по ссылке (публичная/приватная)
|
||||
- Приглашение пользователей с правами "запись" или "администрирование"
|
||||
- Типы календарей: personal (бесплатный, без записи), commercial (платный, запись клиентов, специалисты)
|
||||
- Гибкое подтверждение заявок: auto (автоматически), manual (вручную), timeout (авто через N секунд)
|
||||
- Теги календаря, рейтинг (средняя оценка, количество голосов)
|
||||
|
||||
2.2. События (расширенная версия с повторяющимися событиями)
|
||||
|
||||
2.2.1. Типы событий и модель хранения
|
||||
События делятся на два типа:
|
||||
- single — одиночное событие, имеет конкретные дату и время начала, длительность.
|
||||
- recurring — повторяющееся событие (серия), определяется мастер-записью и правилом повторения.
|
||||
|
||||
Для эффективного хранения и быстрого поиска применяется гибридная модель с отложенной материализацией вхождений:
|
||||
- Каждая повторяющаяся серия представлена одной мастер-записью в таблице events с полем event_type = recurring и полем recurrence_rule, содержащим правило повторения в формате, совместимом с iCalendar RRULE (или упрощённый JSON-представление: freq, interval, byday, until и т.д.).
|
||||
- Конкретные вхождения (экземпляры) серии материализуются в таблице events только при необходимости:
|
||||
* когда на данное вхождение записался хотя бы один участник;
|
||||
* когда администратор вручную редактирует это вхождение (перенос времени, отмена, смена специалиста);
|
||||
* (опционально) при наступлении даты вхождения для архивных целей.
|
||||
- Материализованное вхождение имеет:
|
||||
* event_type = single (или специальный флаг is_instance = true),
|
||||
* ссылку master_id на родительскую мастер-запись,
|
||||
* собственные start_time и duration, которые могут отличаться от вычисленных по правилу (например, при переносе конкретного дня).
|
||||
- Отменённые вхождения из серии (исключения) хранятся в отдельной таблице recurrence_exceptions с указанием master_id, original_start_time и action = cancel | reschedule.
|
||||
|
||||
2.2.2. Правила генерации вхождений при поиске
|
||||
При поиске событий на заданный интервал дат (например, /v1/events?from=...&to=...) система:
|
||||
1. Выбирает все одиночные события (event_type = single), попадающие в интервал.
|
||||
2. Выбирает все активные мастер-записи (event_type = recurring), у которых:
|
||||
- дата первого вхождения ≤ конец интервала,
|
||||
- правило повторения допускает вхождения внутри интервала (учёт until или ограничения по количеству повторений).
|
||||
3. Для каждой мастер-записи генерирует список вхождений в пределах запрошенного интервала (используя встроенную функцию разбора RRULE или собственный алгоритм).
|
||||
4. Из сгенерированного списка исключаются вхождения, присутствующие в таблице recurrence_exceptions с действием cancel.
|
||||
5. Если для какого-либо вхождения уже существует материализованная запись в таблице events (по совпадению master_id и start_time), то используются данные материализованного экземпляра (специалист, длительность, статус) вместо вычисленных по шаблону.
|
||||
6. Итоговый список сортируется по времени начала и возвращается с пагинацией.
|
||||
|
||||
Ограничение: глубина генерации вхождений для одного запроса ограничена 1000 элементов; для длительных серий применяется пагинация по датам.
|
||||
|
||||
2.2.3. Материализация при записи участника
|
||||
При попытке записаться на вхождение повторяющегося события (POST /v1/events/:event_id/join):
|
||||
- Если event_id ссылается на мастер-запись (event_type = recurring), то в теле запроса обязательно передаётся occurrence_start — конкретное время вхождения, на которое производится запись.
|
||||
- Система в одной транзакции Mnesia:
|
||||
* Проверяет, существует ли материализованное вхождение с master_id = EventId и start_time = OccurrenceStart.
|
||||
* Если нет — создаёт новую запись в таблице events (тип single, master_id = EventId), копируя общие атрибуты мастер-записи (название, описание, календарь, специалист).
|
||||
* Создаёт бронирование (booking), привязанное к идентификатору материализованного вхождения.
|
||||
- Дальнейшие действия по подтверждению заявки выполняются уже с материализованным экземпляром.
|
||||
|
||||
2.2.4. Изменение и удаление серий
|
||||
- При редактировании мастер-записи (изменение названия, описания, правила повторения) обновляется только сама мастер-запись. Уже существующие материализованные вхождения остаются неизменными (сохраняют старые значения атрибутов). Это поведение может быть изменено администратором через специальный флаг «применить ко всем будущим вхождениям».
|
||||
- При удалении мастер-записи все связанные материализованные вхождения также помечаются удалёнными (или удаляются каскадно), а бронирования на будущие вхождения аннулируются с уведомлением участников.
|
||||
|
||||
2.2.5. Структура записей (records.hrl)
|
||||
```erlang
|
||||
%% Событие (может быть мастером или экземпляром)
|
||||
-record(event, {
|
||||
id :: binary(),
|
||||
calendar_id :: binary(),
|
||||
title :: binary(),
|
||||
description :: binary(),
|
||||
event_type :: single | recurring,
|
||||
start_time :: calendar:datetime(),
|
||||
duration :: integer(), %% минуты
|
||||
recurrence_rule :: binary() | undefined,
|
||||
master_id :: binary() | undefined,
|
||||
is_instance :: boolean(), %% true для материализованных вхождений
|
||||
specialist_id :: binary() | undefined,
|
||||
location :: #location{} | undefined,
|
||||
tags :: [binary()],
|
||||
status :: active | cancelled | completed,
|
||||
created_at :: calendar:datetime(),
|
||||
updated_at :: calendar:datetime()
|
||||
}).
|
||||
|
||||
%% Исключение из повторений
|
||||
-record(recurrence_exception, {
|
||||
master_id :: binary(),
|
||||
original_start :: calendar:datetime(),
|
||||
action :: cancel | reschedule,
|
||||
new_start :: calendar:datetime() | undefined
|
||||
}).
|
||||
```
|
||||
|
||||
## 2.2.6. Требования к реализации
|
||||
- Разбор и генерация RRULE должны быть реализованы в отдельном модуле `logic_recurrence` без внешних зависимостей (чистый Erlang).
|
||||
- Все операции с материализацией и записью участников должны выполняться в транзакциях Mnesia для обеспечения консистентности.
|
||||
- Для ускорения поиска материализованных вхождений по мастеру и дате создаётся составной индекс в Mnesia: `{master_id, start_time}` (через `mnesia:add_table_index/2` или хранение в ets с ключом `{master_id, start_time}`).
|
||||
|
||||
## 2.3. Запись участников и подтверждение
|
||||
- Запись через календарь
|
||||
- Подтверждение согласно политике календаря
|
||||
- Уведомления участника и владельца
|
||||
- Привязка события к специалисту (отдельная запись в календаре специалиста)
|
||||
|
||||
## 2.4. Отзывы и рейтинги
|
||||
- Только участники событий могут оставлять отзывы
|
||||
- Оценка 1-5, текстовый комментарий
|
||||
- Отзывы на событие или на календарь
|
||||
- Модерация отзывов (администраторы могут скрывать)
|
||||
|
||||
## 2.5. Поиск и фильтрация
|
||||
- По тексту, по тегам, по гео-позиции (радиус), по дате/времени
|
||||
|
||||
## 2.6. Расширенные возможности
|
||||
- Экспорт в Google Calendar (через OAuth2)
|
||||
- Экспорт в Apple Calendar (ICS-файл)
|
||||
- Геокодирование (адрес -> координаты) через внешний API (заглушка / Nominatim)
|
||||
|
||||
## 2.7. Модерация и безопасность
|
||||
- Жалобы на календари, события, отзывы
|
||||
- Автоматическая модерация по ключевым словам и по порогу жалоб
|
||||
- Ручная заморозка / разморозка администратором
|
||||
- Бан-лист слов
|
||||
- Аудит действий администраторов (детальная информация: кто, что, когда, IP, причина)
|
||||
|
||||
## 2.8. Баг-трекер (автоматический)
|
||||
- При ошибке создаётся тикет, группировка по хэшу ошибки
|
||||
- Учёт количества повторений
|
||||
- Уведомление пользователя при создании и при закрытии тикета
|
||||
- Доступ только у администраторов
|
||||
|
||||
## 2.9. Платная подписка
|
||||
- Личное использование бесплатно (personal)
|
||||
- Коммерческое использование платно (commercial)
|
||||
- Пробный период 30 дней
|
||||
- Планы подписки: 1, 3, 6, 12 месяцев
|
||||
- Заглушка платежного шлюза (для тестирования)
|
||||
- Автоматическое истечение подписки
|
||||
|
||||
## 2.10. Административная панель
|
||||
- Отдельный HTTPS-сервер (порт 8445) и отдельный WSS (порт 8446)
|
||||
- Управление календарями, событиями, отзывами, жалобами, тикетами, бан-словами
|
||||
- Статистика, информация о нодах кластера
|
||||
- WebSocket-уведомления администраторам
|
||||
|
||||
### 2.10.1. Ролевая модель администраторов
|
||||
Вводится три встроенные роли администраторов с различным объёмом прав:
|
||||
|
||||
| Роль | Идентификатор | Права |
|
||||
|--------------|---------------|-------------------------------------------------------------------------------------------|
|
||||
| Суперадмин | `superadmin` | Полный доступ ко всем модулям, управление ролями других админов, просмотр аудита, системные метрики. |
|
||||
| Модератор | `moderator` | Модерация контента (события, жалобы, отзывы), блокировка/разблокировка пользователей, работа с баг-трекером. |
|
||||
| Поддержка | `support` | Read-only доступ к пользователям и событиям, обработка жалоб, создание и обновление багов. |
|
||||
|
||||
**Примечание:** На этапе MVP поддерживается только роль `admin` (эквивалент `superadmin`). Полноценная ролевая модель будет внедрена в ближайших итерациях.
|
||||
|
||||
### 2.10.2. Эндпоинты для управления ролями и аудитом
|
||||
- `GET /admin/me` (или `GET /api/auth/me`) — получение текущей роли и разрешений администратора.
|
||||
- `GET /admin/admins` — список всех администраторов с ролями (только для `superadmin`).
|
||||
- `PUT /admin/admins/:id` — изменение роли администратора (только для `superadmin`).
|
||||
- `POST /admin/admins` — приглашение нового администратора с назначением роли (только для `superadmin`).
|
||||
- `GET /admin/audit` — журнал действий администраторов с фильтрацией по дате, пользователю, действию (только для `superadmin`).
|
||||
|
||||
### 2.10.3. Статистика для дашборда с учётом ролей
|
||||
- `superadmin` — системные метрики: все пользователи, события, жалобы, баги за период, графики регистраций/событий по дням, активность администраторов.
|
||||
- `moderator` — собственные обработанные жалобы/события (количество, статусы, время реакции), общая статистика по модерации.
|
||||
- `support` — количество открытых багов и жалоб, назначенных на текущего сотрудника, персональные задачи.
|
||||
|
||||
Эндпоинт: `GET /admin/stats` (или `/api/stats` с авторизацией). Возвращает JSON, содержимое которого фильтруется в соответствии с ролью вызывающего.
|
||||
|
||||
## 2.11. Real-time уведомления (WebSocket)
|
||||
- Пользователи: подписка на календарь, получение обновлений
|
||||
- Администраторы: подписка на глобальные уведомления (жалобы, авто-заморозки)
|
||||
|
||||
## 3.1. Производительность и масштабирование
|
||||
- 100 000+ пользователей
|
||||
- Горизонтальное масштабирование (увеличение нод)
|
||||
- Mnesia с дисковыми копиями на нескольких нодах
|
||||
- Отдельные ноды для исторических данных (disc_only_copies)
|
||||
- Пагинация всех списков
|
||||
|
||||
## 3.2. Надёжность
|
||||
- Супервизорное дерево OTP
|
||||
- Let it crash – быстрый перезапуск процессов
|
||||
- Автоматическое восстановление после падения ноды (Mnesia)
|
||||
|
||||
## 3.3. Безопасность
|
||||
- JWT с ролью (user, admin; в будущем — superadmin, moderator, support)
|
||||
- HTTPS / WSS (самоподписанный сертификат для dev, реальный для prod)
|
||||
- Argon2 для хеширования паролей (erlang-argon2)
|
||||
- OAuth2 для Google (опционально)
|
||||
- Refresh token (запланирован)
|
||||
- При блокировке пользователя или отклонении сущности обязательно сохранять причину (поле `reason`)
|
||||
|
||||
## 3.4. Наблюдаемость
|
||||
- Healthcheck эндпоинт (`GET /health`)
|
||||
- Логирование (JSON, ротация)
|
||||
- Prometheus метрики (запланированы на уровне приложения, в настоящее время доступны через балансировщик)
|
||||
- Аудит действий администраторов (обязателен, см. п. 2.10.2)
|
||||
|
||||
## 3.5. CI/CD
|
||||
- Drone CI (или GitLab CI / GitHub Actions)
|
||||
- EUnit + Common Test + Tsung
|
||||
- Сборка релиза
|
||||
- Docker-образ
|
||||
- Горячее обновление (rolling upgrade) кластера (3+ нод)
|
||||
- Миграции Mnesia
|
||||
|
||||
## 4. СТЕК ТЕХНОЛОГИЙ (С ВЕРСИЯМИ)
|
||||
- Бэкенд: Erlang/OTP 28.2
|
||||
- Сборка: rebar3 3.27.0
|
||||
- HTTP/WebSocket: Cowboy 2.10.0
|
||||
- JSON: jsx 3.1.0
|
||||
- JWT: jose (реализовано)
|
||||
- Хеширование паролей: erlang-argon2 1.0.0
|
||||
- Тестирование: meck 0.9.2, gun 2.0.0
|
||||
- Нагрузочное тестирование: Tsung 1.8.0
|
||||
- CI/CD: Drone 2.0+
|
||||
- Контейнеризация: Docker 20.10+
|
||||
- База данных: Mnesia (встроенная, распределённая)
|
||||
|
||||
## 5. ИЕРАРХИЧЕСКАЯ СТРУКТУРА КОДА
|
||||
```
|
||||
src/
|
||||
├── infra/ # инфраструктура (приложение, супервизоры, аутентификация, подписки)
|
||||
├── core/ # слой доступа к данным (DAO) и модели
|
||||
├── logic/ # бизнес-логика (независимая от HTTP/WS)
|
||||
├── services/ # внешние сервисы (заглушки/интеграции)
|
||||
└── handlers/ # обработчики HTTP/WebSocket
|
||||
```
|
||||
|
||||
**Правила:**
|
||||
- Модули `handlers/` не содержат бизнес-логики.
|
||||
- Модули `logic/` не знают о HTTP/WS.
|
||||
- Модули `core/` (DAO) работают только с Mnesia.
|
||||
- Модули `services/` могут быть заменены на реальные реализации без изменения остального кода.
|
||||
- Заголовочный файл `include/records.hrl` содержит все записи таблиц Mnesia.
|
||||
|
||||
## 6. ОСНОВНЫЕ API (КРАТКО)
|
||||
|
||||
### Пользовательские (порт 8080)
|
||||
- `POST /v1/register`
|
||||
- `POST /v1/login`
|
||||
- `GET /v1/user/me`
|
||||
- `POST /v1/calendars` + CRUD
|
||||
- `POST /v1/calendars/:id/events` + CRUD
|
||||
- `POST /v1/events/:id/join`
|
||||
- `POST /v1/events/:id/confirm/:user_id`
|
||||
- `POST /v1/reviews`
|
||||
- `POST /v1/reports`
|
||||
- `POST /v1/subscription/activate`
|
||||
- `POST /v1/events/:id/export` (Google)
|
||||
- `GET /v1/events/:id/ical` (Apple)
|
||||
- `GET /health`
|
||||
|
||||
**WebSocket (порт 8081):** `ws://localhost:8081/ws?token=...`
|
||||
|
||||
### Административные (порт 8445)
|
||||
- `GET /admin/stats/overview` (или `/admin/stats`) — статистика с учётом роли
|
||||
- `GET /admin/nodes`
|
||||
- `GET /admin/calendars`, `PUT /admin/calendars/:id/freeze`, `/unfreeze`
|
||||
- `GET /admin/events`, `PUT /admin/events/:id/freeze`, `PATCH /admin/events/:id/approve` (модерация)
|
||||
- `GET /admin/reviews`, `PUT /admin/reviews/:id/hide`
|
||||
- `GET /admin/reports` (complaints), `PUT /admin/reports/:id/status`
|
||||
- `GET /admin/tickets` (bugs), `POST /admin/tickets`, `PUT /admin/tickets/:id/status`, `DELETE /admin/tickets/:id`
|
||||
- `GET /admin/banned_words`, `POST /admin/banned_words`, `DELETE /admin/banned_words`
|
||||
- `GET /admin/admins` (только `superadmin`)
|
||||
- `PUT /admin/admins/:id` (только `superadmin`)
|
||||
- `POST /admin/admins` (только `superadmin`)
|
||||
- `GET /admin/audit` (только `superadmin`)
|
||||
- `GET /admin/me` (текущий админ, его роль и права)
|
||||
|
||||
**Административный WebSocket (порт 8446):** `wss://localhost:8446/admin/ws?token=...`
|
||||
|
||||
## 7. ВЕРСИОНИРОВАНИЕ И СТАТУС
|
||||
Текущая версия: **1.2** (MVP, альфа, включает гибридную модель повторяющихся событий и базовую ролевую модель администрирования).
|
||||
|
||||
## 8. ОГРАНИЧЕНИЯ И ДОПУЩЕНИЯ
|
||||
- В разработке используются самоподписанные SSL-сертификаты.
|
||||
- Для production требуется реальный сертификат и настройка OAuth2 для Google.
|
||||
- Заглушки внешних сервисов должны быть заменены перед запуском.
|
||||
- Полноценное разграничение прав администраторов (`superadmin`, `moderator`, `support`) ожидается в следующем релизе; пока используется универсальная роль `admin`.
|
||||
|
||||
## 9. ТРЕБОВАНИЯ К ОКРУЖЕНИЮ
|
||||
- Erlang/OTP 28.2
|
||||
- rebar3 3.27.0
|
||||
- openssl
|
||||
- Docker (опционально)
|
||||
- Drone (опционально, для CI/CD)
|
||||
183
EventHubFrontAdminSpec.md
Normal file
183
EventHubFrontAdminSpec.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# **EventHub Admin UI — Техническое задание** (MVP)
|
||||
|
||||
## 1. Роли и права доступа
|
||||
|
||||
| Роль | Идентификатор | Права |
|
||||
|------|---------------|-------|
|
||||
| **Суперадмин** | `superadmin` | Полный доступ ко всем модулям, включая изменение ролей других админов, просмотр аудита, системные настройки. |
|
||||
| **Модератор** | `moderator` | Модерация событий и жалоб, блокировка/разблокировка пользователей, работа с баг-трекером. |
|
||||
| **Поддержка** | `support` | Просмотр пользователей и событий (read-only), обработка жалоб, создание и обновление багов. |
|
||||
|
||||
**Примечание:** До реализации backend-эндпоинтов для управления ролями подразумевается одна роль `admin` (синоним `superadmin`).
|
||||
|
||||
---
|
||||
|
||||
## 2. Модули панели
|
||||
|
||||
### 2.1. Дашборд (Dashboard)
|
||||
|
||||
**Виджеты:**
|
||||
- Статистика по пользователям: всего, новых за сегодня, активных за неделю.
|
||||
- Статистика по событиям: всего, ожидают модерации, опубликовано, отклонено.
|
||||
- Статистика по жалобам: новых, в обработке.
|
||||
- График регистраций/событий по дням (за последние 30 дней) — если API предоставляет агрегации; иначе заглушка.
|
||||
- Последние действия модераторов (аудит) — последние 10 записей.
|
||||
|
||||
**Источник данных:** `GET /api/stats/*` (приоритетный) или агрегация из списков ресурсов через `X-Total-Count`.
|
||||
|
||||
### 2.2. Управление пользователями
|
||||
|
||||
**Эндпоинты:** `GET /api/users`, `GET /api/users/:id`, `PUT /api/users/:id`, `DELETE /api/users/:id`
|
||||
|
||||
**Функциональность:**
|
||||
- Список пользователей (ID, username, email, роль, дата регистрации, статус, рейтинг).
|
||||
- Фильтрация: по роли, статусу, поиск по username/email.
|
||||
- Детальная карточка:
|
||||
- Основная информация, аватар.
|
||||
- Список событий пользователя.
|
||||
- История жалоб на пользователя.
|
||||
- Блокировка/разблокировка, смена роли (только суперадмин).
|
||||
- Причина блокировки (поле ввода).
|
||||
- Массовые действия: блокировка/удаление выбранных пользователей.
|
||||
|
||||
**Особые требования:** Подтверждение деструктивных действий через модальное окно.
|
||||
|
||||
### 2.3. Управление событиями
|
||||
|
||||
**Эндпоинты:** `GET /api/events`, `GET /api/events/:id`, `PUT /api/events/:id`, `DELETE /api/events/:id`, а также эндпоинт модерации (например, `PATCH /api/events/:id/approve`)
|
||||
|
||||
**Функциональность:**
|
||||
- Список событий (название, организатор, календарь, статус, количество записей).
|
||||
- Фильтрация: по статусу, календарю, дате.
|
||||
- Детальный просмотр:
|
||||
- Полная информация о событии (описание, дата-время, локация, тип).
|
||||
- Список записей участников с возможностью ручного подтверждения/отклонения.
|
||||
- Кнопки «Одобрить» / «Отклонить» (изменение статуса с `pending` на `approved`/`rejected`).
|
||||
- При отклонении — обязательное указание причины.
|
||||
- Редактирование любого поля события.
|
||||
- Удаление с подтверждением.
|
||||
|
||||
### 2.4. Управление календарями
|
||||
|
||||
**Эндпоинты:** `GET /api/calendars`, `POST /api/calendars`, `PUT /api/calendars/:id`, `DELETE /api/calendars/:id`
|
||||
|
||||
**Функциональность:**
|
||||
- Список календарей (название, владелец, тип, количество подписчиков).
|
||||
- Детальный просмотр: информация, возможность деактивации календаря.
|
||||
- Создание коммерческого календаря (опционально, если требуется админам).
|
||||
- Просмотр списка подписчиков (только чтение).
|
||||
|
||||
### 2.5. Модерация жалоб
|
||||
|
||||
**Эндпоинты:** `GET /api/complaints`, `GET /api/complaints/:id`, `PUT /api/complaints/:id`
|
||||
|
||||
**Функциональность:**
|
||||
- Список жалоб (ID, тип, подавший, объект жалобы, статус).
|
||||
- Фильтрация: по статусу, типу.
|
||||
- Детальный просмотр:
|
||||
- Текст жалобы, прикреплённые файлы/ссылки.
|
||||
- Информация о нарушителе/событии.
|
||||
- Кнопки «Рассмотрено» и «Отклонить».
|
||||
- Возможность перехода к блокировке пользователя/события прямо из карточки жалобы.
|
||||
|
||||
### 2.6. Баг-трекер
|
||||
|
||||
**Эндпоинты:** `GET /api/bugs`, `POST /api/bugs`, `PUT /api/bugs/:id`, `DELETE /api/bugs/:id`
|
||||
|
||||
**Функциональность:**
|
||||
- Список багов (ID, заголовок, статус, приоритет, назначенный, дата создания).
|
||||
- Детальный просмотр: описание, шаги воспроизведения, скриншоты.
|
||||
- Смена статуса, назначение ответственного из числа админов.
|
||||
- Комментарии к багу (если поддержано API).
|
||||
- Создание новых багов (только внутренние, не от пользователей).
|
||||
|
||||
---
|
||||
|
||||
## 3. Интеграция с API и аутентификация
|
||||
|
||||
- JWT-аутентификация, аналогичная основному приложению.
|
||||
- Эндпоинт входа: `/api/auth/login` (или `/api/admin/login`).
|
||||
- Токен сохраняется в `localStorage` и добавляется ко всем запросам (`Authorization: Bearer ...`).
|
||||
- При получении HTTP 401 — редирект на страницу входа.
|
||||
- Для дашборда использовать специальные эндпоинты `/api/stats/*`; если их нет — собирать статистику через заголовок `X-Total-Count` и множественные запросы (временно).
|
||||
|
||||
---
|
||||
|
||||
## 4. Требования к UX/UI
|
||||
|
||||
- Material Design (React-Admin + MUI).
|
||||
- Адаптивная верстка (планшеты).
|
||||
- Пагинация (серверная предпочтительна, клиентская допустима для малых объемов).
|
||||
- Сортировка по любому полю.
|
||||
- Поиск с debounce 300 мс.
|
||||
- Подтверждение деструктивных действий (удаление, блокировка).
|
||||
- Уведомления об успехе/ошибке через Snackbar.
|
||||
- Тёмная тема (опционально, переключатель).
|
||||
|
||||
---
|
||||
|
||||
## 5. Технологический стек
|
||||
|
||||
- **Язык:** TypeScript
|
||||
- **Сборщик:** Vite
|
||||
- **UI-фреймворк:** React-Admin v5 + Material UI v5
|
||||
- **Провайдер данных:** `ra-data-simple-rest` с кастомизацией для JWT
|
||||
- **Аутентификация:** кастомный `authProvider`
|
||||
- **Контейнеризация:** Docker, Nginx
|
||||
|
||||
---
|
||||
|
||||
## 6. Этапы реализации (MVP)
|
||||
|
||||
1. **Неделя 1:** Инициализация проекта (Vite + React-Admin), простой dataProvider, страница входа.
|
||||
2. **Неделя 2:** Модуль пользователей (список, детали, блокировка).
|
||||
3. **Неделя 3:** Модуль событий (список, модерация).
|
||||
4. **Неделя 4:** Модули жалоб, баг-трекера, календарей (базовый просмотр/изменение статусов).
|
||||
5. **Неделя 5:** Дашборд (если API готово), финальные штрихи, тестирование, деплой в staging.
|
||||
|
||||
---
|
||||
|
||||
## 7. Что потребуется от бэкенда (EventHubBack)
|
||||
|
||||
### 7.1 Роли и права доступа
|
||||
|
||||
Описать три административные роли: `superadmin`, `moderator`, `support`.
|
||||
|
||||
В JWT-токене после аутентификации передавать поле `role` с одним из этих значений. Оставить поддержку `"role": "admin"` как синоним `superadmin` для обратной совместимости.
|
||||
|
||||
Middleware авторизации для админских эндпоинтов (`/admin/*` или порты 8445/8446) должен:
|
||||
- Проверять валидность JWT.
|
||||
- Извлекать роль.
|
||||
- Сопоставлять с требуемыми правами для каждого действия.
|
||||
|
||||
Эндпоинт получения текущей роли:
|
||||
- `GET /admin/me` (или `GET /api/auth/me`) — возвращает `{ id, username, role, permissions }`.
|
||||
|
||||
Эндпоинты управления ролями (только для `superadmin`):
|
||||
- `GET /admin/admins` — список администраторов.
|
||||
- `PUT /admin/admins/:id` — изменить роль.
|
||||
- `POST /admin/admins` — пригласить нового администратора.
|
||||
|
||||
Логирование действий (аудит):
|
||||
- Таблица `admin_audit` (admin_id, username, роль, действие, тип объекта, ID объекта, timestamp, IP, причина).
|
||||
- Эндпоинт `GET /admin/audit` с фильтрами (доступен только `superadmin`).
|
||||
|
||||
При блокировке пользователя / отклонении события обязательно принимать поле `reason` в теле запроса и сохранять в БД.
|
||||
|
||||
Разграничение прав на уровне API:
|
||||
- `support`: read-only пользователи и события; может обновлять статусы жалоб и багов, создавать баги.
|
||||
- `moderator`: всё, кроме управления админами и просмотра аудита.
|
||||
- `superadmin`: полный доступ.
|
||||
|
||||
Ответ при недостаточности прав: `403 Forbidden`, тело:
|
||||
```json
|
||||
{ "error": "insufficient_permissions", "message": "Требуется роль moderator или выше" }
|
||||
## 7.2 Статистика для дашборда с учётом ролей
|
||||
|
||||
| Роль | Предоставляемые метрики |
|
||||
|------|--------------------------|
|
||||
| `superadmin` | Системные метрики (все пользователи, события, жалобы, баги за период, графики регистраций/событий по дням, активность администраторов). |
|
||||
| `moderator` | Собственные обработанные жалобы/события (количество, статусы, время реакции), общая статистика по модерации. |
|
||||
| `support` | Количество открытых багов и жалоб, назначенных на текущего сотрудника, персональные задачи. |
|
||||
|
||||
Эндпоинт `GET /api/stats` должен возвращать JSON с секциями, доступными согласно роли вызывающего.
|
||||
Reference in New Issue
Block a user