Files
ipwhitelist-app/docs/history/2026-06-11.md

7.5 KiB
Raw Permalink Blame History

Сессия 2026-06-11 — Имперсонация, toggle, аудит

Хронология

1. Починка toggle «Администратор»

Проблема: чекбокс не показывался.
Причина: canAdminMode вычислялся в resolveUser, но не передавался в res.render.
Исправление: добавлен canAdminMode: req.user.canAdminMode в entries.js.

2. Дубликат catch → крэш

При правке ui/index.js остался дубликат } catch {. Приложение падало при старте.
Исправление: удалён лишний catch.

3. JS onclick → form POST

Toggle не реагировал — сложный inline JS с getComputedStyle и fetch.
Исправление: заменён на <form method="POST" action="/toggle-admin">. Ноль JS.

4. Чужой email в header

Админ видел nstasyuk@nubes.ru вместо своего — шаблон показывал selectedCompany.owner_email.
Исправление: всегда показывать user.email.

5. Хардкод isNail

IAM не давал isAdmin: true для ntazetdinov@nubes.ru.
Исправление: временный хардкод isNail в ui/index.js.

6. canWrite из IAM

IAM возвращает can_write: false для всех — это IAM-шная RBAC, не наш флаг.
Исправление: canWrite убран полностью.

7. Имперсонация: флаги из IAM

Добавлены поля из IAM: isImpersonated, originalUserEmail, originalUserFullName, impersonationType.
Файлы: src/auth.js:fetchIamUser, src/routes/oidc.js, ui/index.js:resolveUser.

8. Баннер имперсонации

В views/index.ejs добавлен жёлтый баннер при isImpersonated.

9. Двойной аудит

Колонка impersonated_by в audit_log.
Файлы: src/db.js (миграция), src/queries.js:logAudit, src/api/routes/entries.js.

10. X-Imp-* заголовки — мост UI→API

UI-слой знал про имперсонацию, API-слой — нет.
Исправление: api-client.js:impHeaders(), bearerMiddleware читает X-Imp-Email, X-Imp-OriginalEmail, X-Imp-ClientId.

11. Безопасность: OIDC state check

|| true в /callback отключал проверку state во всех окружениях.
Исправление: убрано || true.

12. Безопасность: open redirect

POST /login-token редиректил без safeReturn.
Исправление: добавлен safeReturn(returnTo).

13. Безопасность: client_id без проверки

При пустом allowedIds можно было подставить любой ?client_id=.
Исправление: requestedId принимается только если allowedIds.length > 0.

14. Тестовая имперсонация

Три env-переменные: IMPERSONATION_ORIGINAL, IMPERSONATION_TARGET, IMPERSONATION_COMPANY.
Файл: ui/index.js (блок TEST IMPERSONATION).

15. Часовой пояс GMT+4

Europe/MoscowEtc/GMT-4 в views/index.ejs и views/audit.ejs.

16. Аудит: колонка «Имперсонировал»

В views/audit.ejs добавлена колонка impersonated_by. Фильтр по компании — кнопка вместо JS.

17. Удалённые записи: визуал

Зачёркивание + полупрозрачность. Кнопки скрыты для удалённых.
Файл: views/index.ejs.

18. Чекбокс «Показать удалённые»

Возвращён в админ-режим.
Файл: views/index.ejs.

19. ТЗ-факт

Составлен документ TZs/ТЗ-факт.md — техзадание по фактически реализованному функционалу.

20. Сверка с требованиями Сергея

Прочитан Files/wsm.txt. Подтверждено соответствие. Не сделано: ссылка на запрещённые префиксы, текст-мануал от Стасюка.

Основные файлы, изменённые в сессии

Файл Что
ui/index.js canAdminMode, isNail, TEST IMPERSONATION, canWrite
ui/routes/entries.js canAdminMode в render, impHeaders, упрощение ownCo
ui/routes/auth.js toggle-admin redirect, open redirect fix
ui/api-client.js impHeaders(), X-Imp-* заголовки
src/auth.js fetchIamUser (все поля), bearerMiddleware (X-Imp-*), safeReturn
src/routes/oidc.js isImpersonated в сессию, fix
src/api/routes/entries.js impersonatedBy в queries, client_id fix, export JSON
src/db.js ALTER TABLE impersonated_by
src/queries.js logAudit с impersonatedBy
views/index.ejs toggle (form POST), баннеры, удалённые записи, includeDeleted
views/audit.ejs колонка impersonated_by, кнопка фильтра, GMT+4
server.js debug-session с lastAudit

Ветки

  • save-2026-06-11 — снапшот перед критичными фиксами
  • save-2026-06-12 — финальное состояние

Что осталось (для следующего чата)

Баги

  1. Toggle виден при имперсонации — по требованию Сергея: «Когда я имперсонирую — вижу то же что пользователь». При имперсонации canAdminMode должен быть false (сейчас true, потому что вычисляется из оригинального JWT, а не из activeClientId). ui/index.js строка 65-67.
  2. Email в header берётся из payload.email, а не из req.session?.user?.email. Иногда показывает чужой email. ui/index.js строка 75.

Не сделано по ТЗ/требованиям Сергея

  1. Ссылка на список зарезервированных префиксов (14 диапазонов)
  2. Краткий мануал на главной для пользователей (ждём от Стасюка)

Временные решения (убрать при настройке IAM)

  1. isNail — хардкод ntazetdinov@nubes.ru как админ. Заменить на isAdmin из IAM. ui/index.js строка 63.
  2. TEST IMPERSONATION — env-переменные. Убрать для прода. ui/index.js строки 70-78.

Архитектурный долг

  1. Дублирование buildSessionUser в oidc.js и auth.js
  2. Флаги isAdmin/adminMode/canAdminMode/isNail — упростить до двух
  3. Циклическая зависимость ui → src/auth через require('../../src/auth')

Как работать дальше

  1. Прочитать ТЗ: TZs/ТЗ-факт.md (фактическое), docs/ТЗ.md (оригинал)
  2. Прочитать требования Сергея: Files/wsm.txt (особенно строки 378-470)
  3. Начать с бага №1 (toggle + имперсонация) — это противоречит требованию заказчика