feat(access): Фаза 2c — история правил + пресет «копировать доступ из класса»

История: GET /api/access/log (admin-only) — кто/когда открыл/закрыл/сбросил
правило для контента (из admin_audit_log, имена классов/учеников резолвятся).
Клиент LS.accessLog; в режиме «По контенту» — кнопка «История изменений».
Пресет: в режиме «По классу» — «Скопировать доступ из класса [выбор]» (дополняет
текущие правила открытыми правилами класса-источника). Тест: история (admin
видит запись, учителю 403). content-access 13/13.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-03 13:55:02 +03:00
parent 11ec350dfa
commit b702b04ed2
4 changed files with 102 additions and 2 deletions
+5 -1
View File
@@ -1034,7 +1034,7 @@ window.LS = {
getFolderAccess, clearFolderAccess, assignFolder, unassignFolder, getStudentsList,
submitWork, resubmitWork, getMySubmissions, getClassSubmissions, reviewSubmission, deleteSubmission, submissionDownloadUrl,
getPermissions, setPermission, getUserPermissions, setUserPermission, resetUserPermissions,
accessCatalog, accessTargets, accessSummary, accessClassOpen, accessMatrix, accessRules, accessSetRule,
accessCatalog, accessTargets, accessSummary, accessClassOpen, accessMatrix, accessLog, accessRules, accessSetRule,
getCourseTemplates, saveCourseTemplate, createFromCourseTemplate, deleteCourseTemplate,
getLessonTemplates, saveLessonTemplate, createFromLessonTemplate, deleteLessonTemplate,
getBookmarks, addBookmark, removeBookmark, removeBookmarkByEntity, checkBookmark,
@@ -1306,6 +1306,10 @@ async function accessTargets() { return req('GET', '/access/targets'); }
async function accessSummary() { return req('GET', '/access/summary'); }
async function accessClassOpen(classId) { return req('GET', `/access/class/${classId}`); }
async function accessMatrix() { return req('GET', '/access/matrix'); }
async function accessLog(content_type, content_ref) {
const p = new URLSearchParams({ content_type, content_ref });
return req('GET', `/access/log?${p}`);
}
async function accessRules(content_type, content_ref) {
const p = new URLSearchParams({ content_type, content_ref });
return req('GET', `/access/rules?${p}`);