v2: fio — строка (fullName), не объект
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ipwhitelist",
|
"name": "ipwhitelist",
|
||||||
"version": "0.5.73",
|
"version": "0.5.74",
|
||||||
"description": "IP WhiteList microservice for cloud provider",
|
"description": "IP WhiteList microservice for cloud provider",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+52
-94
@@ -1,119 +1,77 @@
|
|||||||
# V2 — история 2026-06-12
|
# V2 — история 2026-06-12 (финал)
|
||||||
|
|
||||||
## Цель
|
## V2 — это тестовый стенд для модулей
|
||||||
Перепроектирование ipwhitelist-app. Начали с модуля аутентификации: Keycloak OIDC → IAM API → готовый sessionUser.
|
|
||||||
|
|
||||||
## Архитектура
|
Код в `v2/` — НЕ production. Это полигон для отладки модулей.
|
||||||
|
Каждый модуль тестируется изолированно, затем будет интегрирован в основной код.
|
||||||
|
|
||||||
### Принцип
|
## Текущее состояние (0.5.73)
|
||||||
Один вызов `login()` при логине. После этого ни Keycloak, ни IAM не нужны.
|
|
||||||
Переключение компаний — только в сессии (не через IAM switchProfile).
|
|
||||||
|
|
||||||
### Ответ IAM (`/api/v1/auth/user`)
|
|
||||||
См. `Files/architect.md` — задокументированы все поля.
|
|
||||||
|
|
||||||
### Два стенда
|
|
||||||
| Стенд | URL | Keycloak | IAM |
|
|
||||||
|-------|-----|----------|-----|
|
|
||||||
| Production | `whitelist.nodejsk8s.services.ngcloud.ru` | prod-KC | ✅ |
|
|
||||||
| VM (тест) | `italo.kube5s.ru` | локальный KC на :8080 | ❌ |
|
|
||||||
|
|
||||||
### clientId vs companyId
|
|
||||||
- `clientId` = WZ01112 (W-номер) — идентификатор компании в БД
|
|
||||||
- `companyId` = внутренний ID IAM, не W-формат, почти не используется
|
|
||||||
- `allClientIds` = массив всех W-номеров (собираем из `profiles[].client_id`)
|
|
||||||
|
|
||||||
## Созданные файлы
|
|
||||||
|
|
||||||
```
|
```
|
||||||
v2/
|
v2/
|
||||||
├── server.js # createV2Router() — монтируется в server.js как /v2
|
├── server.js # createV2Router() → /v2/login, /v2/iam, /v2/logout
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── config/index.js # приоритет: V2_KC_* → KC_* → умолчания
|
│ ├── auth/index.js # fetchIamUser(), login(), exchangeCode(), buildAuthUrl()
|
||||||
│ └── auth/index.js # login(), fetchIamUser(), exchangeCode(), buildAuthUrl(), generateState()
|
│ ├── config/index.js # iamUrl, appUrl, version (без KC — пока не нужен)
|
||||||
|
│ ├── crud/index.js # createCrudRouter() — НЕ монтирован (будет позже)
|
||||||
|
│ ├── db/
|
||||||
|
│ │ ├── index.js # pg pool
|
||||||
|
│ │ ├── queries.js # CRUD SQL
|
||||||
|
│ │ └── schema.js # ensureSchema(pool) — автосоздание v2_* таблиц
|
||||||
|
│ └── validators/index.js # CIDR validate, overlaps, BLOCKED_RANGES
|
||||||
└── history/
|
└── history/
|
||||||
└── 2026-06-12.md # этот файл
|
└── 2026-06-12.md
|
||||||
```
|
```
|
||||||
|
|
||||||
## v2/src/auth/index.js — функции
|
## Как работает сейчас
|
||||||
|
|
||||||
| Функция | Что | Вызывается |
|
1. `/v2/login` → редирект на `/login?returnTo=/v2/iam`
|
||||||
|---------|-----|-----------|
|
2. Основной OIDC: production-KC → `/callback` → сессия → редирект на `/v2/iam`
|
||||||
| `buildAuthUrl(config)` | URL редиректа на Keycloak | `GET /v2/login` |
|
3. `/v2/iam` → показывает IAM-данные из `req.session.user`
|
||||||
| `exchangeCode(code, config)` | code → access_token | внутри `login()` |
|
|
||||||
| `fetchIamUser(token, iamUrl)` | IAM → профиль | внутри `login()` |
|
|
||||||
| `generateState()` | CSRF-токен | `GET /v2/login` |
|
|
||||||
| `login(code, oidcConfig, iamUrl)` | оркестратор: всё сразу | `GET /v2/callback` |
|
|
||||||
|
|
||||||
## v2/src/config/index.js — приоритет
|
V2 НЕ делает свой OIDC. Использует готовую сессию основного приложения.
|
||||||
|
Никаких своих KC-настроек. Никакого `/v2/callback`.
|
||||||
|
|
||||||
```
|
## Модуль auth/index.js — готов, но не используется
|
||||||
V2_KC_BASE_URL → KC_BASE_URL → https://italo.kube5s.ru/realms/ipwhitelist
|
|
||||||
V2_KC_CLIENT_ID → KC_CLIENT_ID → ipwhitelist
|
|
||||||
V2_KC_CLIENT_SECRET → KC_CLIENT_SECRET → ''
|
|
||||||
V2_APP_URL → APP_URL → https://italo.kube5s.ru
|
|
||||||
V2_IAM_API_URL → IAM_API_URL → https://auth-api-dev.ngcloud.ru
|
|
||||||
```
|
|
||||||
|
|
||||||
## v2/server.js — роуты
|
Функции готовы к production:
|
||||||
|
- `buildAuthUrl(config)` — URL редиректа на KC
|
||||||
|
- `exchangeCode(code, config)` — обмен code → токен
|
||||||
|
- `fetchIamUser(token, iamUrl)` — IAM → профиль
|
||||||
|
- `generateState()` — CSRF
|
||||||
|
- `login(code, oidcConfig, iamUrl)` — оркестратор
|
||||||
|
|
||||||
| Путь | Что |
|
Не тестировались: нужен `/v2/callback` в redirect URIs production-KC.
|
||||||
|------|-----|
|
|
||||||
| `GET /v2/` | главная: IAM-данные или редирект на /v2/login |
|
|
||||||
| `GET /v2/login` | → Keycloak |
|
|
||||||
| `GET /v2/callback` | Keycloak → code → login() → сессия → /v2/ |
|
|
||||||
| `GET /v2/logout` | сброс v2_ ключей сессии |
|
|
||||||
|
|
||||||
Сессионные ключи с префиксом `v2_`: `v2_user`, `v2_token`, `v2_idToken`, `v2_oidcState`.
|
## Модуль crud/ — готов, не монтирован
|
||||||
Не пересекаются с основным приложением.
|
|
||||||
|
|
||||||
## server.js — изменения
|
Функции:
|
||||||
|
- `createCrudRouter()` — роутер с выбором компании (всегда список, даже если одна)
|
||||||
|
- CRUD через `db/queries.js`
|
||||||
|
|
||||||
Добавлено перед UI-роутером:
|
Таблицы: v2_companies, v2_entries, v2_audit (автосоздание через schema.js).
|
||||||
```js
|
|
||||||
const { createV2Router } = require('./v2/server');
|
|
||||||
app.use('/v2', createV2Router());
|
|
||||||
```
|
|
||||||
|
|
||||||
Порядок: `/healthz` → OIDC → `/api/v1/*` → `/v2/*` → UI (`/*`)
|
## Модуль db/ — готов
|
||||||
|
|
||||||
## Что сделано на VM (italo.kube5s.ru)
|
- `db/index.js` — pg pool
|
||||||
|
- `db/queries.js` — getOrCreateCompany, listEntries, createEntry, updateEntry, deleteEntry, getAudit, ...
|
||||||
|
- `db/schema.js` — ensureSchema(pool) — CREATE TABLE IF NOT EXISTS
|
||||||
|
|
||||||
### Keycloak
|
## Модуль validators/ — готов
|
||||||
- Realm `ipwhitelist`, frontendUrl=`https://italo.kube5s.ru`
|
|
||||||
- Client `ipwhitelist`, redirectUris=`['https://italo.kube5s.ru/v2/callback']`
|
|
||||||
- Пользователь: `test` / `test`
|
|
||||||
- Client secret: `40bpIZvumq6jttIB5QtTLcl9AJvAHxlw`
|
|
||||||
- Доступ через nginx: `/realms/*` → Keycloak:8080
|
|
||||||
|
|
||||||
### .env на ВМ
|
CIDR validate, overlaps, cidrToRange, aggregateCIDRs, BLOCKED_RANGES.
|
||||||
Добавлено: `V2_KC_CLIENT_SECRET=40bpIZvumq6jttIB5QtTLcl9AJvAHxlw`
|
|
||||||
|
|
||||||
### Деплой
|
|
||||||
```bash
|
|
||||||
rsync -az -e "ssh ..." /home/naeel/ipwhitelist-app/v2 naeel@5.172.178.213:~/ipwhitelist/
|
|
||||||
ssh ... 'pm2 restart ipwhitelist'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Git
|
|
||||||
- Версия: `0.5.57` → `0.5.58`
|
|
||||||
- Коммит: `5c09844` — v2: модуль аутентификации + роутер /v2
|
|
||||||
- Запушено в `master` на gitea.services.ngcloud.ru
|
|
||||||
|
|
||||||
## Ошибки в процессе
|
|
||||||
|
|
||||||
1. `rsync v2/` с trailing slash → содержимое v2/ скопировалось в `~/ipwhitelist/`, v2/server.js перезаписал основной server.js
|
|
||||||
- Fix: rsync без trailing slash (`rsync ... v2`)
|
|
||||||
2. `sed` заменил оба вхождения `italo.kube5s.ru` в конфиге (kcBaseUrl и appUrl)
|
|
||||||
- Fix: переписал файл полностью
|
|
||||||
3. `kcBaseUrl` без `/realms/ipwhitelist` → редирект на неверный URL Keycloak
|
|
||||||
- Fix: `https://italo.kube5s.ru/realms/ipwhitelist`
|
|
||||||
4. На ВМ старый `ui/index.js` с багом (дубликат catch) → краш приложения
|
|
||||||
- Fix: rsync --force ui/index.js
|
|
||||||
|
|
||||||
## Что дальше
|
## Что дальше
|
||||||
|
|
||||||
1. Дождаться редеплоя на production (Nubes UI)
|
1. fio в fetchIamUser — возвращать строку (сейчас объект)
|
||||||
2. Проверить `https://whitelist.nodejsk8s.services.ngcloud.ru/v2/login`
|
2. Добавить `/v2/callback` в redirect URIs production-KC
|
||||||
3. Если prod-KC не разрешает `/v2/callback` → добавить в VM-шный KC и задать V2_KC_BASE_URL на production
|
3. Протестировать auth/login() с production-KC
|
||||||
4. Реализовать IAM-фолбэк (если IAM недоступен → JWT claims)
|
4. Подключить crud модуль
|
||||||
|
5. Админка, экспорт
|
||||||
|
|
||||||
|
## Ключевые решения
|
||||||
|
|
||||||
|
- V2 НЕ трогает основной код (server.js — только app.use('/v2', ...))
|
||||||
|
- Каждый модуль — отдельная папка в src/
|
||||||
|
- env-переменные — через process.env, без .env/dotenv
|
||||||
|
- Умолчания — хардкод, переопределяются через V2_* env
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ async function fetchIamUser(token, iamUrl) {
|
|||||||
companyId: ui.companyId || '', // внутр. ID IAM (не W-формат)
|
companyId: ui.companyId || '', // внутр. ID IAM (не W-формат)
|
||||||
companyName: ui.company || activeProfile.company_name || '',
|
companyName: ui.company || activeProfile.company_name || '',
|
||||||
isAdmin: !!ui.isAdmin,
|
isAdmin: !!ui.isAdmin,
|
||||||
fio: ui.fio || null,
|
fio: (ui.fio && ui.fio.fullName) || ui.fio || null,
|
||||||
|
|
||||||
// ── из profiles ──
|
// ── из profiles ──
|
||||||
profiles, // все компании (массив)
|
profiles, // все компании (массив)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// ═══════════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
version: '0.5.73',
|
version: '0.5.74',
|
||||||
iamUrl: process.env.V2_IAM_API_URL || 'https://auth-api.ngcloud.ru',
|
iamUrl: process.env.V2_IAM_API_URL || 'https://auth-api.ngcloud.ru',
|
||||||
appUrl: process.env.V2_APP_URL || 'https://whitelist.nodejsk8s.services.ngcloud.ru',
|
appUrl: process.env.V2_APP_URL || 'https://whitelist.nodejsk8s.services.ngcloud.ru',
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user