v2: разделение слоёв — crud/index.js API-слой, user/ и test/ через crud

This commit is contained in:
2026-06-13 06:55:18 +04:00
parent 4b5ccc6a4c
commit 3c061b6c4b
6 changed files with 267 additions and 240 deletions
+210
View File
@@ -159,3 +159,213 @@ req.v2_profiles → req.profiles
req.v2_companyName → req.companyName
```
Причина: в основном коде нет префиксов.
---
## Текущее состояние (0.5.89)
### Структура v2/
```
v2/
├── server.js # createV2Router() — монтируется в server.js как /v2
├── history/
│ └── 2026-06-12.md # этот файл
└── src/
├── auth/index.js # fetchIamUser(), login(), exchangeCode(), buildAuthUrl()
├── config/index.js # V2_* env, version, умолчания
├── router/index.js # resolveContext middleware (email, clientId, isAdmin, impersonation)
├── user/index.js # createUserRouter() — UI CRUD с выбором компании
├── admin/index.js # createAdminRouter() — ПУСТЫШКА (email, clientId)
├── crud/index.js # createCrudRouter() — старый, НЕ монтирован
├── db/
│ ├── index.js # pg pool
│ ├── queries.js # CRUD: getOrCreateCompany, listEntries, createEntry, updateEntry, deleteEntry, getAudit, getLimit, setLimit, getExportCIDRs, getAllCompanies
│ └── schema.js # ensureSchema(pool) — автосоздание v2_companies, v2_entries, v2_audit
├── test/
│ ├── index.js # createTestRouter() — /v2/test?action=... и GET /chaos
│ └── test.sh # 54 curl-теста
└── validators/index.js # validate(), overlaps(), cidrToRange(), aggregateCIDRs(), BLOCKED_RANGES
```
### Маршруты /v2
| Маршрут | Что | Авторизация |
|---------|-----|------------|
| `/v2/login` | Редирект на `/login?returnTo=/v2/app` | Нет |
| `/v2/iam` | IAM-данные из сессии | Да (сессия) |
| `/v2/app` | UI CRUD (createUserRouter) | resolveContext |
| `/v2/admin` | Админка (пустышка) | resolveContext |
| `/v2/test` | Тестовый API (`?action=...`) | Нет |
| `/v2/test/chaos` | Параллельный хаос-тест | Нет |
| `/v2/logout` | Редирект на `/logout` | Нет |
### Деплой
git push → Gitea → Nubes UI redeploy → `whitelist.nodejsk8s.services.ngcloud.ru`
VM (italo.kube5s.ru) — НЕ используется для деплоя v2.
---
## Тесты — полный список
### 1. test.sh — 54 curl-теста (✅ все пройдены)
**Запрещённые диапазоны (14 тестов):**
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, 127.0.0.0/8,
169.254.0.0/16, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24,
198.18.0.0/15, 224.0.0.0/4, 240.0.0.0/4, 255.255.255.255/32
**Нормализация и маски (5 тестов):**
- /22 работает, /21 отклонена, /33 отклонена, IPv6 отклонён, домен отклонён
- Нормализация хостовой части (13.0.0.5/24 → 13.0.0.0/24)
- wasNormalized=true
**Лимиты (2 теста):**
- 16-я запись отклонена (лимит 15)
- Сообщение о лимите
**CRUD полный цикл (10 тестов):**
- Добавление, добавление 2, добавление /32
- Список — 3 записи
- Изменение CIDR, проверка в БД
- Soft delete, список после удаления, с удалёнными
**Изоляция компаний (3 теста):**
- Добавление в компанию A/B, пересечение разрешено
**Переключение компаний (5 тестов):**
- Добавление в активную, переключение, список, добавление в другую, обратно
**Имперсонация — двойной аудит (6 тестов):**
- created_by = originalUserEmail
- audit: impersonated_by, user_email
- UPDATE: old→new записаны
- DELETE записан
**Нагрузка (2 теста):**
- 50 добавлений (первые 15 ок, остальные лимит)
- БД: ровно 15 записей
**Экспорт (1 тест):**
- Эндпоинт доступен
### 2. Chaos-тест — параллельные пользователи (✅)
`GET /v2/test/chaos` — 4 компании × 10 записей = 40 параллельных операций.
Проверки:
- ok: 40, errors: 0
- totalEntries: 40, totalAudit: 40
- 4 компании по 10 записей, без дубликатов, в лимите
Префиксы CIDR: 11, 12, 13, 14 (10.x заблокирован 10.0.0.0/8).
### 3. Router — resolveContext (✅ 9 тестов)
Файл: `v2/src/router/test.js` (или внутренние).
1. нет сессии → /v2/login
2. нет user → /v2/login
3. обычный юзер 1 компания
4. юзер 2 компании → activeClientId
5. админ adminMode=true
6. админ adminMode=false
7. имперсонация с originalUserEmail
8. имперсонация без originalUserEmail
9. без activeClientId → fallback на clientId
### Сводка
| Группа | Кол-во | Статус |
|--------|--------|--------|
| test.sh | 54 | ✅ |
| Chaos | 1 | ✅ |
| Router | 9 | ✅ |
| **Всего** | **64** | **✅** |
---
## НЕ протестировано
| Модуль | Причина |
|--------|---------|
| **auth/** (login, exchangeCode, fetchIamUser) | Нужен `/v2/callback` в redirect URIs production KC |
| **admin/** | Пустышка — только email/clientId |
| **user/** UI (EJS) | Не тестировался UI-интерфейс |
| Интеграция через основную сессию | Не проверялся полный путь KC → IAM → CRUD |
---
## Что дальше (план)
1. Реализовать **admin/** — аудит, лимиты, все компании
2. Реализовать **export/** — выгрузка CIDR
3. Добавить `/v2/callback` в production KC → протестировать auth/
4. EJS-шаблоны вместо inline HTML
5. Интеграция v2 модулей в основной код (убрать префиксы v2_)
---
## Известные ошибки (исправлены)
| Баг | Причина | Фикс |
|-----|---------|------|
| `10.x` CIDR → 45 ошибок в chaos | `10.0.0.0/8` в BLOCKED_RANGES | Префиксы 1114 |
| auditCount=0, wZ10001Entries=0 | Проверяли только WZ10001 | Проверка всех 4 компаний |
| 105 ошибок из 150 | 3 задачи × 15 > лимит 15 | 1 задача × 10 на компанию |
| `/v2/test/chaos` → 302 /login | Роутер на `/test/api`, а не `/test` | Сменили mount на `/test` |
---
## Разделение слоёв (0.5.90+) — ПЛАН
### Проблема
Сейчас `user/index.js` знает про `db/queries.js` и `getOrCreateCompany`/`companyId`:
```
user/index.js → db/queries.js → SQL
```
Фронтенд смешан с логикой БД.
### Решение: три слоя
```
user/index.js (фронтенд, Express) → crud/index.js (API БД) → db/queries.js (SQL)
```
**crud/index.js** — чистые функции-агностики:
- Не знает про Express, req, res, сессии
- Принимает `clientId` (W-номер), сам резолвит `companyId` через `getOrCreateCompany`
- Вход: plain values, Выход: plain object или throw
```js
list(clientId) { entries, used, limit }
add(clientId, cidr, comment, email, impBy) { entry, wasNormalized }
edit(entryId, clientId, cidr, comment, email, impBy) { entry, wasNormalized }
remove(entryId, clientId, email, impBy) void
```
**user/index.js** — только Express:
- Дёргает crud.*, рендерит HTML
- Не знает про companyId, getOrCreateCompany, SQL
**db/queries.js** — без изменений (чистый SQL)
### Что изменится
| Файл | Было | Стало |
|------|------|-------|
| crud/index.js | старый, не рабочий | новый API-слой |
| user/index.js | require('../db/queries') | require('../crud') |
| test/index.js | require('../db/queries') | require('../crud') |
### Преимущества
1. **Тестирование**: crud тестируется без Express, user тестируется с моком crud
2. **Переиспользование**: admin, test, export — все через crud
3. **Независимость**: фронтенд не знает про deviceId, БД-схему, транзакции