v0.5.142: URL-имперсонация, убраны старые ENV

This commit is contained in:
2026-06-16 05:53:31 +04:00
parent eba1b4974e
commit 9e3ba1c97c
3 changed files with 38 additions and 51 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ipwhitelist", "name": "ipwhitelist",
"version": "0.5.141", "version": "0.5.142",
"description": "IP WhiteList microservice for cloud provider", "description": "IP WhiteList microservice for cloud provider",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
+1 -1
View File
@@ -9,7 +9,7 @@
// ═══════════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════════
module.exports = { module.exports = {
version: '0.5.141', version: '0.5.142',
// ── IAM ────────────────────────────────────────────────────────────────── // ── IAM ──────────────────────────────────────────────────────────────────
iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user', iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user',
+36 -49
View File
@@ -1,73 +1,60 @@
// ═══════════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════════
// V2 — Имперсонация (IAM + тестовый режим через ENV) // V2 — Имперсонация (IAM + URL-режим)
// //
// ЭТО: middleware — имитирует IAM-имперсонацию для тестов. // ЭТО: middleware — подмена сессии при имперсонации.
// НЕ: жёсткая логика в resolveContext или user/index.js. // НЕ: жёсткая логика в resolveContext или user/index.js.
// //
// ТЕСТОВЫЙ РЕЖИМ (если задан IMPERSONATION_TARGET): // IAM-имперсонация: если сессия уже содержит isImpersonated=true → не трогаем.
// При входе IMPERSONATION_ORIGINAL все данные сессии заменяются на TARGET. //
// Полная имитация IAM-имперсонации: email, profiles, clientId — всё от таргета. // URL-имперсонация: для разрешённых пользователей (IMPERSONATION_ALLOWED_USERS).
// /v2/app?impersonate=email&company=W***
// Полная подмена сессии: email, clientId, profiles — всё от таргета.
// //
// ENV: // ENV:
// IMPERSONATION_ORIGINAL — email админа (кто имперсонирует) // IMPERSONATION_ALLOWED_USERS — emails через запятую (кому можно)
// IMPERSONATION_TARGET — email юзера (кого имперсонируют) ← тест
// IMPERSONATION_COMPANY — W-номер основной компании таргета
// IMPERSONATION_EXTRA_COMPANIES — доп. W-номера через запятую
// ═══════════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════════
const ORIGINAL_EMAIL = process.env.IMPERSONATION_ORIGINAL || ''; const ALLOWED_USERS = new Set(
const TARGET_EMAIL = process.env.IMPERSONATION_TARGET || ''; (process.env.IMPERSONATION_ALLOWED_USERS || '')
const MAIN_COMPANY = process.env.IMPERSONATION_COMPANY || ''; .split(',').map(s => s.trim()).filter(Boolean)
const EXTRA_COMPANIES = (process.env.IMPERSONATION_EXTRA_COMPANIES || '') );
.split(',').map(s => s.trim()).filter(Boolean);
const ALL_TARGET_CIDS = [...new Set([MAIN_COMPANY, ...EXTRA_COMPANIES].filter(Boolean))];
function enhanceImpersonation(req, res, next) { function enhanceImpersonation(req, res, next) {
const u = req.session && req.session.user; const u = req.session && req.session.user;
if (!u) return next(); if (!u) return next();
// ── IAM-имперсонация (уже есть в сессии) — просто добавляем компании ── // ── IAM-имперсонация уже в сессии, не трогаем ────────────────────
if (u.isImpersonated && u.originalUserEmail === ORIGINAL_EMAIL) { if (u.isImpersonated) return next();
addExtraCompanies(u);
return next(); // ── URL-имперсонация ───────────────────────────────────────────────
} const targetEmail = req.query.impersonate;
const targetCompany = req.query.company;
if (targetEmail && targetCompany && ALLOWED_USERS.has(u.email)) {
// Сохраняем оригинал
const origEmail = u.email;
const origFio = u.fio;
// ── Тестовый режим: нужны все три — ORIGINAL, TARGET, COMPANY ────────
if (ORIGINAL_EMAIL && TARGET_EMAIL && MAIN_COMPANY && u.email === ORIGINAL_EMAIL) {
// Подменяем ВСЕ данные на таргета (как делает IAM) // Подменяем ВСЕ данные на таргета (как делает IAM)
u.email = TARGET_EMAIL; u.email = targetEmail;
u.clientId = MAIN_COMPANY; u.clientId = targetCompany;
u.activeClientId = u.activeClientId || MAIN_COMPANY; u.activeClientId = targetCompany;
u.allClientIds = ALL_TARGET_CIDS; u.allClientIds = [targetCompany];
u.companyName = MAIN_COMPANY; u.companyName = targetCompany;
u.isImpersonated = true; u.isImpersonated = true;
u.impersonatedCompanyId = MAIN_COMPANY; u.originalUserEmail = origEmail;
u.originalUserEmail = ORIGINAL_EMAIL; u.originalUserFullName = origFio ? (origFio.fullName || '') : '';
u.originalUserFullName = u.fio ? (u.fio.fullName || '') : ''; u.impersonatedCompanyId = targetCompany;
u.fio = null; u.fio = null;
u.profiles = ALL_TARGET_CIDS.map(cid => ({ u.profiles = [{
client_id: cid, client_id: targetCompany,
company_name: cid, company_name: targetCompany,
is_active_profile: cid === MAIN_COMPANY, is_active_profile: true,
})); }];
return next();
} }
// ── Не имперсонация — ничего не делаем ──────────────────────────────
next(); next();
} }
function addExtraCompanies(u) {
if (!ALL_TARGET_CIDS.length) return;
const current = u.allClientIds || [];
u.allClientIds = [...new Set([...current, ...ALL_TARGET_CIDS])].filter(Boolean);
if (!u.profiles) u.profiles = [];
for (const cid of ALL_TARGET_CIDS) {
if (!u.profiles.find(p => p.client_id === cid))
u.profiles.push({ client_id: cid, company_name: cid, is_active_profile: false });
}
}
module.exports = { enhanceImpersonation }; module.exports = { enhanceImpersonation };