feat(permissions): C-4b — админ-UI конструктора ролей + назначение пользователю

Клиент: listRoles/createRole/updateRoleDef/deleteRole/rolePermissions. Во вкладке
«Доступ · роли» — блок «Конструктор ролей»: создать роль (имя-идентификатор +
название + базовые роли чекбоксами), список кастомных ролей, «Настроить права»
(тогглы по группам через getRolePermissions + setPermission под именем роли),
«Удалить» (возврат пользователей на базу). В списке пользователей выпадающий
список ролей теперь включает optgroup «Кастомные роли» (выбор по custom_role);
listUsers отдаёт custom_role. Phase C (произвольные роли) завершена на ветке.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-03 15:26:52 +03:00
parent bdc8bef857
commit 6b148127b6
5 changed files with 123 additions and 5 deletions
+6
View File
@@ -1034,6 +1034,7 @@ window.LS = {
getFolderAccess, clearFolderAccess, assignFolder, unassignFolder, getStudentsList,
submitWork, resubmitWork, getMySubmissions, getClassSubmissions, reviewSubmission, deleteSubmission, submissionDownloadUrl,
getPermissions, permissionsLog, setClassPermission, permissionsPresets, applyClassPreset, setPermission, getUserPermissions, setUserPermission, resetUserPermissions,
listRoles, createRole, updateRoleDef, deleteRole, rolePermissions,
accessCatalog, accessTargets, accessSummary, accessClassOpen, accessMatrix, accessLog, accessRules, accessSetRule,
getCourseTemplates, saveCourseTemplate, createFromCourseTemplate, deleteCourseTemplate,
getLessonTemplates, saveLessonTemplate, createFromLessonTemplate, deleteLessonTemplate,
@@ -1298,6 +1299,11 @@ async function getPermissions() { return req('GET',
async function permissionsLog(userId) { return req('GET', userId ? `/permissions/log?user_id=${userId}` : '/permissions/log'); }
async function setClassPermission(classId, permission, enabled) { return req('POST', `/permissions/class/${classId}/bulk`, { permission, enabled }); }
async function permissionsPresets() { return req('GET', '/permissions/presets'); }
async function listRoles() { return req('GET', '/roles'); }
async function createRole(name, label, baseRoles) { return req('POST', '/roles', { name, label, baseRoles }); }
async function updateRoleDef(name, body) { return req('PUT', `/roles/${encodeURIComponent(name)}`, body); }
async function deleteRole(name) { return req('DELETE', `/roles/${encodeURIComponent(name)}`); }
async function rolePermissions(name) { return req('GET', `/roles/${encodeURIComponent(name)}/permissions`); }
async function applyClassPreset(classId, preset) { return req('POST', `/permissions/class/${classId}/preset`, { preset }); }
async function setPermission(role, permission, enabled) { return req('POST', '/permissions', { role, permission, enabled }); }
async function getUserPermissions(uid) { return req('GET', `/permissions/users/${uid}`); }