feat(permissions): B8 — временные права (expires_at) с авто-снятием

Миграция 053: user_permissions.expires_at (NULL = бессрочно). Резолвер isEnabled
+ /me + /users/:id игнорируют просроченные оверрайды (наследуют роль); seedDefaults
чистит просроченные строки. setUserPermission принимает days → выдаёт право на
срок (datetime('now','+N days')). API отдаёт expiresAt. Клиент: setUserPermission(...,days).
В модалке прав пользователя — бейдж «до ДАТА» + кнопка «врем.» (выдать на N дней).
Тест: срок хранится/отдаётся, просроченное игнорируется и вычищается. Backend pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-03 14:43:06 +03:00
parent 8b495f1508
commit a250d15f9a
6 changed files with 83 additions and 14 deletions
+1 -1
View File
@@ -1301,7 +1301,7 @@ async function permissionsPresets() { return req('GET',
async function applyClassPreset(classId, preset) { return req('POST', `/permissions/class/${classId}/preset`, { preset }); }
async function setPermission(role, permission, enabled) { return req('POST', '/permissions', { role, permission, enabled }); }
async function getUserPermissions(uid) { return req('GET', `/permissions/users/${uid}`); }
async function setUserPermission(uid, permission, enabled) { return req('POST', `/permissions/users/${uid}`, { permission, enabled }); }
async function setUserPermission(uid, permission, enabled, days) { return req('POST', `/permissions/users/${uid}`, days ? { permission, enabled, days } : { permission, enabled }); }
async function resetUserPermissions(uid, permission) { return req('DELETE', `/permissions/users/${uid}/reset`, permission ? { permission } : undefined); }
/* ── content access (учебники / экзамены: открыть-закрыть классам/ученикам) ── */