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

129 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сессия 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 || true |
| `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.
### Не сделано по ТЗ/требованиям Сергея
3. Ссылка на список зарезервированных префиксов (14 диапазонов)
4. Краткий мануал на главной для пользователей (ждём от Стасюка)
### Временные решения (убрать при настройке IAM)
5. `isNail` — хардкод `ntazetdinov@nubes.ru` как админ. Заменить на `isAdmin` из IAM. `ui/index.js` строка 63.
6. `TEST IMPERSONATION` — env-переменные. Убрать для прода. `ui/index.js` строки 70-78.
### Архитектурный долг
7. Дублирование `buildSessionUser` в `oidc.js` и `auth.js`
8. Флаги `isAdmin`/`adminMode`/`canAdminMode`/`isNail` — упростить до двух
9. Циклическая зависимость `ui → src/auth` через `require('../../src/auth')`
## Как работать дальше
1. Прочитать ТЗ: `TZs/ТЗ-факт.md` (фактическое), `docs/ТЗ.md` (оригинал)
2. Прочитать требования Сергея: `Files/wsm.txt` (особенно строки 378-470)
3. Начать с бага №1 (toggle + имперсонация) — это противоречит требованию заказчика