'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)); }); });