From 4f1f64dd6c4b8d8f1b9aa71c0306149e37a1a108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Thu, 11 Jun 2026 11:08:03 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20adminMode=20=E2=80=94=20=D1=87=D0=B5?= =?UTF-8?q?=D0=BA-=D0=B1=D0=BE=D0=BA=D1=81=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B0=D0=B4?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D1=81=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Шаг 1: /toggle-admin роут в ui/routes/auth.js - переключает req.session.adminMode - canAdmin = isAdmin || clientId === WZ01112 (временно) Шаг 2: resolveUser в ui/index.js - req.user.adminMode из req.session.adminMode - isAdmin = IAM.isAdmin || clientId === WZ01112 (временно) Шаг 3: adminMode вместо isAdmin в интерфейсе - ui/routes/entries.js: adminMode решает админский view - ui/routes/admin.js: requireAdmin проверяет adminMode Шаг 4: views/index.ejs - чек-бокс «Администратор» (виден только если isAdmin) - ссылки Аудит/Лимиты видны только при adminMode - селектор компаний — при adminMode --- package.json | 2 +- ui/index.js | 5 ++++- ui/routes/admin.js | 2 +- ui/routes/auth.js | 14 ++++++++++++++ ui/routes/entries.js | 5 +++-- views/index.ejs | 16 ++++++++++++---- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index bd70974..41fc75a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.37", + "version": "0.5.38", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/ui/index.js b/ui/index.js index a230d1c..437e1a4 100644 --- a/ui/index.js +++ b/ui/index.js @@ -58,6 +58,8 @@ function createUiRouter({ auth, MOCK_USERS, authLimiter }) { ? sessionActive : (allClientIds[0] || rawClientId); + // 🔮 isAdmin через IAM, временно: || clientId === WZ01112 + const iamAdmin = req.session && req.session.user && req.session.user.isAdmin; req.user = { clientId: rawClientId, allClientIds, @@ -65,7 +67,8 @@ function createUiRouter({ auth, MOCK_USERS, authLimiter }) { companyId: payload.company_id || payload.companyId || null, companyName: payload.company_name || payload.companyName || activeClientId, email: payload.email || activeClientId + '@unknown', - isAdmin: activeClientId === ADMIN_CLIENT_ID, + isAdmin: iamAdmin || activeClientId === ADMIN_CLIENT_ID, + adminMode: !!(req.session && req.session.adminMode), }; } catch (e) { req.session.destroy(() => diff --git a/ui/routes/admin.js b/ui/routes/admin.js index bef9be4..e2ff011 100644 --- a/ui/routes/admin.js +++ b/ui/routes/admin.js @@ -14,7 +14,7 @@ const { Router } = require('express'); const api = require('../api-client'); function requireAdmin(req, res, next) { - if (!req.user || !req.user.isAdmin) { + if (!req.user || !req.user.adminMode) { return res.status(403).render('error', { status: 403, message: 'Доступ запрещён — требуются права администратора.', diff --git a/ui/routes/auth.js b/ui/routes/auth.js index e9cea81..fd7b85a 100644 --- a/ui/routes/auth.js +++ b/ui/routes/auth.js @@ -166,6 +166,20 @@ function createRouter({ auth, MOCK_USERS, authLimiter }) { res.redirect(returnTo || '/'); }); + // ── Переключатель режима администратора ────────────────────────────── + // 🔮 isAdmin будет из IAM, временно: isAdmin || clientId === WZ01112 + router.post('/toggle-admin', (req, res) => { + const canAdmin = req.session.user && ( + req.session.user.isAdmin || + req.session.user.clientId === (process.env.ADMIN_CLIENT_ID || 'WZ01112') + ); + if (!canAdmin) return res.status(403).send('Forbidden'); + + req.session.adminMode = !req.session.adminMode; + // Редирект туда же откуда пришли + res.redirect(req.get('Referer') || '/'); + }); + // GET /logout router.get('/logout', (req, res) => { req.session.destroy(() => res.redirect('/login')); diff --git a/ui/routes/entries.js b/ui/routes/entries.js index 76567a3..9b0760b 100644 --- a/ui/routes/entries.js +++ b/ui/routes/entries.js @@ -77,7 +77,7 @@ function createRouter() { try { let entries = [], limit = 15, selectedCompany = null, companies = []; - if (req.user.isAdmin) { + if (req.user.adminMode) { const cr = await api.get('/api/v1/companies', token); companies = cr.data.companies || []; @@ -120,6 +120,7 @@ function createRouter() { used: entries.length, user: req.user, isAdmin: req.user.isAdmin, + adminMode: req.user.adminMode, companies, selectedCompany, allClientIds: hasMultiple ? req.user.allClientIds : null, @@ -135,7 +136,7 @@ function createRouter() { } catch (e) { res.render('index', { entries: [], limit: 15, used: 0, - user: req.user, isAdmin: req.user.isAdmin, + user: req.user, isAdmin: req.user.isAdmin, adminMode: req.user.adminMode, companies: [], selectedCompany: null, allClientIds: null, activeClientId: null, error: 'Ошибка загрузки: ' + e.message, diff --git a/views/index.ejs b/views/index.ejs index 0f1b536..3fd9420 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -157,9 +157,17 @@ | Белые списки IP v<%= appVersion %> - + - <% if (isAdmin) { %> + <% if (typeof isAdmin !== 'undefined' && isAdmin) { %> +
+ +
+ <% } %> + <% if (typeof adminMode !== 'undefined' && adminMode) { %> Аудит Лимиты <% } %> @@ -179,8 +187,8 @@ const companyPk = selectedCompany ? selectedCompany.id : null; %> - - <% if (isAdmin && companies) { %> + + <% if (adminMode && companies) { %>