v0.6.9: защита от пустого clientId (null client_id)
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ipwhitelist",
|
"name": "ipwhitelist",
|
||||||
"version": "0.6.8",
|
"version": "0.6.9",
|
||||||
"description": "IP WhiteList microservice for cloud provider",
|
"description": "IP WhiteList microservice for cloud provider",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -832,3 +832,83 @@ express HTTP
|
|||||||
| 1 | Интеграция в основной код | ✅ 0.5.98 |
|
| 1 | Интеграция в основной код | ✅ 0.5.98 |
|
||||||
| 2 | Auth (KC callback) | ⏸ заблокирован облаком |
|
| 2 | Auth (KC callback) | ⏸ заблокирован облаком |
|
||||||
| 3 | Убрать старые v2_* таблицы из БД | ⏸ после деплоя |
|
| 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`) должны быть заданы — иначе авто-имперсонация не включается.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// ═══════════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
version: '0.6.8',
|
version: '0.6.9',
|
||||||
|
|
||||||
// ── 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',
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const { validate } = require('../validators');
|
|||||||
// Возвращает { id, client_id, name, custom_limit }.
|
// Возвращает { id, client_id, name, custom_limit }.
|
||||||
// Вызывается из list/add/edit/remove перед каждой операцией.
|
// Вызывается из list/add/edit/remove перед каждой операцией.
|
||||||
async function resolve(clientId) {
|
async function resolve(clientId) {
|
||||||
|
if (!clientId || !clientId.trim()) throw new Error('Ошибка: не определён clientId (W-номер компании). Обратитесь к администратору.');
|
||||||
return q.getOrCreateCompany(clientId, clientId);
|
return q.getOrCreateCompany(clientId, clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ function resolveContext(req, res, next) {
|
|||||||
// ВЕЗДЕ: created_by, экран, формы
|
// ВЕЗДЕ: created_by, экран, формы
|
||||||
req.email = u.email || '';
|
req.email = u.email || '';
|
||||||
req.clientId = isImpersonated ? u.impersonatedCompanyId : (u.activeClientId || u.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>');
|
||||||
req.companyName = u.companyName || req.clientId;
|
req.companyName = u.companyName || req.clientId;
|
||||||
req.isAdmin = !!(u.isAdmin && u.adminMode) || (ADMIN_EMAIL && u.email === ADMIN_EMAIL);
|
req.isAdmin = !!(u.isAdmin && u.adminMode) || (ADMIN_EMAIL && u.email === ADMIN_EMAIL);
|
||||||
req.isImpersonated = isImpersonated;
|
req.isImpersonated = isImpersonated;
|
||||||
|
|||||||
Reference in New Issue
Block a user