feat(permissions): C-2 — присвоение кастомной роли пользователю (users.custom_role)

Миграция 055: ADD COLUMN users.custom_role (безопасно, без пересборки users).
Модель: users.role = функциональная база (встроенная, CHECK ок, драйвит ветки
контроллеров и резолв прав), users.custom_role = имя кастомной роли. updateRole
(PATCH /api/admin/users/:id/role) принимает кастомные роли → ставит base_roles[0]
как базу + custom_role=имя; встроенная → custom_role=NULL; неизвестная → 400.
authMiddleware/optionalAuth читают custom_role → req.user.customRole; requireRole
расширяет до effectiveRoles(customRole||role). Тесты custom-roles 7/7; backend без регрессий.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-03 15:03:41 +03:00
parent 5aa2dd1a4b
commit 7cdb2e2af2
4 changed files with 66 additions and 12 deletions
@@ -0,0 +1,10 @@
-- 055_user_custom_role.sql
-- Phase C, Stage C-2 — присвоение кастомной роли пользователю.
-- users.role в канон-схеме имеет CHECK (admin/teacher/student/free_student) и
-- безопасно пересобрать users нельзя (FK многих таблиц, миграции в транзакции).
-- Поэтому кастомную роль храним отдельной колонкой: users.role = функциональная
-- БАЗА (встроенная роль для веток контроллеров и резолва прав), users.custom_role
-- = имя кастомной роли (для гейтов через effectiveRoles + метка + C-3 пер-ролевые права).
-- NULL = обычная встроенная роль.
ALTER TABLE users ADD COLUMN custom_role TEXT;