From 00d3928a508ad8b0cb092078f7a2a6547889aaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 15 Jun 2026 10:35:03 +0400 Subject: [PATCH] =?UTF-8?q?v0.6.9:=20=D0=B7=D0=B0=D1=89=D0=B8=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BE=D1=82=20=D0=BF=D1=83=D1=81=D1=82=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?clientId=20(null=20client=5Fid)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- v2/history/2026-06-12.md | 80 ++++++++++++++++++++++++++++++++++++++++ v2/src/config/index.js | 2 +- v2/src/crud/index.js | 1 + v2/src/router/index.js | 1 + 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6250232..5c56b96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.6.8", + "version": "0.6.9", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/v2/history/2026-06-12.md b/v2/history/2026-06-12.md index 463def5..f05a537 100644 --- a/v2/history/2026-06-12.md +++ b/v2/history/2026-06-12.md @@ -832,3 +832,83 @@ express HTTP | 1 | Интеграция в основной код | ✅ 0.5.98 | | 2 | Auth (KC callback) | ⏸ заблокирован облаком | | 3 | Убрать старые v2_* таблицы из БД | ⏸ после деплоя | + + +--- + +## Интеграция v2 в основной проект (0.6.0–0.6.8, 2026-06-15) + +### Что сделано + +| Версия | Что | +|--------|-----| +| 0.5.98 | Таблицы `v2_*` → `companies`, `whitelist_entries`, `audit_log` | +| 0.5.98 | `impersonation/` модуль — добавление компаний через ENV | +| 0.5.99 | V2 как основной UI: `app.use('/', createV2Router())`, старый UI закомментирован | +| 0.6.0 | Дизайн Nubes: лого, header, стили из `views/index.ejs` | +| 0.6.1 | Фикс: email в header | +| 0.6.2 | `displayEmail` справа от статистики | +| 0.6.3 | Жёлтый баннер имперсонации вместо метки `(имперсонация)` | +| 0.6.4 | Авто-имперсонация: `IMPERSONATION_ORIGINAL → TARGET` | +| 0.6.4 | `ADMIN_EMAIL` в `resolveContext` | +| 0.6.5 | `loginEmail` из `originalUserEmail` | +| 0.6.6 | `req.displayEmail` — разделение экран/аудит | +| 0.6.7 | **Перепутаны местами**: `req.email` и `req.impersonatedBy` | +| 0.6.8 | «Выйти» — только реальный KC-юзер | + +### Ключевая ошибка: перепутаны `req.email` и `req.impersonatedBy` + +**Что было неправильно (0.6.6 и ранее):** + +```js +req.email = реальный → created_by = ntazetdinov@nubes.ru ❌ +req.impersonatedBy = имперсонированный → impersonated_by = tazet@narod.ru ❌ +``` + +**Почему ошибался:** AI думал что `req.email` должно хранить реального юзера «для аудита», +а имперсонированного — для показа. Это неверно. Везде должен использоваться ТЕКУЩИЙ +юзер (имперсонированный если есть имперсонация), а реальный — ТОЛЬКО в колонке +`impersonated_by` таблицы аудита. + +**Как правильно (0.6.7+):** + +```js +req.email = ТЕКУЩИЙ → created_by = tazet@narod.ru ✅ +req.impersonatedBy = РЕАЛЬНЫЙ → impersonated_by = ntazetdinov@... ✅ +``` + +**Урок:** `req.email` — это ВСЕГДА текущий юзер. Имперсонация не меняет его смысл — +она меняет значение `session.user.email`, и `req.email` просто берёт его. + +### Правильная логика (0.6.8) + +``` +KC логин: ntazetdinov@nubes.ru + ↓ +session.user.email = ntazetdinov@nubes.ru + ↓ +enhanceImpersonation: ORIGINAL совпал → авто-имперсонация + session.user.originalUserEmail = ntazetdinov@nubes.ru (реальный) + session.user.email = tazet@narod.ru (текущий) + ↓ +resolveContext: + req.email = u.email = tazet@narod.ru (текущий — created_by, экран) + req.impersonatedBy = u.originalUserEmail (реальный — только аудит) + req.isImpersonated = true + ↓ +user/index.js → шаблон: + loginEmail = ntazetdinov@nubes.ru → «Выйти» + email = tazet@narod.ru → контент, статистика +``` + +### Переменные ENV для авто-имперсонации + +| Переменная | Значение | Роль | +|-----------|---------|------| +| `IMPERSONATION_ORIGINAL` | `ntazetdinov@nubes.ru` | Условие: чей email сравнить | +| `IMPERSONATION_TARGET` | `tazet@narod.ru` | Цель: в кого имперсонировать | +| `IMPERSONATION_COMPANY` | `WZ01325` | Компания: какая компания | +| `IMPERSONATION_EXTRA_COMPANIES` | `WZ01112` | Доп. компании | +| `ADMIN_EMAIL` | `tazet@narod.ru` | Псевдо-админ | + +Все три (`ORIGINAL`, `TARGET`, `COMPANY`) должны быть заданы — иначе авто-имперсонация не включается. diff --git a/v2/src/config/index.js b/v2/src/config/index.js index 995c11f..e25c050 100644 --- a/v2/src/config/index.js +++ b/v2/src/config/index.js @@ -9,7 +9,7 @@ // ═══════════════════════════════════════════════════════════════════════════════ module.exports = { - version: '0.6.8', + version: '0.6.9', // ── IAM ────────────────────────────────────────────────────────────────── iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user', diff --git a/v2/src/crud/index.js b/v2/src/crud/index.js index 4837e96..bfcf2de 100644 --- a/v2/src/crud/index.js +++ b/v2/src/crud/index.js @@ -31,6 +31,7 @@ const { validate } = require('../validators'); // Возвращает { id, client_id, name, custom_limit }. // Вызывается из list/add/edit/remove перед каждой операцией. async function resolve(clientId) { + if (!clientId || !clientId.trim()) throw new Error('Ошибка: не определён clientId (W-номер компании). Обратитесь к администратору.'); return q.getOrCreateCompany(clientId, clientId); } diff --git a/v2/src/router/index.js b/v2/src/router/index.js index 66692d7..db3357e 100644 --- a/v2/src/router/index.js +++ b/v2/src/router/index.js @@ -42,6 +42,7 @@ function resolveContext(req, res, next) { // ВЕЗДЕ: created_by, экран, формы req.email = u.email || ''; req.clientId = isImpersonated ? u.impersonatedCompanyId : (u.activeClientId || u.clientId || ''); + if (!req.clientId) return res.status(400).send('

Ошибка

Не удалось определить W-номер компании. Проверьте настройки IAM.

Выйти

'); req.companyName = u.companyName || req.clientId; req.isAdmin = !!(u.isAdmin && u.adminMode) || (ADMIN_EMAIL && u.email === ADMIN_EMAIL); req.isImpersonated = isImpersonated;