|
@@ -1,437 +1,311 @@
|
|
|
-# MyBeacon - Техническое задание
|
|
|
|
|
|
|
+# MyBeacon Backend
|
|
|
|
|
|
|
|
-## О проекте
|
|
|
|
|
-
|
|
|
|
|
-MyBeacon - это платформа для работы с BLE и WiFi сканерами. Платформа **модульная** - можно подключать разные продукты независимо друг от друга. Сейчас планируются два продукта:
|
|
|
|
|
|
|
+Модульная платформа BLE/WiFi мониторинга с multi-tenant архитектурой.
|
|
|
|
|
|
|
|
-1. **WiFi Analytics** - сбор данных о WiFi устройствах для рекламной аналитики
|
|
|
|
|
-2. **BLE Tracking** - отслеживание BLE меток для контроля персонала и активов
|
|
|
|
|
-
|
|
|
|
|
-В будущем могут появиться другие продукты (например, мониторинг температуры, счетчики посетителей и т.д.). Вся админка и демон железки должны легко расширяться под новые продукты.
|
|
|
|
|
-
|
|
|
|
|
-## Кто пользуется системой
|
|
|
|
|
-
|
|
|
|
|
-### 1. Супер-админ
|
|
|
|
|
-- Полный доступ ко всему
|
|
|
|
|
-- Управляет клиентами (организациями)
|
|
|
|
|
-- Управляет железками (может отвязать от клиента, поменять настройки)
|
|
|
|
|
-- Видит все данные
|
|
|
|
|
|
|
+## Стек технологий
|
|
|
|
|
|
|
|
-### 2. Клиент (организация)
|
|
|
|
|
-- Это компания, которая покупает услугу
|
|
|
|
|
-- У клиента может быть **несколько пользователей** (сотрудников)
|
|
|
|
|
-- Видит только свои железки и свои данные
|
|
|
|
|
-- Доступ к продуктам включает админ (WiFi, BLE или оба)
|
|
|
|
|
|
|
+- **Backend**: Python 3.11+, FastAPI, SQLAlchemy (async)
|
|
|
|
|
+- **Database**: PostgreSQL 16 (metadata), Redis (cache)
|
|
|
|
|
+- **Authentication**: JWT (python-jose), bcrypt
|
|
|
|
|
+- **Development**: Poetry, uvicorn --reload
|
|
|
|
|
|
|
|
-### 3. Пользователь клиента
|
|
|
|
|
-- Сотрудник компании-клиента
|
|
|
|
|
-- Имеет **права доступа** (может быть read-only или полный доступ)
|
|
|
|
|
-- Права настраиваются **для каждого объекта** (например: может смотреть данные, но не менять настройки)
|
|
|
|
|
-- Все действия **логируются** (кто, когда, что делал)
|
|
|
|
|
|
|
+## Архитектура
|
|
|
|
|
|
|
|
-## Многопользовательский доступ в организации
|
|
|
|
|
-
|
|
|
|
|
-У одного клиента может работать много людей:
|
|
|
|
|
-- Директор (полный доступ)
|
|
|
|
|
-- Менеджеры (read-only по аналитике)
|
|
|
|
|
-- Техники (доступ к настройкам железок)
|
|
|
|
|
-- Охранники (только просмотр BLE меток на картах)
|
|
|
|
|
-
|
|
|
|
|
-**Требования:**
|
|
|
|
|
-- Владелец организации может добавлять пользователей
|
|
|
|
|
-- Каждому пользователю назначаются роли/права
|
|
|
|
|
-- Права на уровне объектов (может смотреть эту локацию, но не ту)
|
|
|
|
|
-- Логи всех действий: кто куда ходил, что смотрел, что нажимал
|
|
|
|
|
-- Возможность ограничить только чтением (read-only mode)
|
|
|
|
|
-
|
|
|
|
|
-**Роли пользователей в организации:**
|
|
|
|
|
-- **Владелец** (Owner) - полный доступ, управление пользователями
|
|
|
|
|
-- **Администратор** (Admin) - полный доступ к функционалу, но не может управлять пользователями
|
|
|
|
|
-- **Менеджер** (Manager) - доступ к аналитике и отчетам (read-only)
|
|
|
|
|
-- **Оператор** (Operator) - доступ к конкретным локациям/объектам
|
|
|
|
|
-- **Наблюдатель** (Viewer) - только просмотр, ничего не может менять
|
|
|
|
|
-
|
|
|
|
|
-## Регистрация и управление клиентами
|
|
|
|
|
-
|
|
|
|
|
-### Вариант 1: Самостоятельная регистрация
|
|
|
|
|
-
|
|
|
|
|
-1. Клиент заходит на сайт, жмет "Зарегистрироваться"
|
|
|
|
|
-2. Заполняет форму: email, пароль, название компании, телефон
|
|
|
|
|
-3. Ему приходит письмо с подтверждением email
|
|
|
|
|
-4. Кликает по ссылке - email подтвержден
|
|
|
|
|
-5. Логинится в личный кабинет - видит сообщение "Ожидается активация администратором"
|
|
|
|
|
-6. **По умолчанию доступа к продуктам НЕТ** (wifi_enabled=false, ble_enabled=false)
|
|
|
|
|
-7. Админ видит нового клиента в списке "Ожидают активации"
|
|
|
|
|
-8. Админ включает нужные продукты (WiFi, BLE или оба) - клиенту приходит уведомление
|
|
|
|
|
-9. Клиент заходит - видит активированные продукты
|
|
|
|
|
-
|
|
|
|
|
-### Вариант 2: Создание админом
|
|
|
|
|
-
|
|
|
|
|
-1. Админ создает клиента: email, название, телефон
|
|
|
|
|
-2. Выбирает какие продукты доступны (WiFi, BLE)
|
|
|
|
|
-3. Система генерирует пароль, отправляет на email клиента
|
|
|
|
|
-4. Клиент получает письмо с логином и паролем
|
|
|
|
|
-5. Логинится - сразу видит активные продукты
|
|
|
|
|
-
|
|
|
|
|
-## Железки (устройства)
|
|
|
|
|
-
|
|
|
|
|
-### Простой ID для общения с клиентами
|
|
|
|
|
-
|
|
|
|
|
-Железки имеют MAC адрес (например `38:54:39:4b:1b:ac`), но клиентам так общаться неудобно.
|
|
|
|
|
-
|
|
|
|
|
-**Решение:** Каждой железке присваивается **простой ID** начиная с 1:
|
|
|
|
|
-- Приемник #1
|
|
|
|
|
-- Приемник #2
|
|
|
|
|
-- Приемник #3
|
|
|
|
|
-- ...
|
|
|
|
|
-
|
|
|
|
|
-Когда клиент звонит в поддержку: "У нас проблема с приемником номер 5" - админ по фильтру легко находит его в базе.
|
|
|
|
|
-
|
|
|
|
|
-**Как работает:**
|
|
|
|
|
-- ID назначается автоматически при регистрации железки
|
|
|
|
|
-- ID уникальный в рамках всей системы (не сбрасывается)
|
|
|
|
|
-- В админке можно искать как по MAC, так и по простому ID
|
|
|
|
|
-- Клиенту показывается "Приемник #5", но можно раскрыть и увидеть MAC
|
|
|
|
|
-
|
|
|
|
|
-### Управление железками
|
|
|
|
|
-
|
|
|
|
|
-**Админ может:**
|
|
|
|
|
-- Видеть все железки (все клиенты)
|
|
|
|
|
-- Фильтровать: по клиенту, по статусу (онлайн/офлайн), по MAC, по простому ID
|
|
|
|
|
-- Привязывать/отвязывать железку к клиенту
|
|
|
|
|
-- Менять настройки любой железки
|
|
|
|
|
-- Открыть SSH терминал (через туннель)
|
|
|
|
|
-- Открыть dashboard железки (через туннель)
|
|
|
|
|
-
|
|
|
|
|
-**Клиент может:**
|
|
|
|
|
-- Видеть только свои железки
|
|
|
|
|
-- Менять настройки (если есть права)
|
|
|
|
|
-- Видеть статус (онлайн/офлайн)
|
|
|
|
|
-- Видеть последнюю активность
|
|
|
|
|
-- Назначать железку на конкретную локацию (для BLE)
|
|
|
|
|
-
|
|
|
|
|
-## Продукт 1: WiFi Analytics
|
|
|
|
|
-
|
|
|
|
|
-**Для кого:** рекламные агентства, торговые центры, аэропорты - всем кто хочет знать сколько людей проходит мимо.
|
|
|
|
|
-
|
|
|
|
|
-**Что делает:**
|
|
|
|
|
-- Собирает данные о WiFi устройствах (MAC адреса)
|
|
|
|
|
-- Фильтрует фейковые (рандомизированные) MAC адреса
|
|
|
|
|
-- Показывает статистику: уникальные посетители, повторные визиты, время нахождения
|
|
|
|
|
-- Экспортирует данные для рекламщиков
|
|
|
|
|
-
|
|
|
|
|
-**Личный кабинет клиента:**
|
|
|
|
|
-
|
|
|
|
|
-1. **Dashboard**
|
|
|
|
|
- - Общая статистика за период (сегодня/неделя/месяц)
|
|
|
|
|
- - Уникальные MAC адреса
|
|
|
|
|
- - Фейковые vs настоящие
|
|
|
|
|
- - График по дням/часам
|
|
|
|
|
- - Топ производителей устройств (Apple, Samsung и т.д.)
|
|
|
|
|
-
|
|
|
|
|
-2. **Мои железки**
|
|
|
|
|
- - Список своих сканеров
|
|
|
|
|
- - Статус (онлайн/офлайн)
|
|
|
|
|
- - Сколько событий собрали за период
|
|
|
|
|
- - Простой ID + MAC адрес
|
|
|
|
|
-
|
|
|
|
|
-3. **Экспорт данных**
|
|
|
|
|
- - Выбрать период
|
|
|
|
|
- - Выбрать формат (CSV, JSON)
|
|
|
|
|
- - Опции: исключить фейковые MAC
|
|
|
|
|
- - Скачать файл
|
|
|
|
|
- - История экспортов (когда, кто скачал)
|
|
|
|
|
-
|
|
|
|
|
-## Продукт 2: BLE Tracking
|
|
|
|
|
-
|
|
|
|
|
-**Для кого:** магазины, склады, больницы, офисы - где нужно отслеживать людей или объекты.
|
|
|
|
|
-
|
|
|
|
|
-**Что делает:**
|
|
|
|
|
-- Отслеживает BLE метки (iBeacon)
|
|
|
|
|
-- Показывает на карте где находятся метки
|
|
|
|
|
-- Привязывает метки к людям/объектам ("Марья Ивановна", "Велосипед №5")
|
|
|
|
|
-- История перемещений
|
|
|
|
|
-
|
|
|
|
|
-**Личный кабинет клиента:**
|
|
|
|
|
-
|
|
|
|
|
-### 1. Локации (объекты)
|
|
|
|
|
-
|
|
|
|
|
-Клиент может иметь несколько объектов:
|
|
|
|
|
-- Магазин на Ленина
|
|
|
|
|
-- Магазин на Пушкина
|
|
|
|
|
-- Склад №3
|
|
|
|
|
-
|
|
|
|
|
-Для каждой локации:
|
|
|
|
|
-- Название
|
|
|
|
|
-- Адрес
|
|
|
|
|
-- Свои приемники
|
|
|
|
|
-- Свои планы помещений
|
|
|
|
|
-
|
|
|
|
|
-### 2. Планы помещений
|
|
|
|
|
-
|
|
|
|
|
-**Загрузка плана:**
|
|
|
|
|
-1. Клиент загружает картинку (JPG/PNG) - растровый план
|
|
|
|
|
-2. Система автоматически конвертирует в вектор (SVG)
|
|
|
|
|
-3. Клиент в редакторе может:
|
|
|
|
|
- - Подправить контуры стен
|
|
|
|
|
- - Выделить зоны/комнаты
|
|
|
|
|
- - Добавить подписи
|
|
|
|
|
- - Указать масштаб (сколько метров в одном пикселе)
|
|
|
|
|
-
|
|
|
|
|
-**Цветовая схема (светлая тема):**
|
|
|
|
|
-- Фон: светло-зеленый `#E5F2E5`
|
|
|
|
|
-- Стены/контуры: серо-бежевый `#D4CFC4`
|
|
|
|
|
-- Комнаты: пастельные тона
|
|
|
|
|
- - Бежевый `#F5EFE0`
|
|
|
|
|
- - Персиковый `#FFE8D6`
|
|
|
|
|
- - Голубой `#E0F7FA`
|
|
|
|
|
-- Выделенные зоны: оранжевый контур `#FF9800`
|
|
|
|
|
-- Подписи: черный текст `#000000`
|
|
|
|
|
-
|
|
|
|
|
-*(Для темной темы - потом придумаем)*
|
|
|
|
|
-
|
|
|
|
|
-### 3. Размещение приемников на плане
|
|
|
|
|
-
|
|
|
|
|
-**Как работает:**
|
|
|
|
|
-1. Клиент открывает план помещения
|
|
|
|
|
-2. Видит список своих приемников (по простым ID: Приемник #1, #2, #3...)
|
|
|
|
|
-3. Перетаскивает иконку приемника на нужное место на карте
|
|
|
|
|
-4. Приемник показывается как **прямоугольная иконка с логотипом** (logo.svg)
|
|
|
|
|
-5. Можно повернуть иконку (если направление важно)
|
|
|
|
|
-6. Сохраняет расположение
|
|
|
|
|
-
|
|
|
|
|
-**Логотип приемника:**
|
|
|
|
|
-- Использовать `logo.svg` (beacon с концентрическими кругами)
|
|
|
|
|
-- Размер: ~32x32px на карте
|
|
|
|
|
-- Цвет: голубой `#1CB5D5`
|
|
|
|
|
-- При наведении - показывает: "Приемник #5 (онлайн)"
|
|
|
|
|
-
|
|
|
|
|
-### 4. Зоны на плане
|
|
|
|
|
-
|
|
|
|
|
-**Зачем нужны зоны:**
|
|
|
|
|
-С таким железом точная навигация не получится - только определение зоны нахождения. Этого достаточно в большинстве случаев: понять что человек в столовой, на складе или в туалете.
|
|
|
|
|
-
|
|
|
|
|
-**Как рисовать зоны:**
|
|
|
|
|
-1. Клиент открывает редактор плана
|
|
|
|
|
-2. Выбирает инструмент "Нарисовать зону"
|
|
|
|
|
-3. Рисует полигон (многоугольник) поверх плана
|
|
|
|
|
-4. Зона показывается **полупрозрачной** (например, синий с прозрачностью 30%)
|
|
|
|
|
-5. Зоне автоматически присваивается номер: Зона #1, Зона #2, Зона #3...
|
|
|
|
|
-6. Клиент может дать зоне название: "Столовая", "Зал", "Склад", "Туалет", "Задний вход"
|
|
|
|
|
-7. Сохраняет
|
|
|
|
|
-
|
|
|
|
|
-**Свойства зоны:**
|
|
|
|
|
-- Номер (автоматический, уникальный на плане)
|
|
|
|
|
-- Название (задает клиент)
|
|
|
|
|
-- Цвет (можно выбрать из палитры)
|
|
|
|
|
-- Полигон (координаты вершин)
|
|
|
|
|
-
|
|
|
|
|
-**Примеры зон:**
|
|
|
|
|
-- Зона #1: "Столовая" (голубой)
|
|
|
|
|
-- Зона #2: "Торговый зал" (зеленый)
|
|
|
|
|
-- Зона #3: "Склад" (желтый)
|
|
|
|
|
-- Зона #4: "Туалет" (розовый)
|
|
|
|
|
-- Зона #5: "Задний вход" (оранжевый)
|
|
|
|
|
-
|
|
|
|
|
-**Определение принадлежности метки к зоне:**
|
|
|
|
|
-- Бэк по координатам метки определяет в какой зоне она находится (point-in-polygon)
|
|
|
|
|
-- Если метка видна несколькими приемниками - берется среднее положение
|
|
|
|
|
-- Если не попала ни в одну зону - показывается "Вне зон"
|
|
|
|
|
-
|
|
|
|
|
-**Аналитика по зонам:**
|
|
|
|
|
-- Сколько времени метка провела в каждой зоне
|
|
|
|
|
-- Сколько меток сейчас в каждой зоне
|
|
|
|
|
-- Тепловая карта по зонам (какие зоны самые посещаемые)
|
|
|
|
|
-- Маршруты: Зона #1 → Зона #3 → Зона #2
|
|
|
|
|
-
|
|
|
|
|
-### 5. Управление метками (Beacons)
|
|
|
|
|
-
|
|
|
|
|
-**Добавление метки:**
|
|
|
|
|
-- UUID, Major, Minor (технические идентификаторы iBeacon)
|
|
|
|
|
-- Привязать к объекту:
|
|
|
|
|
- - Тип: Человек / Актив / Транспорт
|
|
|
|
|
- - Имя: "Марья Ивановна", "Велосипед №5", "Погрузчик ПГ-12"
|
|
|
|
|
- - Фото (опционально)
|
|
|
|
|
- - Описание
|
|
|
|
|
-
|
|
|
|
|
-**Список меток:**
|
|
|
|
|
-- Поиск по имени
|
|
|
|
|
-- Фильтр по типу
|
|
|
|
|
-- Статус: активна / не видна >10 минут
|
|
|
|
|
-- Последнее местоположение
|
|
|
|
|
-
|
|
|
|
|
-### 5. Real-time карта
|
|
|
|
|
-
|
|
|
|
|
-**Что видит клиент:**
|
|
|
|
|
-- План помещения
|
|
|
|
|
-- Иконки приемников (с логотипами) на своих местах
|
|
|
|
|
-- **Метки на карте:**
|
|
|
|
|
- - Показываются иконкой (точка или аватарка)
|
|
|
|
|
- - Рядом с меткой: "Марья Ивановна, -65dB"
|
|
|
|
|
- - RSSI показывает силу сигнала (близость к приемнику)
|
|
|
|
|
- - Если метка видна несколькими приемниками - показывается примерная позиция
|
|
|
|
|
-
|
|
|
|
|
-**Обновление:**
|
|
|
|
|
-- Каждые 5-10 секунд карта обновляется
|
|
|
|
|
-- Можно включить автообновление (polling) или WebSocket
|
|
|
|
|
-
|
|
|
|
|
-**История:**
|
|
|
|
|
-- Можно включить "воспроизведение" - как двигалась метка за последний час/день
|
|
|
|
|
-- Тепловая карта (где метка проводила больше времени)
|
|
|
|
|
-
|
|
|
|
|
-## Туннели (удаленный доступ)
|
|
|
|
|
-
|
|
|
|
|
-### SSH туннель
|
|
|
|
|
-
|
|
|
|
|
-**Зачем:** админ может подключиться к терминалу железки удаленно (даже если она за NAT).
|
|
|
|
|
-
|
|
|
|
|
-**Как работает:**
|
|
|
|
|
-1. Админ в списке железок жмет кнопку **[Открыть SSH]**
|
|
|
|
|
-2. Открывается новая страница с сообщением "Подключение к устройству..."
|
|
|
|
|
-3. Система:
|
|
|
|
|
- - Включает SSH туннель на железке
|
|
|
|
|
- - Ждет пока железка подключится (до 60 секунд)
|
|
|
|
|
- - Запускает ttyd (веб-терминал)
|
|
|
|
|
-4. В браузере открывается терминал - админ работает как в SSH
|
|
|
|
|
-5. При закрытии вкладки - терминал убивается (через 60 секунд grace period)
|
|
|
|
|
-6. Туннель остается активным (можно переоткрыть терминал)
|
|
|
|
|
-
|
|
|
|
|
-### Dashboard туннель
|
|
|
|
|
-
|
|
|
|
|
-**Зачем:** админ или клиент может открыть веб-интерфейс железки.
|
|
|
|
|
-
|
|
|
|
|
-**Как работает:**
|
|
|
|
|
-1. Жмет кнопку **[Открыть Dashboard]**
|
|
|
|
|
-2. Ожидание подключения...
|
|
|
|
|
-3. Открывается iframe с dashboard железки
|
|
|
|
|
-4. Можно смотреть статус, логи, менять настройки прямо на железке
|
|
|
|
|
-
|
|
|
|
|
-## Права доступа и логирование
|
|
|
|
|
-
|
|
|
|
|
-### Система прав
|
|
|
|
|
-
|
|
|
|
|
-**На уровне организации:**
|
|
|
|
|
-- Владелец может добавлять/удалять пользователей
|
|
|
|
|
-- Владелец назначает роли
|
|
|
|
|
-- Администратор не может управлять пользователями, но может все остальное
|
|
|
|
|
-
|
|
|
|
|
-**На уровне объектов (для BLE):**
|
|
|
|
|
-- Пользователь может иметь доступ только к определенным локациям
|
|
|
|
|
-- Пример: охранник видит только "Магазин на Ленина", но не видит "Склад №3"
|
|
|
|
|
-- Права: read-only (только смотреть) или read-write (менять настройки)
|
|
|
|
|
-
|
|
|
|
|
-**Матрица прав:**
|
|
|
|
|
-```
|
|
|
|
|
-Действие | Owner | Admin | Manager | Operator | Viewer
|
|
|
|
|
--------------------------|-------|-------|---------|----------|-------
|
|
|
|
|
-Просмотр аналитики | ✓ | ✓ | ✓ | ✓ | ✓
|
|
|
|
|
-Экспорт данных | ✓ | ✓ | ✓ | ✗ | ✗
|
|
|
|
|
-Настройки железок | ✓ | ✓ | ✗ | ✓ | ✗
|
|
|
|
|
-Управление метками | ✓ | ✓ | ✗ | ✓ | ✗
|
|
|
|
|
-Управление пользователями| ✓ | ✗ | ✗ | ✗ | ✗
|
|
|
|
|
-Изменение планов | ✓ | ✓ | ✗ | ✓ | ✗
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-### Детальное логирование
|
|
|
|
|
-
|
|
|
|
|
-**Что логируется:**
|
|
|
|
|
-- Вход/выход пользователя (timestamp, IP адрес)
|
|
|
|
|
-- Переходы по страницам ("открыл страницу локации X")
|
|
|
|
|
-- Просмотр данных ("посмотрел аналитику за период Y")
|
|
|
|
|
-- Изменения ("изменил настройки железки #5", "привязал метку к человеку")
|
|
|
|
|
-- Экспорты ("скачал CSV с данными за месяц")
|
|
|
|
|
-- Действия с пользователями ("добавил пользователя", "изменил права")
|
|
|
|
|
-
|
|
|
|
|
-**Формат лога:**
|
|
|
|
|
-```
|
|
|
|
|
-2024-01-15 10:30:45 | user@example.com | Просмотр | Локация "Магазин на Ленина" | IP: 192.168.1.100
|
|
|
|
|
-2024-01-15 10:31:12 | user@example.com | Изменение | Метка #42: "Велосипед №5" → "Велосипед №6" | IP: 192.168.1.100
|
|
|
|
|
-2024-01-15 10:35:00 | user@example.com | Экспорт | WiFi Analytics, 2024-01-01 - 2024-01-15, CSV | IP: 192.168.1.100
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-**Где смотреть логи:**
|
|
|
|
|
-- Владелец и Админ видят все логи своей организации
|
|
|
|
|
-- Фильтры: по пользователю, по действию, по дате
|
|
|
|
|
-- Экспорт логов в CSV
|
|
|
|
|
-
|
|
|
|
|
-## Модульность системы
|
|
|
|
|
-
|
|
|
|
|
-Система должна легко расширяться новыми продуктами.
|
|
|
|
|
-
|
|
|
|
|
-**Принципы:**
|
|
|
|
|
-- Каждый продукт - независимый модуль
|
|
|
|
|
-- Админка - общая (управление клиентами, железками, пользователями)
|
|
|
|
|
-- Демон железки универсальный (можно включать/выключать модули в конфиге)
|
|
|
|
|
-- API универсальное (endpoints группируются по продуктам)
|
|
|
|
|
-
|
|
|
|
|
-**Пример добавления нового продукта "Temperature Monitoring":**
|
|
|
|
|
-1. В клиентах добавляется флаг `temperature_enabled`
|
|
|
|
|
-2. В API добавляется группа `/api/v1/client/temperature/*`
|
|
|
|
|
-3. В демоне железки добавляется модуль сбора температуры
|
|
|
|
|
-4. Во frontend добавляется раздел "Температура"
|
|
|
|
|
-5. Админ включает продукт клиенту - тот видит новый раздел
|
|
|
|
|
-
|
|
|
|
|
-**Переиспользование в других проектах:**
|
|
|
|
|
-- Можно взять только админку и использовать для управления любыми IoT устройствами
|
|
|
|
|
-- Можно взять демон железки и адаптировать под другое железо (Raspberry Pi, ESP32)
|
|
|
|
|
-- API спроектировано универсально
|
|
|
|
|
-
|
|
|
|
|
-## Технический стек
|
|
|
|
|
-
|
|
|
|
|
-### Backend
|
|
|
|
|
-- **Python + FastAPI**
|
|
|
|
|
-- **PostgreSQL** - клиенты, пользователи, железки, права
|
|
|
|
|
-- **ClickHouse** - события (BLE/WiFi), аналитика
|
|
|
|
|
-- **Redis** - очереди, кеш
|
|
|
|
|
-
|
|
|
|
|
-### Frontend
|
|
|
|
|
-- **Vue 3 + Vite**
|
|
|
|
|
-- **Vue Router** + **Pinia**
|
|
|
|
|
-- **TailwindCSS** (или Vuetify)
|
|
|
|
|
-
|
|
|
|
|
-### Деплой
|
|
|
|
|
-- **БЕЗ Docker** (обычный Linux + systemd)
|
|
|
|
|
-- Скрипт установки всех зависимостей
|
|
|
|
|
-- PostgreSQL, ClickHouse, Redis, Nginx
|
|
|
|
|
-- Автоматические миграции БД
|
|
|
|
|
-
|
|
|
|
|
-## План разработки
|
|
|
|
|
-
|
|
|
|
|
-### Этап 1: Фундамент (2-3 недели)
|
|
|
|
|
-- Auth (многопользовательский, роли)
|
|
|
|
|
-- Админка: клиенты + пользователи в организациях
|
|
|
|
|
-- Device API (регистрация, конфиг)
|
|
|
|
|
-- Управление железками (с простыми ID)
|
|
|
|
|
-- Background worker: буфер → ClickHouse
|
|
|
|
|
-
|
|
|
|
|
-### Этап 2: WiFi Analytics (1-2 недели)
|
|
|
|
|
-- WiFi события в ClickHouse
|
|
|
|
|
-- Аналитика (уникальные MAC, фейковые)
|
|
|
|
|
-- Клиентский кабинет WiFi
|
|
|
|
|
-- Экспорт данных
|
|
|
|
|
-
|
|
|
|
|
-### Этап 3: Tunnels (1 неделя)
|
|
|
|
|
-- SSH + Dashboard туннели
|
|
|
|
|
-- ttyd для веб-терминала
|
|
|
|
|
-- UI: кнопки + ожидание подключения
|
|
|
|
|
-
|
|
|
|
|
-### Этап 4: BLE Tracking (2-3 недели)
|
|
|
|
|
-- Локации, планы, метки
|
|
|
|
|
-- Загрузка и редактирование планов
|
|
|
|
|
-- Размещение приемников на карте
|
|
|
|
|
-- Real-time отображение меток
|
|
|
|
|
-
|
|
|
|
|
-### Этап 5: Права и логи (1 неделя)
|
|
|
|
|
-- Детальная система прав
|
|
|
|
|
-- Логирование всех действий
|
|
|
|
|
-- UI для просмотра логов
|
|
|
|
|
-
|
|
|
|
|
-## Открытые вопросы
|
|
|
|
|
-
|
|
|
|
|
-1. **Домен**: какой? mybeacon.ru?
|
|
|
|
|
-2. **Email**: SMTP настройки? Свой сервер или SendGrid?
|
|
|
|
|
-3. **File storage**: где хранить планы и фото? `/uploads` на сервере?
|
|
|
|
|
-4. **Real-time BLE**: polling каждые 5 сек или WebSocket?
|
|
|
|
|
-5. **Экспорт WiFi**: какой формат CSV нужен? Какие поля?
|
|
|
|
|
-6. **Хранение событий**: сколько хранить в ClickHouse? Год?
|
|
|
|
|
-7. **Ресурсы сервера**: сколько RAM/CPU? Сколько железок планируется?
|
|
|
|
|
|
|
+### Multi-tenant
|
|
|
|
|
+
|
|
|
|
|
+Полная изоляция данных между организациями:
|
|
|
|
|
+- Каждый пользователь принадлежит организации
|
|
|
|
|
+- Устройства назначаются организациям
|
|
|
|
|
+- API автоматически фильтрует данные по organization_id
|
|
|
|
|
+
|
|
|
|
|
+### Роли (RBAC)
|
|
|
|
|
+
|
|
|
|
|
+1. **superadmin** - полный доступ ко всем организациям и устройствам
|
|
|
|
|
+2. **owner** - управление своей организацией (создание/удаление пользователей, устройств)
|
|
|
|
|
+3. **admin** - управление пользователями в организации
|
|
|
|
|
+4. **manager** - просмотр и частичное управление
|
|
|
|
|
+5. **operator** - только просмотр устройств
|
|
|
|
|
+6. **viewer** - минимальный доступ (только чтение)
|
|
|
|
|
+
|
|
|
|
|
+### Автоматическая регистрация устройств
|
|
|
|
|
+
|
|
|
|
|
+- Superadmin включает авторегистрацию через API
|
|
|
|
|
+- Новые устройства регистрируются автоматически при первом подключении
|
|
|
|
|
+- Авторегистрация автоматически отключается через 1 час после последнего зарегистрированного устройства
|
|
|
|
|
+- Незарегистрированные устройства (organization_id = NULL) назначаются superadmin'ом
|
|
|
|
|
+
|
|
|
|
|
+## API Endpoints
|
|
|
|
|
+
|
|
|
|
|
+### Authentication (`/api/v1/auth/*`)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+POST /auth/register - Регистрация нового пользователя
|
|
|
|
|
+POST /auth/login - Вход (получение JWT токенов)
|
|
|
|
|
+POST /auth/refresh - Обновление access token
|
|
|
|
|
+GET /auth/me - Информация о текущем пользователе
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Superadmin API (`/api/v1/superadmin/*`)
|
|
|
|
|
+
|
|
|
|
|
+**Organizations:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /superadmin/organizations - Список всех организаций
|
|
|
|
|
+POST /superadmin/organizations - Создание организации
|
|
|
|
|
+GET /superadmin/organizations/:id - Просмотр организации
|
|
|
|
|
+PATCH /superadmin/organizations/:id - Обновление (статус, модули)
|
|
|
|
|
+DELETE /superadmin/organizations/:id - Удаление организации
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Users:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /superadmin/users - Список всех пользователей
|
|
|
|
|
+POST /superadmin/users - Создание пользователя
|
|
|
|
|
+GET /superadmin/users/:id - Просмотр пользователя
|
|
|
|
|
+PATCH /superadmin/users/:id - Обновление пользователя
|
|
|
|
|
+DELETE /superadmin/users/:id - Удаление пользователя
|
|
|
|
|
+POST /superadmin/users/:id/change-password - Смена пароля
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Devices:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /superadmin/devices - Список всех устройств
|
|
|
|
|
+POST /superadmin/devices - Регистрация устройства
|
|
|
|
|
+GET /superadmin/devices/:id - Просмотр устройства
|
|
|
|
|
+PATCH /superadmin/devices/:id - Обновление (назначение организации)
|
|
|
|
|
+DELETE /superadmin/devices/:id - Удаление устройства
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Settings:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /superadmin/settings/auto-registration - Статус авторегистрации
|
|
|
|
|
+POST /superadmin/settings/auto-registration - Включить/выключить авторегистрацию
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Client API (`/api/v1/client/*`)
|
|
|
|
|
+
|
|
|
|
|
+**Organization:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /client/organization/me - Информация о своей организации
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Users (owner/admin only):**
|
|
|
|
|
+```
|
|
|
|
|
+GET /client/users - Пользователи в организации
|
|
|
|
|
+POST /client/users - Создать пользователя
|
|
|
|
|
+GET /client/users/:id - Просмотр пользователя
|
|
|
|
|
+PATCH /client/users/:id - Обновление пользователя
|
|
|
|
|
+DELETE /client/users/:id - Удаление пользователя
|
|
|
|
|
+POST /client/users/:id/change-password - Смена пароля
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Devices:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /client/devices - Устройства организации
|
|
|
|
|
+GET /client/devices/:id - Просмотр устройства
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Device API (для железок)
|
|
|
|
|
+
|
|
|
|
|
+**Registration:**
|
|
|
|
|
+```
|
|
|
|
|
+POST /api/v1/registration
|
|
|
|
|
+Body: {"device_id": "MAC_ADDRESS", "ssh_public_key": "..."}
|
|
|
|
|
+Response: {"device_token": "...", "device_password": "..."}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Configuration:**
|
|
|
|
|
+```
|
|
|
|
|
+GET /api/v1/config?device_id=MAC_ADDRESS
|
|
|
|
|
+Headers: Authorization: Bearer DEVICE_TOKEN
|
|
|
|
|
+Response: {config object with BLE/WiFi settings}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Events:**
|
|
|
|
|
+```
|
|
|
|
|
+POST /api/v1/ble - BLE scan events batch
|
|
|
|
|
+POST /api/v1/wifi - WiFi probe events batch
|
|
|
|
|
+Headers: Authorization: Bearer DEVICE_TOKEN
|
|
|
|
|
+Headers: Content-Encoding: gzip (optional)
|
|
|
|
|
+Body: {"count": N, "events": [...]}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Database Schema
|
|
|
|
|
+
|
|
|
|
|
+### Основные таблицы
|
|
|
|
|
+
|
|
|
|
|
+**users** - Пользователи (superadmin + org users)
|
|
|
|
|
+```sql
|
|
|
|
|
+id, email, hashed_password, full_name, phone,
|
|
|
|
|
+role, status, organization_id, email_verified,
|
|
|
|
|
+last_login_at, created_at
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**organizations** - Организации (клиенты)
|
|
|
|
|
+```sql
|
|
|
|
|
+id, name, contact_email, contact_phone,
|
|
|
|
|
+wifi_enabled, ble_enabled, status, notes, created_at
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**devices** - Устройства (receivers)
|
|
|
|
|
+```sql
|
|
|
|
|
+id, simple_id, mac_address, organization_id,
|
|
|
|
|
+device_token, device_password, status, last_seen_at,
|
|
|
|
|
+config (JSONB), created_at
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**settings** - Системные настройки
|
|
|
|
|
+```sql
|
|
|
|
|
+id, key, value (JSONB), updated_at
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**refresh_tokens** - JWT refresh tokens
|
|
|
|
|
+```sql
|
|
|
|
|
+id, user_id, token, expires_at, created_at
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Simple ID
|
|
|
|
|
+
|
|
|
|
|
+Устройства получают автоинкрементный simple_id для отображения:
|
|
|
|
|
+- Устройство #1, #2, #3... вместо MAC-адресов
|
|
|
|
|
+- PostgreSQL sequence гарантирует уникальность
|
|
|
|
|
+- Используется для customer support
|
|
|
|
|
+
|
|
|
|
|
+## Установка и запуск
|
|
|
|
|
+
|
|
|
|
|
+### Требования
|
|
|
|
|
+
|
|
|
|
|
+- Python 3.11+
|
|
|
|
|
+- PostgreSQL 16+
|
|
|
|
|
+- Redis 7+
|
|
|
|
|
+- Poetry
|
|
|
|
|
+
|
|
|
|
|
+### Установка
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd backend
|
|
|
|
|
+
|
|
|
|
|
+# Установка зависимостей
|
|
|
|
|
+poetry install
|
|
|
|
|
+
|
|
|
|
|
+# Копирование .env
|
|
|
|
|
+cp .env.example .env
|
|
|
|
|
+# Редактировать .env (DATABASE_URL, SECRET_KEY)
|
|
|
|
|
+
|
|
|
|
|
+# Миграции
|
|
|
|
|
+poetry run alembic upgrade head
|
|
|
|
|
+
|
|
|
|
|
+# Создание superadmin (вручную или через скрипт)
|
|
|
|
|
+poetry run python -c "
|
|
|
|
|
+from app.core.security import hash_password
|
|
|
|
|
+print(hash_password('YOUR_PASSWORD'))
|
|
|
|
|
+"
|
|
|
|
|
+# Вставить в БД:
|
|
|
|
|
+# INSERT INTO users (email, hashed_password, role, status, email_verified)
|
|
|
|
|
+# VALUES ('admin@example.com', 'HASHED_PASSWORD', 'superadmin', 'active', true);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Запуск
|
|
|
|
|
+
|
|
|
|
|
+**Development:**
|
|
|
|
|
+```bash
|
|
|
|
|
+poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Production:**
|
|
|
|
|
+```bash
|
|
|
|
|
+poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Swagger UI:** http://localhost:8000/docs
|
|
|
|
|
+
|
|
|
|
|
+## Тестирование
|
|
|
|
|
+
|
|
|
|
|
+### Включение авторегистрации
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+curl -X POST http://localhost:8000/api/v1/superadmin/settings/auto-registration \
|
|
|
|
|
+ -H "Authorization: Bearer SUPERADMIN_TOKEN" \
|
|
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
|
|
+ -d '{"enabled": true}'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Проверка регистрации устройства
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# На устройстве (автоматически при старте):
|
|
|
|
|
+# POST /api/v1/registration с MAC-адресом
|
|
|
|
|
+
|
|
|
|
|
+# Проверка в базе:
|
|
|
|
|
+psql -U mybeacon -d mybeacon -c "SELECT simple_id, mac_address, status FROM devices;"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Назначение устройства организации
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+curl -X PATCH http://localhost:8000/api/v1/superadmin/devices/DEVICE_ID \
|
|
|
|
|
+ -H "Authorization: Bearer SUPERADMIN_TOKEN" \
|
|
|
|
|
+ -H "Content-Type: application/json" \
|
|
|
|
|
+ -d '{"organization_id": ORG_ID}'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Конфигурация
|
|
|
|
|
+
|
|
|
|
|
+### Environment Variables (.env)
|
|
|
|
|
+
|
|
|
|
|
+```env
|
|
|
|
|
+# Database
|
|
|
|
|
+DATABASE_URL=postgresql+asyncpg://mybeacon:password@localhost/mybeacon
|
|
|
|
|
+
|
|
|
|
|
+# Security
|
|
|
|
|
+SECRET_KEY=your-secret-key-here-minimum-32-chars
|
|
|
|
|
+ALGORITHM=HS256
|
|
|
|
|
+ACCESS_TOKEN_EXPIRE_MINUTES=15
|
|
|
|
|
+REFRESH_TOKEN_EXPIRE_DAYS=30
|
|
|
|
|
+
|
|
|
|
|
+# Redis (optional)
|
|
|
|
|
+REDIS_URL=redis://localhost:6379/0
|
|
|
|
|
+
|
|
|
|
|
+# Server
|
|
|
|
|
+HOST=0.0.0.0
|
|
|
|
|
+PORT=8000
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Device Default Config
|
|
|
|
|
+
|
|
|
|
|
+Дефолтная конфигурация для устройств (см. `app/api/v1/config.py`):
|
|
|
|
|
+- BLE enabled, batch_interval_ms: 2500
|
|
|
|
|
+- WiFi monitor disabled по умолчанию
|
|
|
|
|
+- SSH/Dashboard tunnels disabled
|
|
|
|
|
+- NTP servers: pool.ntp.org, time.google.com
|
|
|
|
|
+
|
|
|
|
|
+Конфигурация перезаписывается через `device.config` (JSONB).
|
|
|
|
|
+
|
|
|
|
|
+## Безопасность
|
|
|
|
|
+
|
|
|
|
|
+- JWT токены с expiration (15 мин access, 30 дней refresh)
|
|
|
|
|
+- Device tokens уникальные, хранятся в БД
|
|
|
|
|
+- Bcrypt для паролей (cost factor 12)
|
|
|
|
|
+- HTTPS рекомендуется (nginx reverse proxy)
|
|
|
|
|
+- RBAC на уровне endpoints
|
|
|
|
|
+- Multi-tenant изоляция в SQL queries
|
|
|
|
|
+
|
|
|
|
|
+## Мониторинг
|
|
|
|
|
+
|
|
|
|
|
+События логируются в консоль:
|
|
|
|
|
+```
|
|
|
|
|
+[REGISTRATION] device=MAC simple_id=N
|
|
|
|
|
+[BLE BATCH] device=MAC simple_id=N count=X
|
|
|
|
|
+[WIFI BATCH] device=MAC simple_id=N count=X
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+ClickHouse для хранения событий будет добавлен позже.
|
|
|
|
|
+
|
|
|
|
|
+## Roadmap
|
|
|
|
|
+
|
|
|
|
|
+- [ ] ClickHouse интеграция для событий
|
|
|
|
|
+- [ ] WebSocket для real-time BLE карты
|
|
|
|
|
+- [ ] Frontend (Vue 3)
|
|
|
|
|
+- [ ] Email notifications
|
|
|
|
|
+- [ ] Audit logs middleware
|
|
|
|
|
+- [ ] Rate limiting
|
|
|
|
|
+- [ ] Grafana dashboards
|