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
+2 -1
View File
@@ -44,8 +44,9 @@ function requireRole(...roles) {
/* ── Разрешено ли ОДНО право: user override → role override → дефолт реестра ── */
function isEnabled(uid, role, key) {
// Просроченный временный оверрайд (expires_at в прошлом) игнорируем — наследуем роль.
const userRow = db.prepare(
'SELECT enabled FROM user_permissions WHERE user_id = ? AND permission = ?'
"SELECT enabled FROM user_permissions WHERE user_id = ? AND permission = ? AND (expires_at IS NULL OR expires_at > datetime('now'))"
).get(uid, key);
if (userRow !== undefined) return userRow.enabled === 1;
const roleRow = db.prepare(