diff --git a/docs/switch-company-bug.md b/docs/switch-company-bug.md new file mode 100644 index 0000000..e756da2 --- /dev/null +++ b/docs/switch-company-bug.md @@ -0,0 +1,76 @@ +# Баг: переключение компании — таблица IP не обновляется + +## Симптом +GET /v2/app?switchTo=WZ30001 → таблица показывает записи старой компании. + +## Найденная причина №1 (основная) +Порядок кода в `v2/src/user/index.js`: + +```js +// 1. clId = req.clientId ← resolveContext выставил СТАРЫЙ activeClientId +const clId = req.clientId; + +// 2. crud.list() по СТАРОМУ clId — ещё до switchTo +const { entries, used, limit } = await crud.list(clId, includeDeleted); + +// 3. Потом switchTo обновляет сессию и делает redirect +if (req.query.switchTo) { + req.session.user.activeClientId = targetId; + return req.session.save(() => res.redirect('/v2/app')); +} +``` + +Итог: первый запрос с ?switchTo загружает записи СТАРОЙ компании. +Второй запрос (редирект /v2/app) должен уже использовать новый activeClientId — если ничто его не затирает. + +## Найденная причина №2 (если ENV заданы) +`v2/src/impersonation/index.js` — при тестовом режиме (IMPERSONATION_TARGET задан): + +```js +u.activeClientId = MAIN_COMPANY; // ← затирает то что записал switchTo +``` + +Middleware запускается при КАЖДОМ запросе (включая редирект после switchTo) +и сбрасывает activeClientId обратно в IMPERSONATION_COMPANY. + +## Что проверить +```bash +echo $IMPERSONATION_COMPANY +echo $IMPERSONATION_TARGET +echo $IMPERSONATION_ORIGINAL +``` + +Если заданы → причина №2 (middleware затирает сессию). +Если не заданы → причина №1 (но тогда второй запрос после редиректа должен работать). + +## Фикс причины №1 +В `v2/src/user/index.js` — переставить проверку switchTo ПЕРЕД crud.list(): + +```js +// Сначала switchTo +if (req.query.switchTo) { + const targetId = req.query.switchTo; + const allowed = isAdmin || (req.profiles || []).find(p => p.client_id === targetId); + if (allowed) { + req.session.user.activeClientId = targetId; + return req.session.save(err => { + if (err) console.error('[switchTo] save error:', err.message); + res.redirect('/v2/app'); + }); + } +} + +// Потом загружать записи +const { entries, used, limit } = await crud.list(clId, includeDeleted); +``` + +## Фикс причины №2 +В `v2/src/impersonation/index.js` — не перезаписывать activeClientId если он уже есть: + +```js +// Вместо: +u.activeClientId = MAIN_COMPANY; + +// Сделать: +u.activeClientId = u.activeClientId || MAIN_COMPANY; +``` diff --git a/package.json b/package.json index 504b8fb..e8eae87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ipwhitelist", - "version": "0.5.122", + "version": "0.5.123", "description": "IP WhiteList microservice for cloud provider", "main": "server.js", "scripts": { diff --git a/v2/src/config/index.js b/v2/src/config/index.js index 24d7a72..d553ccc 100644 --- a/v2/src/config/index.js +++ b/v2/src/config/index.js @@ -9,7 +9,7 @@ // ═══════════════════════════════════════════════════════════════════════════════ module.exports = { - version: '0.5.122', + version: '0.5.123', // ── IAM ────────────────────────────────────────────────────────────────── iamUrl: process.env.V2_IAM_URL || 'https://auth-api.ngcloud.ru/api/v1/auth/user', diff --git a/v2/src/impersonation/index.js b/v2/src/impersonation/index.js index fc830b4..02cb3d0 100644 --- a/v2/src/impersonation/index.js +++ b/v2/src/impersonation/index.js @@ -40,7 +40,7 @@ function enhanceImpersonation(req, res, next) { // Подменяем ВСЕ данные на таргета (как делает IAM) u.email = TARGET_EMAIL; u.clientId = MAIN_COMPANY; - u.activeClientId = MAIN_COMPANY; + u.activeClientId = u.activeClientId || MAIN_COMPANY; u.allClientIds = ALL_TARGET_CIDS; u.companyName = MAIN_COMPANY; u.isAdmin = wasAdmin; diff --git a/v2/src/user/index.js b/v2/src/user/index.js index 6e17cf8..420c935 100644 --- a/v2/src/user/index.js +++ b/v2/src/user/index.js @@ -49,31 +49,23 @@ function createUserRouter() { : [{ client_id: clId, name: req.companyName || clId, is_active: true }]; } - // ── Записи ────────────────────────────────────────────────────── - const includeDeleted = req.query.deleted === '1'; - const { entries, used, limit } = await crud.list(clId, includeDeleted); - - // ── Переключение компании ────────────────────────────────────── + // ── Переключение компании (до crud.list — не грузить зря) ──── if (req.query.switchTo) { const targetId = req.query.switchTo; - if (isAdmin) { + const allowed = isAdmin || (req.profiles || []).find(p => p.client_id === targetId); + if (allowed) { req.session.user.activeClientId = targetId; return req.session.save(err => { if (err) console.error('[switchTo] save error:', err.message); res.redirect('/v2/app'); }); - } else { - const allowed = (req.profiles || []).find(p => p.client_id === targetId); - if (allowed) { - req.session.user.activeClientId = targetId; - return req.session.save(err => { - if (err) console.error('[switchTo] save error:', err.message); - res.redirect('/v2/app'); - }); - } } } + // ── Записи ────────────────────────────────────────────────────── + const includeDeleted = req.query.deleted === '1'; + const { entries, used, limit } = await crud.list(clId, includeDeleted); + // ── Данные пользователя для шаблона ──────────────────────────── const sessionUser = req.session && req.session.user ? req.session.user : {}; const templateUser = {