diff --git a/docs/README.md b/docs/README.md index 233e4d8..a1070fe 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,6 +18,7 @@ | [architecture.md](architecture.md) | Компоненты, потоки данных, пакеты | | [manual.md](manual.md) | Подробное руководство по модулям, процессам и API | | [api.md](api.md) | REST: префикс `/v1`, публичные маршруты, ссылки на OpenAPI | +| [router-lists-ui-integration.md](router-lists-ui-integration.md) | Интеграция `router-lists-ui` с EvoBGP API (`DOMAINS/IP_RANGES/AS_PREFIXES/communities`) | | [access.md](access.md) | Выдача доступа: API-ключи, роли, нода, CORS | | [openapi.yaml](openapi.yaml) | Источник правды по контракту API | | [OPENAPI-GITEA.md](OPENAPI-GITEA.md) | Как открыть HTML-документацию API (в т.ч. из Gitea) | diff --git a/docs/router-lists-ui-integration.md b/docs/router-lists-ui-integration.md new file mode 100644 index 0000000..8a529f4 --- /dev/null +++ b/docs/router-lists-ui-integration.md @@ -0,0 +1,117 @@ +# Интеграция router-lists-ui с EvoBGP API + +Документ описывает подключение разделов `Домены`, `IP-диапазоны`, `AS`, `Community` из проекта `router-lists-ui` напрямую к EvoBGP API (`/v1`). + +Источник правды по контракту: [openapi.yaml](openapi.yaml). + +## 1. Базовые требования + +- Base URL API: `https:///v1` +- Аутентификация: `Authorization: Bearer ` +- CORS на стороне EvoBGP: переменная `EVOBGP_CORS_ORIGINS` +- Роли: + - чтение: `viewer+` + - изменение данных: `editor+` + - apply/деплой: `operator` + +## 2. Маппинг legacy -> EvoBGP + +| Раздел UI | Legacy endpoint | EvoBGP endpoint | +|---|---|---| +| Домены | `/api/domains-new` | `/v1/modules?type=DOMAINS` + `/v1/modules/{module_id}/domain-entries` | +| IP-диапазоны | `/api/ip-ranges` | `/v1/modules?type=IP_RANGES` + `/v1/modules/{module_id}/ip-range-entries` | +| AS | `/api/asns` | `/v1/modules?type=AS_PREFIXES` + `/v1/modules/{module_id}/as-entries` | +| Community | `/api/communities` | `/v1/communities` | + +## 3. Маппинг полей + +| Legacy модель | EvoBGP модель | Комментарий | +|---|---|---| +| `{ domain, community }` | `DomainEntry { fqdn, community_id }` | `community` в UI резолвится в `community_id` через `/v1/communities` | +| `{ ipRange, community }` | `IpRangeEntry { prefix, community_id }` | Для `IP_RANGES` `community_id` обязателен | +| `{ domain, type }` (AS) | `AsEntry { asn, community_id }` | `domain` legacy = ASN | +| `{ value, name }` (Community dict) | `BgpCommunity { community, title }` | `value -> community`, `name -> title` | + +## 4. Алгоритм работы по разделам + +### 4.1 Домены / IP / AS (общая схема) + +1. Найти модуль нужного типа через `GET /v1/modules?type=...`. +2. Если модуль отсутствует, создать через `POST /v1/modules`. +3. Загрузить entries: + - домены: `GET /v1/modules/{module_id}/domain-entries` + - IP: `GET /v1/modules/{module_id}/ip-range-entries` + - AS: `GET /v1/modules/{module_id}/as-entries` +4. При сохранении: + - удалить отсутствующие записи (`DELETE .../{entry_id}`) + - обновить изменённые (`PATCH .../{entry_id}`) + - добавить новые (`POST ...`) + +### 4.2 Community + +1. Получить список: `GET /v1/communities` +2. Для сохранения diff: + - новые -> `POST /v1/communities` + - изменённые -> `PATCH /v1/communities/{id}` + - удалённые -> `DELETE /v1/communities/{id}` + +## 5. Разрешение community + +- Перед работой с entries загрузить `/v1/communities`. +- Основной путь: сопоставление по `id`. +- Для UI-формы использовать значение `community` (например, `65001:120`) и перед записью преобразовывать в `community_id`. +- Если community не найдена: + - для `IP_RANGES` считать ошибкой валидации; + - для `DOMAINS` и `AS_PREFIXES` можно передать `null` только если это допускается бизнес-логикой. + +## 6. Пагинация и ошибки + +- Списки используют `cursor + limit`. +- Формат ошибок: `application/problem+json` (RFC 9457). +- Базовая обработка: + - `401` — неверный/отсутствующий токен + - `403` — недостаточно прав + - `404` — ресурс не найден + - `422` — ошибка валидации + +## 7. Примеры (PowerShell) + +```powershell +$base = "http://localhost:8080/v1" +$token = "YOUR_API_KEY" +$h = @{ Authorization = "Bearer $token" } + +# 1) Найти модуль DOMAINS +$modules = Invoke-RestMethod -Uri "$base/modules?type=DOMAINS&limit=50" -Headers $h +$moduleId = $modules.items[0].id + +# 2) Прочитать домены +Invoke-RestMethod -Uri "$base/modules/$moduleId/domain-entries?limit=100" -Headers $h +``` + +```powershell +# Создать community +$body = @{ + community = "65001:120" + title = "Video" +} | ConvertTo-Json + +Invoke-RestMethod -Method Post -Uri "$base/communities" -Headers $h -ContentType "application/json" -Body $body +``` + +## 8. Настройки router-lists-ui для прямой интеграции + +Рекомендуемые переменные frontend: + +- `VITE_EVOBGP_API_URL` (по умолчанию `/v1`) +- `VITE_EVOBGP_API_TOKEN` (опционально; либо хранить токен в `localStorage` как `evobgp_api_token`) + +Для dev-прокси Vite добавить маршрут `/v1 -> http://localhost:8080`. + +## 9. Контрольный список интеграции + +- [ ] `Домены`: list/create/update/delete работают через `/v1/modules/{id}/domain-entries` +- [ ] `IP-диапазоны`: list/create/update/delete работают через `/v1/modules/{id}/ip-range-entries` +- [ ] `AS`: list/create/update/delete работают через `/v1/modules/{id}/as-entries` +- [ ] `Community`: CRUD работает через `/v1/communities` +- [ ] ошибки `problem+json` корректно отображаются в UI