7.5 KiB
Сессия 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/Moscow → Etc/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— финальное состояние
Что осталось (для следующего чата)
Баги
- Toggle виден при имперсонации — по требованию Сергея: «Когда я имперсонирую — вижу то же что пользователь». При имперсонации
canAdminModeдолжен быть false (сейчас true, потому что вычисляется из оригинального JWT, а не изactiveClientId).ui/index.jsстрока 65-67. - Email в header берётся из
payload.email, а не изreq.session?.user?.email. Иногда показывает чужой email.ui/index.jsстрока 75.
Не сделано по ТЗ/требованиям Сергея
- Ссылка на список зарезервированных префиксов (14 диапазонов)
- Краткий мануал на главной для пользователей (ждём от Стасюка)
Временные решения (убрать при настройке IAM)
isNail— хардкодntazetdinov@nubes.ruкак админ. Заменить наisAdminиз IAM.ui/index.jsстрока 63.TEST IMPERSONATION— env-переменные. Убрать для прода.ui/index.jsстроки 70-78.
Архитектурный долг
- Дублирование
buildSessionUserвoidc.jsиauth.js - Флаги
isAdmin/adminMode/canAdminMode/isNail— упростить до двух - Циклическая зависимость
ui → src/authчерезrequire('../../src/auth')
Как работать дальше
- Прочитать ТЗ:
TZs/ТЗ-факт.md(фактическое),docs/ТЗ.md(оригинал) - Прочитать требования Сергея:
Files/wsm.txt(особенно строки 378-470) - Начать с бага №1 (toggle + имперсонация) — это противоречит требованию заказчика