'use strict'; /** * Фаза 1c (добавочная модель): видимость курсов по классам через content_access. * GET /api/courses фильтрует список для НЕпривилегированных по allowedRefs(uid,'course'); * admin/teacher видят все. content_ref = courses.id (как TEXT). */ const { describe, it, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { db, getToken, inject, cleanup } = require('./setup'); after(() => cleanup()); describe('course access (per-class)', () => { let teacher, student, classId, courseId; before(async () => { teacher = await getToken('teacher'); student = await getToken('student'); const r = db.prepare( `INSERT INTO courses (subject_slug, title, is_published, created_by) VALUES ('math','Acc Course',1,?)` ).run(teacher.userId); courseId = Number(r.lastInsertRowid); const cr = await inject('POST', '/api/classes', { name: 'CourseAcc Class' }, teacher.token); assert.ok(cr.status < 300, JSON.stringify(cr.body)); classId = db.prepare('SELECT id FROM classes WHERE name = ?').get('CourseAcc Class').id; await inject('POST', `/api/classes/${classId}/members`, { user_id: student.userId }, teacher.token); }); const has = (body, id) => (Array.isArray(body) ? body : []).some(c => c.id === id); it('ученик без правил не видит опубликованный курс (allowlist)', async () => { const r = await inject('GET', '/api/courses', null, student.token); assert.equal(r.status, 200); assert.ok(!has(r.body, courseId), 'курс скрыт без правила'); }); it('teacher видит курс (privileged)', async () => { const r = await inject('GET', '/api/courses', null, teacher.token); assert.ok(has(r.body, courseId)); }); it('открытый классу курс виден ученику', async () => { db.prepare(`INSERT OR IGNORE INTO content_access (content_type,content_ref,scope,target_id,allow) VALUES ('course',?, 'class',?,1)`).run(String(courseId), classId); const r = await inject('GET', '/api/courses', null, student.token); assert.ok(has(r.body, courseId), 'курс виден после открытия классу'); }); it('каталог админки включает курсы', async () => { const r = await inject('GET', '/api/access/catalog', null, teacher.token); assert.ok(Array.isArray(r.body.courses), 'есть массив courses'); assert.ok(r.body.courses.some(c => Number(c.id) === courseId), 'наш курс в каталоге'); }); });