feat(admin): журнал событий безопасности (Tier 1-2) + аудит чувствительных действий (Tier 3)

- security_events (миграция 047) + utils/securityLog.js (defensive, lazy stmt)
- Tier 1: login.success/fail, register, password.change в authController
- Tier 2: 403 (роль/разрешение) в middleware/auth, rate_limited в rateLimit
- Tier 3: audit() на выдачу доступа (access), начисление/сброс XP (gam), модерацию аватаров
- API GET/DELETE /api/admin/security-log (фильтр по категории + поиск, прунинг по дням)
- Frontend: вкладка «Безопасность» в admin.html + loadSecurityLog, расширены ACTION_LABELS

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-01 15:28:21 +03:00
parent 30626e0928
commit fe122b7681
12 changed files with 262 additions and 2 deletions
+3
View File
@@ -7,6 +7,7 @@
const router = require('express').Router();
const db = require('../db/db');
const { authMiddleware, requireRole } = require('../middleware/auth');
const { audit } = require('../utils/audit');
router.use(authMiddleware);
router.use(requireRole('admin', 'teacher'));
@@ -198,6 +199,7 @@ router.post('/rules', (req, res) => {
db.prepare(`DELETE FROM content_access
WHERE content_type = ? AND content_ref = ? AND scope = ? AND target_id = ?`)
.run(content_type, content_ref, scope, tid);
audit(req, 'access.inherit', `${content_type}:${content_ref}`, `${scope}:${tid}`);
return res.json({ ok: true, allow: null });
}
@@ -209,6 +211,7 @@ router.post('/rules', (req, res) => {
DO UPDATE SET allow = excluded.allow, created_by = excluded.created_by, created_at = datetime('now')
`).run(content_type, content_ref, scope, tid, allow, req.user.id);
audit(req, allow ? 'access.grant' : 'access.deny', `${content_type}:${content_ref}`, `${scope}:${tid}`);
res.json({ ok: true, allow });
});