feat(access): доступ к учебникам и экзаменам по классам/ученикам из админ-панели
Модель allowlist (закрыто по умолчанию), правило ученика важнее класса. Управляют админ (все) и учителя (свои классы/ученики). - миграция 040: таблица content_access + непрерывный переход (всем существующим классам открыт текущий контент) - сервис contentAccess: резолвинг доступа, главы наследуют хаб - API /api/access (catalog/targets/rules) для admin+teacher - гейты: каталог учебников, router.param slug/examKey, фильтр tracks - клиентские редиректы на /403 (textbook-tracker, exam-prep boot) - раздел админки «Доступ к учебникам»: классы + ученики (tri-state) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1025,6 +1025,7 @@ window.LS = {
|
||||
getFolderAccess, clearFolderAccess, assignFolder, unassignFolder, getStudentsList,
|
||||
submitWork, resubmitWork, getMySubmissions, getClassSubmissions, reviewSubmission, deleteSubmission, submissionDownloadUrl,
|
||||
getPermissions, setPermission, getUserPermissions, setUserPermission, resetUserPermissions,
|
||||
accessCatalog, accessTargets, accessRules, accessSetRule,
|
||||
getCourseTemplates, saveCourseTemplate, createFromCourseTemplate, deleteCourseTemplate,
|
||||
getLessonTemplates, saveLessonTemplate, createFromLessonTemplate, deleteLessonTemplate,
|
||||
getBookmarks, addBookmark, removeBookmark, removeBookmarkByEntity, checkBookmark,
|
||||
@@ -1288,6 +1289,17 @@ async function getUserPermissions(uid) { return req('GET',
|
||||
async function setUserPermission(uid, permission, enabled) { return req('POST', `/permissions/users/${uid}`, { permission, enabled }); }
|
||||
async function resetUserPermissions(uid, permission) { return req('DELETE', `/permissions/users/${uid}/reset`, permission ? { permission } : undefined); }
|
||||
|
||||
/* ── content access (учебники / экзамены: открыть-закрыть классам/ученикам) ── */
|
||||
async function accessCatalog() { return req('GET', '/access/catalog'); }
|
||||
async function accessTargets() { return req('GET', '/access/targets'); }
|
||||
async function accessRules(content_type, content_ref) {
|
||||
const p = new URLSearchParams({ content_type, content_ref });
|
||||
return req('GET', `/access/rules?${p}`);
|
||||
}
|
||||
async function accessSetRule(content_type, content_ref, scope, target_id, allow) {
|
||||
return req('POST', '/access/rules', { content_type, content_ref, scope, target_id, allow });
|
||||
}
|
||||
|
||||
/* ── notifications ───────────────────────────────────────────────────────── */
|
||||
async function getNotifications() { return req('GET', '/notifications'); }
|
||||
async function markNotifRead(id) { return req('PATCH',`/notifications/${id}/read`); }
|
||||
|
||||
Reference in New Issue
Block a user