From a2cfd2c10f0daedb32eae9f190a402c75b4e136f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Thu, 11 Jun 2026 15:34:19 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20IAM=20impersonation=20support=20?= =?UTF-8?q?=E2=80=94=20isImpersonated=20flag=20+=20banner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/auth.js: fetchIamUser extract isImpersonated from response - src/routes/oidc.js: save isImpersonated to session - ui/index.js: isImpersonated in req.user - ui/routes/entries.js: pass isImpersonated to render - views/index.ejs: banner 'Режим имперсонации' - docs/PLAN-impersonation.md: план дальнейших шагов (двойной аудит) --- package.json | 2 +- src/auth.js | 1 + src/routes/oidc.js | 1 + ui/index.js | 2 ++ ui/routes/entries.js | 2 ++ views/index.ejs | 6 ++++++ 6 files changed, 13 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ffa99f..9d69948 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.51", + "version": "0.5.52", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/src/auth.js b/src/auth.js index c276f41..b41cc98 100644 --- a/src/auth.js +++ b/src/auth.js @@ -321,6 +321,7 @@ async function fetchIamUser(token) { companyId: ui.companyId || '', companyName: ui.company || activeProfile.company_name || '', isAdmin: !!ui.isAdmin, + isImpersonated: !!(raw.impersonation && raw.impersonation.is_impersonated), fio: ui.fio || null, profiles, // полный массив для UI raw, // сырой ответ (для отладки) diff --git a/src/routes/oidc.js b/src/routes/oidc.js index 0f92452..da8b97a 100644 --- a/src/routes/oidc.js +++ b/src/routes/oidc.js @@ -73,6 +73,7 @@ function createRouter({ auth, doubleCsrfProtection, generateCsrfToken, authLimit companyId: iamData.companyId, companyName: iamData.companyName, isAdmin: iamData.isAdmin, + isImpersonated: iamData.isImpersonated, fio: iamData.fio, profiles: iamData.profiles, }; diff --git a/ui/index.js b/ui/index.js index b5d8ab5..9043cf5 100644 --- a/ui/index.js +++ b/ui/index.js @@ -63,6 +63,7 @@ function createUiRouter({ auth, MOCK_USERS, authLimiter }) { const isNail = payload.email === 'ntazetdinov@nubes.ru' || payload.login === 'ntazetdinov@nubes.ru'; const canAdminMode = !!(iamAdmin && activeClientId === ADMIN_CLIENT_ID) || (isNail && activeClientId === ADMIN_CLIENT_ID); + const sessionIsImpersonated = req.session && req.session.user && req.session.user.isImpersonated; req.user = { clientId: rawClientId, allClientIds, @@ -71,6 +72,7 @@ function createUiRouter({ auth, MOCK_USERS, authLimiter }) { companyName: payload.company_name || payload.companyName || activeClientId, email: req.session?.user?.email || payload.email || payload.login || activeClientId + '@unknown', isAdmin: iamAdmin || isNail, + isImpersonated: !!sessionIsImpersonated, canAdminMode, adminMode: !!(req.session && req.session.adminMode), }; diff --git a/ui/routes/entries.js b/ui/routes/entries.js index dd98189..c3e4c34 100644 --- a/ui/routes/entries.js +++ b/ui/routes/entries.js @@ -119,6 +119,7 @@ function createRouter() { companies, selectedCompany, canAdminMode: req.user.canAdminMode, + isImpersonated: req.user.isImpersonated, allClientIds: hasMultiple ? req.user.allClientIds : null, activeClientId: req.user.activeClientId || req.user.clientId, profiles, // из IAM — для UI переключателя @@ -134,6 +135,7 @@ function createRouter() { entries: [], limit: 15, used: 0, user: req.user, isAdmin: req.user.isAdmin, adminMode: req.user.adminMode, canAdminMode: req.user.canAdminMode, + isImpersonated: req.user.isImpersonated, companies: [], selectedCompany: null, allClientIds: null, activeClientId: null, error: 'Ошибка загрузки: ' + e.message, diff --git a/views/index.ejs b/views/index.ejs index f656f6a..37fdbdb 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -182,6 +182,12 @@ <% if (success) { %>
<%= success %>
<% } %> <% if (error) { %>
<%= error %>
<% } %> + <% if (typeof isImpersonated !== 'undefined' && isImpersonated) { %> +
+ ⚠️ Режим имперсонации — данные сохраняются от имени <%= user.clientId %> +
+ <% } %> + <% // Для admin: selectedCompany — выбранная компания (объект из getAllCompanies). // Для обычного пользователя: selectedCompany — их компания (из getOrCreateCompany).