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;