fix(features): админ видит и открывает все модули, даже отключённые

Скрытие фич в сайдбаре (и kill-switch геймификации) применялось независимо от роли —
у админа тоже пропадали пункты отключённых модулей. Админ управляет модулями, поэтому
должен видеть и открывать всё.

Добавлен admin-override (_isAdminUser, читает getUser() синхронно из localStorage —
работает и на ранней FOUC-инъекции): для админа _applyFeatureCss чистит <style>-скрытие
и снимает .no-gamification; hideDisabledFeatures выходит до любых скрытий/редиректов;
showBoardIfAllowed показывает доску админу всегда. Поведение для student/teacher не
изменилось. Verified vm-смоук на реальном api.js 10/10.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-23 13:03:09 +03:00
parent 748b0aaab1
commit a7f2ae9937
+20 -2
View File
@@ -863,10 +863,24 @@ const FEATURE_WIDGETS = {
pet: ['#hc-pet'],
textbooks: ['#hc-read'],
};
/* Админ видит и имеет доступ ко ВСЕМУ, даже к отключённым модулям (он ими управляет).
Поэтому для админа никакие скрытия/редиректы фич не применяются. getUser() читает
localStorage синхронно (определён в начале файла) — работает и на ранней sync-инъекции. */
function _isAdminUser() {
try { return getUser()?.role === 'admin'; } catch { return false; }
}
/* Инъекция CSS, прячущего отключённые фичи. Ставится синхронно из localStorage-кэша
на ранней загрузке (ДО построения сайдбара/виджетов) — против мигания (FOUC),
затем обновляется по свежему /api/features. */
function _applyFeatureCss(feats) {
// Админ — без скрытий: чистим <style> и снимаем kill-switch геймификации.
if (_isAdminUser()) {
const elA = document.getElementById('ls-feat-hide');
if (elA) elA.textContent = '';
document.documentElement.classList.remove('no-gamification');
return;
}
const sels = [];
if (feats) {
for (const [key, hrefs] of Object.entries(FEATURE_HREFS)) {
@@ -925,18 +939,22 @@ async function showBoardIfAllowed() {
if (!el) return;
const user = getUser();
if (!user) return;
// Админ видит доску всегда (даже если фича отключена) — он ею управляет.
if (user.role === 'admin') { el.style.display = ''; return; }
const feats = await loadFeatures();
// Фича выключена (глобально или для класса) → доску не показываем, даже учителю/админу.
// Фича выключена (глобально или для класса) → доску не показываем, даже учителю.
// Эта функция зовётся напрямую на многих страницах, поэтому проверка ОБЯЗАТЕЛЬНА,
// иначе она перекрывает скрытие из hideDisabledFeatures().
if (feats.board === false) { el.style.display = 'none'; return; }
if (user.role === 'teacher' || user.role === 'admin') { el.style.display = ''; return; }
if (user.role === 'teacher') { el.style.display = ''; return; }
// Student: check if in a class
if (!feats._no_class) el.style.display = '';
}
async function hideDisabledFeatures() {
const feats = await loadFeatures(); // loadFeatures уже вызвал _applyFeatureCss (визуальное скрытие)
// Админ видит и открывает всё — никаких скрытий, редиректов и схлопывания групп.
if (_isAdminUser()) return;
// Редирект со страницы отключённой фичи (CSS прячет ссылки, а тут уводим со страницы).
for (const [key, hrefs] of Object.entries(FEATURE_HREFS)) {
if (feats[key] === false) {