fix(features): админ открывает отключённые модули — пейдж-гейты уважают admin-override

Причина бага «из админа конструктор симуляций редиректит на дашборд»: у sim-builder.html
свой пейдж-гейт, который при feature_sim_builder=false уводил на /dashboard НЕЗАВИСИМО от
роли (мой прошлый admin-override был только в hideDisabledFeatures, а этот гейт его не знал).

Тот же недочёт нашёлся ещё у 3 страниц с собственным фича-редиректом (на /403):
collection.html, knowledge-map.html, red-book.html. Во все 4 добавил обход для админа
(админ управляет модулями → видит и открывает всё, даже отключённое) — согласно правилу
admin-override. Поведение для ученика/учителя не изменилось.

node --check инлайна всех 4 страниц — OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-23 16:59:51 +03:00
parent efba722977
commit 3898080f04
4 changed files with 5 additions and 4 deletions
+1 -1
View File
@@ -365,7 +365,7 @@
LS.sidebar?.init(); LS.sidebar?.init();
lucide.createIcons(); lucide.createIcons();
const feats = await LS.loadFeatures(); const feats = await LS.loadFeatures();
if (feats.collection === false) { window.location.replace('/403'); return; } if (feats.collection === false && user?.role !== 'admin') { window.location.replace('/403'); return; }
LS.hideDisabledFeatures?.(); LS.hideDisabledFeatures?.();
await loadCollection(); await loadCollection();
})(); })();
+1 -1
View File
@@ -585,7 +585,7 @@ let _dashOffset = 0; // animated dash offset for link flow
LS.notif.init(); LS.notif.init();
lucide.createIcons(); lucide.createIcons();
const feats = await LS.loadFeatures(); const feats = await LS.loadFeatures();
if (feats.knowledge_map === false) { window.location.replace('/403'); return; } if (feats.knowledge_map === false && user?.role !== 'admin') { window.location.replace('/403'); return; }
LS.hideDisabledFeatures?.(); LS.hideDisabledFeatures?.();
document.querySelector('.sb-toggle')?.addEventListener('click', () => { document.querySelector('.sb-toggle')?.addEventListener('click', () => {
+1 -1
View File
@@ -792,7 +792,7 @@ const XP_MAP = { CR: 50, EN: 40, VU: 30, NT: 20, LC: 10 };
async function init() { async function init() {
lucide.createIcons(); lucide.createIcons();
const feats = await LS.loadFeatures().catch(() => ({})); const feats = await LS.loadFeatures().catch(() => ({}));
if (feats.red_book === false) { window.location.replace('/403'); return; } if (feats.red_book === false && LS.getUser()?.role !== 'admin') { window.location.replace('/403'); return; }
LS.hideDisabledFeatures?.(); LS.hideDisabledFeatures?.();
// Auth (sidebar) // Auth (sidebar)
+2 -1
View File
@@ -196,7 +196,8 @@
if (!(ip.isTeacher || ip.isAdmin)) { location.href = '/dashboard'; return; } if (!(ip.isTeacher || ip.isAdmin)) { location.href = '/dashboard'; return; }
// Фича-гейт: «Конструктор симуляций» можно отключить в админке (feature_sim_builder_enabled). // Фича-гейт: «Конструктор симуляций» можно отключить в админке (feature_sim_builder_enabled).
if (LS.loadFeatures) { // Админ имеет доступ всегда (он управляет модулями) — для него гейт не срабатывает.
if (LS.loadFeatures && !ip.isAdmin) {
LS.loadFeatures().then(function (feats) { LS.loadFeatures().then(function (feats) {
if (feats && feats.sim_builder === false) { LS.toast && LS.toast('Конструктор симуляций отключён', 'warn'); location.href = '/dashboard'; } if (feats && feats.sim_builder === false) { LS.toast && LS.toast('Конструктор симуляций отключён', 'warn'); location.href = '/dashboard'; }
}).catch(function () {}); }).catch(function () {});