Files
mdm-ordinis/docs/integration/api/read-endpoints.md
T
Zimin A.N. b601c4636f feat(swagger): OAuth2/Keycloak PKCE flow в Swagger UI + docs links
OpenApiConfig:
- Добавлена OAuth2 security scheme (authorization_code flow с Keycloak
  realm `nstart`). Auth/token URLs из ordinis.openapi.oauth.issuer-uri
  configuration property (default: auth.nstart.space/realms/nstart).
- BearerAuth scheme сохранён secondary — для pre-issued tokens из CI/scripts.
- Servers list переупорядочен — prod первый, staging второй.
- Description обновлён с pointer на /docs/ для full integration guide.

application.yml:
- springdoc.swagger-ui.oauth: client-id (env override), use-pkce-with-
  authorization-code-grant=true. Public client `ordinis-swagger`
  настраивается отдельно в Keycloak — see keycloak-setup-swagger-client.md
  в ordinis-infra repo.
- ORDINIS_OPENAPI_OAUTH_ISSUER_URI env var для override realm на разных
  окружениях.

docs/integration/api/read-endpoints.md:
- Swagger UI section обновлён: акцент на Authorize button + Keycloak
  PKCE login (no client_secret needed), tip про bearerAuth fallback.

docs/index.md:
- Добавлен tab "Я хочу пощупать API" с link на Swagger UI.

После deploy:
- https://ordinis.k8s.264.nstart.cloud/swagger-ui.html  — Swagger UI
- https://ordinis.k8s.264.nstart.cloud/v3/api-docs      — OpenAPI spec
Authorize → выбрать oauth2 → Keycloak login (PKCE) → Try it out с JWT.
2026-05-08 00:08:29 +03:00

