v2: подробные комментарии во всех модулях — что, зачем, контракты
This commit is contained in:
@@ -369,3 +369,186 @@ remove(entryId, clientId, email, impBy) → void
|
||||
1. **Тестирование**: crud тестируется без Express, user тестируется с моком crud
|
||||
2. **Переиспользование**: admin, test, export — все через crud
|
||||
3. **Независимость**: фронтенд не знает про deviceId, БД-схему, транзакции
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Текущее состояние (0.5.93) — полная архитектура
|
||||
|
||||
### Слои приложения
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Express HTTP │
|
||||
├────────────┬────────────────┬───────────────────────┤
|
||||
│ user/ │ admin/ │ test/ │
|
||||
│ (юзер) │ (админ) │ (тестовый слой) │
|
||||
│ HTML+POST │ HTML+POST │ JSON, no session │
|
||||
├────────────┴────────────────┴───────────────────────┤
|
||||
│ router/ │
|
||||
│ resolveContext middleware │
|
||||
│ сессия → req.clientId, email, isAdmin │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ crud/ │
|
||||
│ API БД (чистые функции) │
|
||||
│ list(clientId) / add / edit / remove │
|
||||
│ validate() вызывается здесь │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ db/ │
|
||||
│ queries.js (SQL) + schema.js (DDL) │
|
||||
│ чистый SQL: createEntry, updateEntry, ... │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ validators/ │
|
||||
│ validate(cidr), overlaps(), BLOCKED_RANGES │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ auth/ + config/ │
|
||||
│ OIDC: login, exchangeCode, fetchIamUser │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Слои — внутренние API (не HTTP)
|
||||
|
||||
Каждый слой — модуль Node.js с контрактом:
|
||||
|
||||
| Слой | Экспорт | Вход | Выход |
|
||||
|------|---------|------|-------|
|
||||
| **validators/** | `validate(raw)` | строка CIDR | `{ cidr, wasNormalized }` или throw |
|
||||
| **crud/** | `add(clientId, cidr, ...)` | W-номер + параметры | `{ entry, wasNormalized }` или throw |
|
||||
| **crud/** | `list(clientId)` | W-номер | `{ entries, used, limit }` |
|
||||
| **crud/** | `edit(entryId, clientId, cidr, ...)` | ID + W-номер | `{ entry, wasNormalized }` |
|
||||
| **crud/** | `remove(entryId, clientId, ...)` | ID + W-номер | void |
|
||||
| **db/** | `createEntry(companyId, cidr, ...)` | внутренний ID + чистый CIDR | `{ entry }` |
|
||||
| **db/** | `getAllCompanies()` | — | массив компаний |
|
||||
| **db/** | `getAudit(companyId)` | companyId или null | массив записей аудита |
|
||||
| **db/** | `setLimit(companyId, limit)` | ID + число | void |
|
||||
|
||||
### Структура файлов
|
||||
|
||||
```
|
||||
v2/
|
||||
├── server.js # createV2Router() — монтаж всех роутеров
|
||||
├── history/
|
||||
│ └── 2026-06-12.md # этот файл
|
||||
└── src/
|
||||
├── auth/index.js # OIDC: login, exchangeCode, fetchIamUser, buildAuthUrl
|
||||
├── config/index.js # V2_* env, version, умолчания
|
||||
├── router/index.js # resolveContext — сессия → req.*
|
||||
├── validators/
|
||||
│ └── index.js # validate, overlaps, BLOCKED_RANGES (14 диапазонов ТЗ)
|
||||
├── crud/
|
||||
│ └── index.js # list, add, edit, remove — API БД, вызывает validate()
|
||||
├── db/
|
||||
│ ├── index.js # pg pool
|
||||
│ ├── queries.js # SQL: CRUD + admin (getAllCompanies, setLimit, getAudit)
|
||||
│ └── schema.js # ensureSchema — автосоздание v2_companies, v2_entries, v2_audit
|
||||
├── user/
|
||||
│ └── index.js # createUserRouter — фронт юзера: HTML + POST /add /edit /delete
|
||||
├── admin/
|
||||
│ └── index.js # createAdminRouter — дашборд, аудит, лимиты, записи
|
||||
└── test/
|
||||
├── index.js # createTestRouter — тестовый API + chaos + userFlow
|
||||
└── test.sh # 54 curl-теста
|
||||
```
|
||||
|
||||
### Маршруты /v2
|
||||
|
||||
| Маршрут | Слой | Авторизация | Что |
|
||||
|---------|------|------------|-----|
|
||||
| `/v2/login` | server.js | Нет | Редирект на `/login?returnTo=/v2/app` |
|
||||
| `/v2/iam` | server.js | Сессия | IAM-данные (отладка) |
|
||||
| `/v2/app` | user/ | resolveContext | CRUD юзера: список, добавить, изменить, удалить |
|
||||
| `/v2/admin` | admin/ | isAdmin | Дашборд компаний |
|
||||
| `/v2/admin/audit` | admin/ | isAdmin | Аудит по компании |
|
||||
| `/v2/admin/limit` | admin/ | isAdmin | POST — установить лимит |
|
||||
| `/v2/admin/entries` | admin/ | isAdmin | Записи любой компании |
|
||||
| `/v2/test` | test/ | Нет (флаг) | Тестовый API: `?action=add/list/edit/delete/audit/limit/switch/cleanup/userFlow` |
|
||||
| `/v2/test/chaos` | test/ | Нет (флаг) | Параллельный хаос-тест (40 операций) |
|
||||
| `/v2/logout` | server.js | Нет | Редирект на `/logout` |
|
||||
|
||||
### Цепочка вызовов (юзер добавляет CIDR)
|
||||
|
||||
```
|
||||
Браузер: форма <form method="POST" action="/v2/app/add">
|
||||
→ POST /v2/app/add
|
||||
→ user/index.js router.post('/add')
|
||||
→ crud.add(clientId, rawCidr, comment, email, impBy)
|
||||
→ validators.validate(rawCidr)
|
||||
→ db.getOrCreateCompany(clientId)
|
||||
→ db.createEntry(companyId, validatedCidr, ...)
|
||||
→ overlaps() — проверка дубликатов в БД
|
||||
→ SQL INSERT v2_entries
|
||||
→ SQL INSERT v2_audit
|
||||
→ 302 /v2/app?msg=Добавлено
|
||||
```
|
||||
|
||||
### Админка — возможности
|
||||
|
||||
| Функция | Маршрут | Через |
|
||||
|---------|---------|-------|
|
||||
| Список всех компаний | GET /v2/admin | q.getAllCompanies() |
|
||||
| Аудит компании | GET /v2/admin/audit?companyId=X | q.getAudit() |
|
||||
| Установка лимита | POST /v2/admin/limit | q.setLimit() |
|
||||
| Записи компании | GET /v2/admin/entries?companyId=X | crud.list(clientId) |
|
||||
|
||||
Колонки аудита: Дата, Действие, Кто, От имени (impersonated_by), Компания, Значения (old→new).
|
||||
|
||||
### Тестовый слой
|
||||
|
||||
`/v2/test` — полный доступ ко всем слоям через curl, без KC-сессии:
|
||||
|
||||
| Action | Что тестирует | Слои |
|
||||
|--------|--------------|------|
|
||||
| `?action=add&cidr=X` | Добавление | test→crud→validate→db |
|
||||
| `?action=edit&id=X&cidr=Y` | Изменение | test→crud→validate→db |
|
||||
| `?action=delete&id=X` | Удаление | test→crud→db |
|
||||
| `?action=list` | Список | test→crud→db |
|
||||
| `?action=audit` | Аудит | test→db |
|
||||
| `?action=userFlow&sub=add` | Полная эмуляция юзера | test→мок сессии→crud→db |
|
||||
| `/chaos` | Параллельный (40 ops) | test→crud→db |
|
||||
| `?action=cleanup` | Очистка | test→db (прямые DELETE) |
|
||||
|
||||
Флаг отключения: `ENABLE_TEST_API=false` — код остаётся, роутер не монтируется.
|
||||
|
||||
### Тесты — сводка
|
||||
|
||||
| Группа | Кол-во | Статус |
|
||||
|--------|--------|--------|
|
||||
| test.sh (curl) | 54 | ✅ |
|
||||
| Chaos (параллельные) | 1 | ✅ |
|
||||
| Router (resolveContext) | 9 | ✅ |
|
||||
| **Всего** | **64** | **✅** |
|
||||
|
||||
### Деплой
|
||||
|
||||
git push → Gitea → Nubes UI redeploy → `whitelist.nodejsk8s.services.ngcloud.ru`
|
||||
|
||||
VM (italo.kube5s.ru) — НЕ используется для деплоя v2.
|
||||
|
||||
### Ключевые решения
|
||||
|
||||
1. **Слои — внутренние API**: не HTTP, не микросервисы, чистые функции в одном процессе
|
||||
2. **validate() вызывается в crud/**: db/queries получает готовый CIDR, не вызывает validate
|
||||
3. **crud/ резолвит clientId→companyId**: фронтенды не знают про внутренние ID БД
|
||||
4. **test/ — отдельный вход**: мок-сессия, без KC, доступен только в dev
|
||||
5. **ENABLE_TEST_API=false** — отключение без удаления кода
|
||||
6. **v2_ префиксы**: на таблицах БД — v2_companies, v2_entries, v2_audit. При интеграции убрать.
|
||||
7. **Сессия без v2_ префикса**: `req.session.user` — совместимо с основным приложением
|
||||
|
||||
### Что дальше
|
||||
|
||||
| # | Задача | Статус |
|
||||
|---|--------|--------|
|
||||
| 1 | export/ — выгрузка CIDR | ❌ |
|
||||
| 2 | EJS-шаблоны вместо inline HTML | ❌ |
|
||||
| 3 | Auth end-to-end (KC callback) | ❌ |
|
||||
| 4 | Интеграция в основной код (убрать v2_) | ❌ |
|
||||
|
||||
### Известные ошибки (исправлены)
|
||||
|
||||
| Баг | Причина | Фикс | Версия |
|
||||
|-----|---------|------|--------|
|
||||
| 10.x CIDR → 45 ошибок chaos | 10.0.0.0/8 в BLOCKED | Префиксы 11–14 | 0.5.89 |
|
||||
| auditCount=0 | Проверяли только WZ10001 | Все 4 компании | 0.5.89 |
|
||||
| 105/150 ошибок | 3 задачи × 15 > лимит 15 | 1 задача × 10 | 0.5.89 |
|
||||
| /chaos → 302 /login | Роутер на /test/api | Сменили на /test | 0.5.88 |
|
||||
| validate() в db/queries | Смешаны слои | Вынесен в crud/ | 0.5.91 |
|
||||
|
||||
Reference in New Issue
Block a user