feat(permissions): C-4a — API конструктора ролей (/api/roles, admin)
rolesController + routes/roles (admin, inline guards): GET список (с числом пользователей), POST создать кастомную роль (имя-идентификатор + метка + base_roles; засев прав из функциональной базы), PUT изменить, DELETE удалить (пользователей возвращает на базу), GET /:name/permissions (эффективная карта база+оверлей + defs). setPermission теперь принимает кастомные роли (ключ валидируется по базе, хранится под именем роли). Смонтировано в server.js + тест-харнесс. Тест roles-api 5/5. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,9 +38,21 @@ function getPermissions(_req, res) {
|
||||
/* ── POST /api/permissions { role, permission, enabled } ─────────────── */
|
||||
function setPermission(req, res) {
|
||||
const { role, permission, enabled } = req.body;
|
||||
if (!['teacher', 'student'].includes(role))
|
||||
return res.status(400).json({ error: 'Invalid role' });
|
||||
if (!ALL_PERMISSIONS.find(p => p.key === permission && p.role === role))
|
||||
// Встроенные конфигурируемые роли — напрямую; кастомная роль — ключи валидируем
|
||||
// по её функциональной базе, но храним под именем роли.
|
||||
let keyRole;
|
||||
if (['teacher', 'student'].includes(role)) {
|
||||
keyRole = role;
|
||||
} else {
|
||||
let cr = null;
|
||||
try { cr = db.prepare('SELECT base_roles, is_builtin FROM roles WHERE name = ?').get(role); } catch (_e) { cr = null; }
|
||||
if (!cr || cr.is_builtin) return res.status(400).json({ error: 'Invalid role' });
|
||||
let bases = [];
|
||||
try { bases = JSON.parse(cr.base_roles || '[]'); } catch (_e) { bases = []; }
|
||||
const primary = bases.find(b => ['teacher', 'student', 'free_student'].includes(b)) || 'student';
|
||||
keyRole = primary === 'free_student' ? 'student' : primary;
|
||||
}
|
||||
if (!ALL_PERMISSIONS.find(p => p.key === permission && p.role === keyRole))
|
||||
return res.status(400).json({ error: 'Unknown permission' });
|
||||
// Серверное применение прав — ЖИВОЕ: requirePermission() читает role_permissions
|
||||
// из БД на каждый запрос (auth.js). Поэтому role-level изменение НЕ инвалидирует
|
||||
|
||||
Reference in New Issue
Block a user