204 lines
6.0 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.
# Read-side endpoints
Read-API в Ordinis — отдельный deployable (`ordinis-read-api`, scaled 2× в проде)
работающий на Postgres replica. Запросы из read-api **не блокируют** writer'а.
Base URL:
| Среда | URL |
|---|---|
| prod | `https://ordinis.k8s.264.nstart.cloud/api/v1` |
| staging | `https://ordinis.k8s.265.nstart.cloud/api/v1` |
Все endpoints требуют JWT (см. [Авторизация](auth.md)).
## OpenAPI / Swagger UI
Interactive playground с **Keycloak login** (PKCE flow, без client_secret):
- **Swagger UI:** `https://ordinis.k8s.264.nstart.cloud/swagger-ui.html`
→ нажми **Authorize** → выбери `oauth2` → войдёшь через Keycloak.
После login каждый "Try it out" автоматически добавит JWT.
- **Spec JSON:** `https://ordinis.k8s.264.nstart.cloud/v3/api-docs`
- **Spec YAML:** `https://ordinis.k8s.264.nstart.cloud/v3/api-docs.yaml`
{% note tip %}
Если у тебя уже есть pre-issued service token (например для CI scripts) —
выбери схему `bearerAuth` в Authorize dialog и paste'ни raw JWT. PKCE flow
тогда не нужен.
{% endnote %}
Из spec'а можно generate'ить клиент:
```bash
openapi-generator-cli generate \
-i https://ordinis.k8s.264.nstart.cloud/v3/api-docs \
-g python \
-o ./altum-backend/clients/ordinis
```
Поддерживаются: Python, TypeScript, Go, Java, Kotlin, Ruby и др.
## `GET /api/v1/dictionaries`
Список доступных справочников (фильтрован по scope JWT'а).
```bash
curl -H "Authorization: Bearer $TOKEN" \
https://ordinis.k8s.264.nstart.cloud/api/v1/dictionaries
```
Response:
```json
[
{
"name": "spacecraft",
"displayName": "Космические аппараты",
"scope": "PUBLIC",
"schemaVersion": "1.0.0",
"recordsCount": 4
},
{
"name": "mission",
"displayName": "Миссии / программы",
"scope": "PUBLIC",
"schemaVersion": "1.0.0",
"recordsCount": 9
}
]
```
## `GET /api/v1/{name}/records`
{% note warning %}
**БЕЗ префикса `/dictionaries/`!** Read-api сидит на `/api/v1/{name}/records`.
Префикс `/api/v1/dictionaries/...` — это admin write controller (CRUD), у него
нет bulk-list эндпоинта.
{% endnote %}
Активные записи на момент `at` (default: сейчас).
### Параметры
| Параметр | Тип | Пример | Назначение |
|---|---|---|---|
| `lang` | string | `ru-RU`, `en-US` | Flatten i18n полей в строку. Короткие `ru`/`en` тоже. |
| `at` | ISO 8601 | `2026-05-04T12:00:00+03:00` | Bitemporal query — активные на момент. |
| `as_scope` | string | `PUBLIC,INTERNAL` | Legacy для anonymous + `allowQueryScope=true`. |
### Пример
```bash
curl -H "Authorization: Bearer $TOKEN" \
"https://ordinis.k8s.264.nstart.cloud/api/v1/spacecraft/records?lang=ru-RU"
```
Response:
```json
[
{
"businessKey": "RESURS-P-3",
"displayKey": "Ресурс-П № 3",
"scope": "PUBLIC",
"validFrom": "2025-01-01T00:00:00+03:00",
"validTo": "9999-12-31T23:59:59+03:00",
"data": {
"name": "Ресурс-П № 3",
"satelliteTypeCode": "EARTH-OBSERVATION-OPTICAL",
"launchDate": "2024-12-25",
"status": "active"
},
"version": 2
}
]
```
### Без `?lang` (raw i18n)
```json
"name": { "ru-RU": "Ресурс-П № 3", "en-US": "Resurs-P No.3" }
```
С `?lang=ru-RU`:
```json
"name": "Ресурс-П № 3"
```
Если запрошенного языка нет — fallback к `default_locale` (обычно `ru-RU`).
## `GET /api/v1/{name}/records/{businessKey}`
Одна запись. Параметры те же что у list.
```bash
curl -H "Authorization: Bearer $TOKEN" \
"https://ordinis.k8s.264.nstart.cloud/api/v1/spacecraft/records/RESURS-P-3?lang=ru"
```
`404 Not Found` — запись либо не существует, либо закрыта на момент `at`,
либо вне scope JWT'а (Ordinis скрывает существование).
## `GET /api/v1/{name}/records/{businessKey}/history`
Все версии записи (включая закрытые) для построения истории изменений в UI.
```json
[
{
"version": 1,
"validFrom": "2024-06-01T00:00:00+03:00",
"validTo": "2025-01-01T00:00:00+03:00",
"data": {...},
"txTime": "2024-06-01T10:23:45+03:00",
"changedBy": "admin@nstart.space",
"changeReason": "initial"
},
{
"version": 2,
"validFrom": "2025-01-01T00:00:00+03:00",
"validTo": "9999-12-31T23:59:59+03:00",
"data": {...},
"txTime": "2024-12-30T14:11:22+03:00",
"changedBy": "admin@nstart.space",
"changeReason": "Обновление статуса после успешного запуска"
}
]
```
Для consumers history endpoint обычно не нужен — это UI-feature.
## Spatial filters (geometry)
Если справочник имеет geometry поля (`spacecraft.aoi`, `mission.coverage_area`),
поддерживаются bbox + polygon фильтры:
### `?bbox=` (bounding box)
```
GET /api/v1/spacecraft/records?bbox=37.0,55.0,38.0,56.0
```
Format: `min_lon,min_lat,max_lon,max_lat` (WGS84). Возвращает записи где
`geometry` пересекает bbox через PostGIS `ST_Intersects` + GiST index.
### `?polygon=` (GeoJSON)
```
GET /api/v1/spacecraft/records?polygon={"type":"Polygon","coordinates":[[[37,55],[38,55],[38,56],[37,56],[37,55]]]}
```
Polygon — GeoJSON object (URL-encoded). Сложнее bbox, точнее.
## Дальше
- [События (Kafka outbox)](events.md) — push-обновления вместо polling
- [Bitemporal](bitemporal.md) — детали `validFrom`/`validTo` модели
- [Caching](caching.md) — стратегии актуализации