feat: add branches feature, security audit, and multi-branch support

This commit is contained in:
dev
2026-09-09 09:41:07 +03:00
parent 7a003e5df6
commit d6e589d2f5
19 changed files with 1377 additions and 82 deletions
+142
View File
@@ -0,0 +1,142 @@
# План: Мультифилиальность и роли пользователей
## Проблема
Сейчас приложение однофилиальное и одно-user-овое. Нужно поддержать:
- 5-20 филиалов
- Несколько тьюторов/админов
- Филиал студента определяется автоматически через его группу
---
## 1. База данных — схема
### Новые таблицы
```sql
-- Филиалы
CREATE TABLE branches (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Пользователи системы
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(150) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) NOT NULL DEFAULT 'tutor', -- 'admin' или 'tutor'
branch_id INT REFERENCES branches(id), -- NULL для супер-админа
created_at TIMESTAMPTZ DEFAULT now()
);
```
### Изменения в существующих таблицах
| Таблица | Новое поле | Тип | Связь |
|---------|-----------|-----|-------|
| `groups` | `branch_id` | `INT` | `REFERENCES branches(id)` |
| `students` | `branch_id` | `INT` | `REFERENCES branches(id)` |
| `entries` | `branch_id` | `INT` | `REFERENCES branches(id)` |
| `group_photos` | `branch_id` | `INT` | `REFERENCES branches(id)` |
### Логика определения филиала
- Студент → в группе → группа привязана к филиалу → филиал определён
- При отправке записи `branch_id` берётся из группы студента
- Студенту не нужно выбирать филиал — он определяется автоматически
---
## 2. Аутентификация
- Вход по **имени + пароль** (без email)
- Пароли хранятся в `bcrypt` хеше
- Токен (JWT) выдаётся при логине, хранится в `sessionStorage`
- `requireAdmin` заменяется на `requireAuth` + проверку роли
---
## 3. Роли
| Роль | Возможности |
|------|-------------|
| **admin** | Всё: управление пользователями, филиалами, настройками, бэкапами + все данные |
| **tutor** | Управление записями, группами, студентами, файлами, ссылками — видит все группы |
---
## 4. Публичная форма
- Ссылка на форму одна (как сейчас)
- Студент вводит имя → система находит студента → определяет группу → определяет филиал
- Если студент новый (нет в базе) — варианты на обсуждение:
- Не пускать (только зарегистрированные студенты)
- Автоматически создать в группе "Не распределён"
---
## 5. Фронтенд — изменения
### Страница логина
- Поле "Имя" + "Пароль" вместо одного пароля
### Админ-панель
- В хедере/сайдбаре выпадающий список филиалов для фильтрации
- Группы — отображение филиала у каждой группы
- Студенты — отображение филиала у каждого студента
- Журнал — фильтр по филиалу
- Настройки — управление пользователями и филиалами (только для admin)
---
## 6. API — новые эндпоинты
| Метод | Путь | Описание |
|-------|------|----------|
| `POST` | `/api/auth/login` | Вход (имя + пароль → токен) |
| `GET` | `/api/branches` | Список филиалов |
| `POST` | `/api/branches` | Создать филиал (admin) |
| `DELETE` | `/api/branches/:id` | Удалить филиал (admin) |
| `GET` | `/api/users` | Список пользователей (admin) |
| `POST` | `/api/users` | Создать пользователя (admin) |
| `DELETE` | `/api/users/:id` | Удалить пользователя (admin) |
---
## 7. Миграция данных
- Существующие группы/студенты/записи автоматически попадут в филиал "Основной" (или первый созданный)
- `ADMIN_PASSWORD` из `.env` конвертируется в запись `users` с ролью `admin`
---
## 8. Структура файлов (рефакторинг)
```
server.js → рефакторинг на модули:
├── routes/
│ ├── auth.js (логин/аутентификация)
│ ├── branches.js (CRUD филиалов)
│ ├── users.js (CRUD пользователей)
│ ├── groups.js (существующие + branch_id)
│ ├── students.js (существующие + branch_id)
│ ├── entries.js (существующие + branch_id)
│ └── ...
├── middleware/
│ ├── auth.js (requireAuth, requireRole)
│ └── branch.js (branch scoping)
└── db.js (подключение к БД)
```
---
## Порядок реализации
1. **Миграция БД** — создать таблицы `branches`, `users`, добавить `branch_id` к существующим
2. **Миграция данных** — создать филиал "Основной", перенести существующие данные
3. **Бэкенд: аутентификация** — `auth.js` (логин, JWT, middleware)
4. **Бэкенд: CRUD филиалов и пользователей** — новые роуты
5. **Бэкенд: branch scoping** — добавить `branch_id` ко всем существующим запросам
6. **Фронтенд: логин** — новая страница логина
7. **Фронтенд: admin panel** — добавить фильтр филиалов, страницы управления
8. **Тестирование** — проверить все сценарии