Редагування ролей через UI¶
Шлях: ERP → Адмін-інструменти → Матриця ролей.
Доступ: лише is_tenant_admin / is_superuser (endpoint IsTenantAdmin).
Що видно¶
Зведена таблиця:
- Рядки — кожна entity_code, що зустрічається у будь-якій ролі цього тенанта (включно з псевдо-entities reports/print/etc.).
- Колонки — усі ролі тенанта (відсортовано: tenant_admin → решта по алфавіту).
- Клітинки — 5 чекбоксів V C U D P (view / create / update / delete / post).
Special cases:
- Колонка tenant_admin — 🔒 локована. Це wildcard роль, у матриці не виражається.
- Клітинка з фіолетовою "A" + замком — каталоговий wildcard 'all' для цієї пари (entity, role). Не редагується через матрицю — тільки через каталог.
- Wildcard роль ((*, 'all') десь у наборі) — показується окремим Alert зверху, не як рядок.
Робочий flow¶
- Reload — отримати поточний стан з БД
- Клікнути будь-який чекбокс → з'являється жовтий банер «Незбережені зміни в:
<role_code>» - Зберегти (N) — пише у БД (PATCH /admin/roles/
<code>/permissions/ по кожній зміненій ролі) - Скасувати зміни — повертає до останньо завантаженого стану (без HTTP-запиту)
- Скинути до каталогу — повне відкочування ВСІХ ролей до Python-каталога (з підтвердженням)
Filter¶
Поле Фільтр за entity — ширше substring-match по entity_code. Зручно коли треба знайти всі рядки, що стосуються invoice'у:
- ввести invoice → побачиш invoices, purchaseInvoices, purchaseInvoiceLines, goodsShipments (...не зовсім invoice, але substring збігається).
Save семантика¶
Save проходиться по списку dirtyRoles (ролі з відмінністю від snapshot) і викликає для кожної:
PATCH /api/v1/admin/roles/<code>/permissions/
{ "permissions": [{"entity_code": "...", "action": "..."}, ...] }
Backend (RolePermissionsView) виконує: 1. Валідація action ∈ {view, create, update, delete, post, all} 2. Валідація entity_code не пустий 3. Дедуплікація tuples 4. Атомарна заміна усіх RolePermission цієї ролі (delete + bulk_create) 5. Повертає оновлену роль із новим набором permissions
Гарантії:
- tenant_admin — 400 (заборонено редагувати wildcard роль)
- Невідомий action → 400 з переліком valid choices
- Не-admin → 403
Reset to catalog¶
Кнопка "Скинути до каталогу" → confirm dialog → POST /admin/roles/reapply/ → виконує apply_system_roles(tenant):
- delete всі RolePermission для системних ролей
- bulk_create з даних SYSTEM_ROLES (Python module)
- result: 14 ролей × catalog perms
Це rollback, а не sync. Тобто:
- ✅ Працює: повернути після помилкового редагування
- ✅ Працює: підтягнути зміни з оновленого role_catalog.py (наприклад, я зробив правки в коді — ти тиснеш кнопку)
- ❌ Не працює як «push to code»: твої правки через UI зникають, не зберігаються у Python-каталог
Коли тиснути «Скинути»¶
| Сценарій | Що зробити |
|---|---|
| Хочу повернути одну роль до дефолтів | Кнопка "Скасувати зміни" (працює лише до Save) АБО Reset (відкочує всі ролі) |
Я (розробник) додав entity у role_catalog.py — як побачити в UI? |
"Скинути до каталогу" |
| Я (тенант-адмін) додав права для кастомного use-case | НЕ тискай Reset — він знесе твої правки. Зберігай з Save і не чіпай Reset |
| Хтось через Django admin наплутав permissions | Reset відновить до коду |
Відсутні фічі (gaps)¶
- Per-role reset (відкатити лише одну роль до каталога) — поки немає. Тільки full Reset усіх.
- Створення нових ролей через UI — поки немає. Тільки edit існуючих 14 системних.
- Видалення / перейменування ролей — поки немає (бо вони з каталога).
- Audit log змін — UI не пише AuditLog коли тенант-адмін править матрицю. У майбутньому — бажано.
- Додавання нових entity-рядків — лише існуючі. Якщо треба надати роль доступ до сутності, якої немає в матриці, треба:
- або додати в каталог через Python (development)
- або зачекати поки інша роль/код матиме цю entity → тоді з'явиться рядок
Усе вище — у backlog. Скажи коли потрібно — зробимо.
Relation до useActivePermissions¶
Зміни через матрицю — миттєво відображаються у БД. Але залогінені користувачі продовжують бачити старі права у своєму кешованому useAuthStore.user.permissions доки не перелогіняться (або не зробимо invalidate current-user query після Save).
Workaround: попроси юзера перелогінитись для тесту, або вручну useAuthStore.getState().logout() → login. У майбутньому — додамо invalidation з боку фронту.
API endpoints¶
| Метод | URL | Permission | Що робить |
|---|---|---|---|
| GET | /api/v1/admin/roles/ |
IsTenantAdmin | Повертає всі ролі тенанта з permissions |
| POST | /api/v1/admin/roles/reapply/ |
IsTenantAdmin | apply_system_roles → відкат до каталога |
| PATCH | /api/v1/admin/roles/<code>/permissions/ |
IsTenantAdmin | Replace permissions list для ролі |
| GET | /api/v1/admin/users/<id>/roles/ |
IsTenantAdmin | Список ролей юзера |
| POST | /api/v1/admin/users/<id>/roles/ |
IsTenantAdmin | Replace user→role assignments |
| DELETE | /api/v1/admin/users/<id>/roles/<code>/ |
IsTenantAdmin | Зняти одну роль |
Per-user role management — окрема секція в Admin Tools → Users → drawer "Ролі".