v0.6.12: полный санитайзер IAM в resolveContext — защита от null/undefined/говна

This commit is contained in:
2026-06-15 10:46:31 +04:00
parent 2cf86a22de
commit 7a4dd6f3e5
3 changed files with 28 additions and 16 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ipwhitelist", "name": "ipwhitelist",
"version": "0.6.11", "version": "0.6.12",
"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.6.11', version: '0.6.12',
// ── 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',
+26 -14
View File
@@ -32,24 +32,36 @@ function resolveContext(req, res, next) {
// Нет сессии — нет доступа // Нет сессии — нет доступа
if (!u) return res.redirect('/login'); if (!u) return res.redirect('/login');
// Имперсонация: админ действует от имени компании // ═══ САНИТАЙЗЕР IAM — всё что пришло может быть null/undefined/говном ═══
// u.originalUserEmail — реальный админ const s = (v) => (v == null || v === 'null' || v === 'undefined') ? '' : String(v).trim();
// u.impersonatedCompanyId — W-номер компании const arr = (v) => (Array.isArray(v) ? v : []);
const ADMIN_EMAIL = process.env.ADMIN_EMAIL || '';
const isImpersonated = !!(u.originalUserEmail && u.impersonatedCompanyId) || u.isImpersonated; // Нормализуем ВСЕ поля из сессии
const email = s(u.email);
const clientId = s(u.clientId);
const activeClientId = s(u.activeClientId);
const originalUserEmail = s(u.originalUserEmail);
const impersonatedCompanyId = s(u.impersonatedCompanyId);
const companyName = s(u.companyName);
const allClientIds = arr(u.allClientIds).map(s).filter(Boolean);
const profiles = arr(u.profiles);
const isAdmin = !!u.isAdmin;
const adminMode = !!u.adminMode;
const isImpersonatedFlag = !!u.isImpersonated;
const ADMIN_EMAIL = (process.env.ADMIN_EMAIL || '').trim();
const isImpersonated = (!!originalUserEmail && !!impersonatedCompanyId) || isImpersonatedFlag;
// req.email = ТЕКУЩИЙ юзер (имперсонированный или реальный) // req.email = ТЕКУЩИЙ юзер (имперсонированный или реальный)
// ВЕЗДЕ: created_by, экран, формы req.email = email;
req.email = u.email || ''; req.clientId = isImpersonated ? impersonatedCompanyId : (activeClientId || clientId);
req.clientId = isImpersonated ? u.impersonatedCompanyId : (u.activeClientId || u.clientId || '');
if (!req.clientId) return res.status(400).send('<h2>Ошибка</h2><p>Не удалось определить W-номер компании. Проверьте настройки IAM.</p><p><a href="/logout">Выйти</a></p>'); if (!req.clientId) return res.status(400).send('<h2>Ошибка</h2><p>Не удалось определить W-номер компании. Проверьте настройки IAM.</p><p><a href="/logout">Выйти</a></p>');
req.companyName = u.companyName || req.clientId; req.companyName = companyName || req.clientId;
req.isAdmin = !!(u.isAdmin && u.adminMode) || (ADMIN_EMAIL && u.email === ADMIN_EMAIL); req.isAdmin = (isAdmin && adminMode) || (!!ADMIN_EMAIL && email === ADMIN_EMAIL);
req.isImpersonated = isImpersonated; req.isImpersonated = isImpersonated;
// req.impersonatedBy = РЕАЛЬНЫЙ юзер (только в колонке impersonated_by аудита) req.impersonatedBy = isImpersonated ? originalUserEmail : null;
req.impersonatedBy = isImpersonated ? (u.originalUserEmail || '') : null; req.allClientIds = allClientIds.length ? allClientIds : [req.clientId];
req.allClientIds = u.allClientIds || [req.clientId]; req.profiles = profiles;
req.profiles = u.profiles || [];
next(); next();
} }