diff --git a/backend/src/permissions/registry.js b/backend/src/permissions/registry.js index f107080..f34403e 100644 --- a/backend/src/permissions/registry.js +++ b/backend/src/permissions/registry.js @@ -144,14 +144,14 @@ const PERMISSIONS = { }, 'theory.access': { role: 'student', roles: ['student', 'free_student'], default: 1, - label: 'Доступ к теории', - desc: 'Просматривать теоретические курсы и уроки', + label: 'Раздел теории доступен роли', + desc: 'Включает раздел теории для роли. Какие именно курсы видны — настраивается по классам в «Доступ · контент»', requireConfirmOff: true, }, 'simulations.access': { role: 'student', roles: ['student', 'free_student'], default: 1, - label: 'Доступ к симуляциям', - desc: 'Открывать лабораторию с физическими, химическими и биологическими симуляциями', + label: 'Лаборатория доступна роли', + desc: 'Включает раздел лаборатории для роли. Какие именно симуляции видны — настраивается по классам в «Доступ · контент»', requireConfirmOff: true, }, 'simulations.quiz': { diff --git a/backend/tests/permissions-registry.test.js b/backend/tests/permissions-registry.test.js new file mode 100644 index 0000000..b99be91 --- /dev/null +++ b/backend/tests/permissions-registry.test.js @@ -0,0 +1,55 @@ +'use strict'; +/** + * Гигиена реестра прав (A2): каждый ключ, переданный в requirePermission('…') / + * perm('…') в коде backend/src, ДОЛЖЕН существовать в registry.js. Ловит опечатки + * и дрейф (раньше perm() падал на старте, но «сырой» requirePermission — нет). + * Дополнительно: список ключей реестра, не используемых в requirePermission (это + * НЕ ошибка — многие студенческие ключи гейтятся на клиенте через /me — просто + * выводим для обзора). + */ +const { describe, it } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const registry = require('../src/permissions/registry'); + +const SRC = path.join(__dirname, '..', 'src'); +const USE_RE = /\b(?:requirePermission|perm)\(\s*['"]([\w.]+)['"]/g; + +function walk(dir, out = []) { + for (const e of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, e.name); + if (e.isDirectory()) walk(p, out); + else if (e.isFile() && e.name.endsWith('.js')) out.push(p); + } + return out; +} + +describe('permissions registry hygiene', () => { + const files = walk(SRC); + const used = new Map(); // key -> first file where seen + for (const f of files) { + const txt = fs.readFileSync(f, 'utf8'); + let m; + while ((m = USE_RE.exec(txt)) !== null) { + if (!used.has(m[1])) used.set(m[1], path.relative(SRC, f)); + } + } + + it('все ключи requirePermission/perm(...) в коде есть в реестре', () => { + const unknown = [...used.entries()].filter(([k]) => !registry.isKnown(k)); + assert.equal(unknown.length, 0, + 'неизвестные ключи прав (опечатка / не добавлены в registry): ' + + unknown.map(([k, f]) => `${k} (${f})`).join(', ')); + }); + + it('обзор: ключи реестра, не используемые в requirePermission (информативно, не ошибка)', () => { + const unused = registry.listKeys().filter(k => !used.has(k)); + // Не падаем: часть прав enforce-ится на клиенте через /permissions/me. + if (unused.length) { + // eslint-disable-next-line no-console + console.log('[perm-hygiene] не используются в requirePermission (ок, могут гейтиться на клиенте):', unused.join(', ')); + } + assert.ok(Array.isArray(unused)); + }); +});