Files
Learn_System/plans/permissions-rework/PLAN.md
T
2026-06-03 14:43:45 +03:00

74 lines
7.5 KiB
Markdown
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.
# PLAN — Переработка ролевых прав (Role Permissions Rework)
> Составлен 2026-06-03 (Opus) по итогам разбора. Цель — сделать модель ролевых прав корректной
> (зависимости), прозрачной (история, линт), гибкой (группы, пресеты, кастомные роли) и убрать
> болезненный сайд-эффект (массовый разлогин при смене права).
>
> Факты по текущему коду (проверено):
> - `backend/src/permissions/registry.js` — 23 ключа, роли teacher/student (+free_student зеркалит student);
> поля `role/roles/default/label/desc/requireConfirmOff`.
> - Резолв: `requirePermission` (`middleware/auth.js:46`) читает **живьём из БД**: user_permissions →
> role_permissions → дефолт реестра. `authMiddleware` каждый запрос перечитывает роль из БД.
> - Таблицы `role_permissions(role,permission,enabled)`, `user_permissions(user_id,permission,enabled)`.
> - `permissionsController.js`: GET /api/permissions, POST (role-level), GET /me, GET/POST /users/:id, DELETE reset.
> На каждое изменение — `token_version++` (role-level → у ВСЕХ юзеров роли; user-level → у одного).
> - UI: `frontend/js/admin/sections/permissions.js` (тумблеры по ролям) + `user-detail.js` (оверрайды).
---
## Phase A — Быстрые победы (низкий риск)
- [ ] **A1. Зависимости между правами (`requires`).** Поле `requires:[...]` в реестре
(`questions.delete``questions.manage`; `templates.public``templates.manage`;
`courses.interactive``courses.manage`; `simulations.quiz``simulations.access`).
Enforce в `requirePermission` (effective = own AND все requires). Учесть в `/me` и `/users/:id`
(effective с учётом requires). UI: каскад (родитель off → дочерние серые/выключены). Тест.
- [ ] **A2. Гигиена реестра + ясные метки.** Тест-линт: каждый ключ из `requirePermission/perm(...)` в коде
есть в реестре; предупреждать о неиспользуемых ключах. Метки `theory.access`/`simulations.access`
переформулировать как «… доступен роли» (видимость конкретного — по классам в content_access).
- [ ] **A3. История изменений прав в UI.** Аудит уже пишется (`permission.set`/`permission.user_set`/
`permission.user_reset`). Эндпоинт `GET /api/permissions/log` (+ опц. фильтр по роли/пользователю),
кнопка «История» на вкладке «Доступ · роли» и в карточке пользователя. Переиспользовать паттерн
`/api/access/log`.
- [ ] **A4. Смягчить `token_version++`.** Сервер уже применяет права live → массовый разлогин роли при
одном тумблере не нужен. Убрать bump на role-level (и/или user-level), вместо этого клиент
пере-запрашивает `/permissions/me` при `focus`/навигации. Сохранить немедленный серверный эффект
(он и так есть). Аккуратно: проверить, где клиент кэширует права (lab-glue и т. п.).
## Phase B — Среднее (управление при масштабе)
- [ ] **B5. Группы прав (`group`).** Поле `group` в реестре («Контент»/«Класс»/«Геймификация»/«Профиль»/
«Библиотека») → секции в UI + «вкл/выкл всю группу».
- [ ] **B6. Массовое применение к классу / выбранным ученикам.** Через `class_members`: выставить право
пачке учеников (аналог матрицы/массовых операций content_access).
- [ ] **B7. Пресеты-профили прав.** Бандлы («Ограниченный ученик», «Ассистент учителя») — применить к
пользователю/классу одним кликом.
- [ ] **B8. Временные права (`expires_at`).** Колонка в `user_permissions` + авто-снятие в резолвере/кроне.
## Phase C — Крупное / архитектурное
- [ ] **C9. Кастомные роли.** Таблица ролей в БД + наборы дефолтов; реестр остаётся словарём ключей.
Кандидаты: методист/завуч, классрук/куратор, ассистент учителя, родитель (есть `parentAuth`).
- [ ] **C10. Делегирование учителю.** Часть студенческих прав — учителю в рамках его классов.
- [ ] **C11. Пер-классовый скоуп прав.** Право на уровне класса (свести к модели content_access). Большая работа.
## Порядок исполнения
A1 → A2 → A3 → A4 → B5 → B6 → B7 → B8 → C9 → C10 → C11. Phase C — отдельными ветками/планом (архитектура).
## Тесты/гочи
- Бэкенд-тесты через `backend/tests/setup.js` (харнесс монтирует /api/permissions). Прогон `node --test`.
- pre-commit гоняет полный backend-набор (baseline 3 Auth + флака «intro» в chemistry8-page под нагрузкой).
- ⛔ эмодзи; коммитить поимённо; fetch перед работой (активны параллельные сессии на master).
## Прогресс (2026-06-03)
- [x] A1 зависимости (requires) — commit 9ac2a61
- [x] A2 гигиена реестра (lint) + ясные метки — b0e385b
- [x] A3 история изменений прав (endpoint + UI) — 7d474b4
- [x] A4 убран role-level token_version bump (нет массового разлогина) — 6bd1532
- Фаза A завершена. Далее по порядку: B5 группы прав → B6 массово к классу → B7 пресеты → B8 временные → C9-11.
- Линт A2 подсветил: ряд teacher-прав (students.invite, sessions.reset, results.export, schedule.manage, templates.public, courses.interactive) и theory.access НЕ enforce-ятся через requirePermission — потенциальные гейты для проверки (отдельно).
## Прогресс — Phase B (2026-06-03)
- [x] B5 группы прав — 0a24a66
- [x] B6 массово по классу — b95b639
- [x] B7 пресеты-профили — 8b495f1
- [x] B8 временные права (expires_at, миграция 053) — a250d15
- Phase A + Phase B ЗАВЕРШЕНЫ. Остаётся Phase C (C9 кастомные роли / C10 делегирование учителю / C11 пер-классовый скоуп) — архитектура, отдельной веткой + обсуждение.