iac/apps/iam/ENDPOINTS.md

14 KiB
Raw Blame History

Эндпоинты сервиса iams-v2

Документ описывает все HTTP-эндпоинты, которые предоставляет сервис iams (IAM: пользователи, ресурсы/проекты, права доступа). В отличие от фронтенд-модулей, здесь описан контракт самого сервиса.

Как устроено взаимодействие

Сервер — Fiber (internal/controller/http/server.go). Маршруты регистрируются двумя наборами:

  • Внутренний контур (RegisterAPIRoutes) — без аутентификации на уровне приложения, доступ ограничивается сетевым слоем (не публикуется через ingress). Базовые группы: /api/v0, /api/admin/v0, /api/v1, /api/v2.
  • Внешний контур (RegisterExternalAPIRoutes) — регистрируется только при AUTH_ENABLED=true. Перед маршрутами выполняется разбор JWT (AuthMiddleware) и пометка контекста (ExternalAPIMiddleware, для админ-группы дополнительно ExternalUserAdminAPIMiddleware). Базовые группы: /external/api/v0, /external/api/admin/v0, /external/api/v1, /external/api/v2. Внешний контур публикует подмножество внутренних маршрутов, часть — только на чтение.

Глобальные middleware: requestid, recover, OTel (при OTEL_ENABLED и заданном OTEL_SERVICE_NAME), логирование.

Аутентификация (внешний контур)

Токен передаётся заголовком Authorization: Bearer <jwt> (internal/controller/http/jwt/parser.go). Подпись токена не проверяется — доверие делегируется вышестоящему gateway/virtual service. Схема разбора выбирается по заголовку Identity:

  • заголовок Identity отсутствует/пуст → legacy-формат (Django SimpleJWT);
  • заголовок Identity задан → Zitadel (клейм urn:zitadel:iam:user:metadata, значения полей — base64).

Формат ответов и ошибок

Успешные ответы — JSON (списки: { count, results }; часть эндпоинтов возвращает объект напрямую). Ошибки — JSON { "error": "...", "id": "..." } (httpx.Response). Доменный Kind маппится на HTTP-статус (httpx/error_resolve.go): InvalidArgument/OutOfRange400, Unauthenticated401, PermissionDenied403, NotFound404, Aborted/AlreadyExists409, PreconditionFailed412, ResourceExhausted429, Unavailable503, Internal/Unknown/DataLoss500. Идентификатор запроса — заголовок из requestid.

Пагинация и фильтры

Списки — через query limit/offset (по умолчанию limit=1000). Дополнительные фильтры задаются query-параметрами (напр. для /resource: parent_id, type, tenant_id, name, code, public_id, target_id, service_accounts; для /users: username, search, is_active, is_staff, is_superuser, service_account_id, id, company_id, departments, positions, groups).

Служебные эндпоинты

Метод Путь Назначение
GET /api/health Health-check: проверка БД и (при включении) Kafka. 200 — ok, 503 — недоступность зависимости

Внутренний контур

Users (/api/v0/users, /api/admin/v0, /api/v1)

Метод Путь Назначение
GET /api/v0/users Список пользователей (фильтры, пагинация)
POST /api/v0/users Создать пользователя (если включён use case)
PATCH /api/v0/users Массовое обновление пользователей (legacy bulk_update)
GET /api/v0/users/:id Пользователь по id
PUT /api/v0/users/:id Полное обновление пользователя
PATCH /api/v0/users/:id Частичное обновление пользователя
DELETE /api/v0/users/:id Удалить пользователя
POST /api/admin/v0/users/activation Активация/деактивация пользователей компании
POST /api/v1/users-with-resources Пользователи с их ресурсами (тело: tenant_id, id[])
GET /api/v1/users-grouped-by-resource/ Пользователи, сгруппированные по ресурсу (если включён use case)

Permission check (/api/v0)

Метод Путь Назначение
POST /api/v0/permissions-check Проверка набора прав пользователя (user_id, checks[])

Groups (/api/v0/groups)

Метод Путь Назначение
GET /api/v0/groups Список групп
POST /api/v0/groups Создать группу
POST /api/v0/groups/search Поиск групп (пагинация, сортировка, фильтры)
GET /api/v0/groups/:id Группа по id
PUT /api/v0/groups/:id Обновить группу
PATCH /api/v0/groups/:id Частично обновить группу
DELETE /api/v0/groups/:id Удалить группу

Positions (/api/v0/positions)

Метод Путь Назначение
GET /api/v0/positions Список должностей
POST /api/v0/positions Создать должность
GET /api/v0/positions/:id Должность по id
PUT /api/v0/positions/:id Обновить должность
PATCH /api/v0/positions/:id Частично обновить должность
DELETE /api/v0/positions/:id Удалить должность

Departments (/api/v0/departments)

Метод Путь Назначение
GET /api/v0/departments Список подразделений
POST /api/v0/departments Создать подразделение
GET /api/v0/departments/:id Подразделение по id
PUT /api/v0/departments/:id Обновить подразделение
PATCH /api/v0/departments/:id Частично обновить подразделение
DELETE /api/v0/departments/:id Удалить подразделение

Django permissions (/api/v0/permissions)

Метод Путь Назначение
GET /api/v0/permissions Список permission'ов
POST /api/v0/permissions Создать permission
POST /api/v0/permissions/search Поиск permission'ов
GET /api/v0/permissions/:id Permission по id
DELETE /api/v0/permissions/:id Удалить permission

Resource types v0 (/api/v0/resource-types)

Метод Путь Назначение
GET /api/v0/resource-types Список типов ресурсов
POST /api/v0/resource-types Создать тип
GET /api/v0/resource-types/:id Тип по id
PUT /api/v0/resource-types/:id Обновить тип
PATCH /api/v0/resource-types/:id Частично обновить тип
DELETE /api/v0/resource-types/:id Удалить тип

Resources v0 (/api/v0/resources)

Метод Путь Назначение
GET /api/v0/resources Список ресурсов (legacy v0)
POST /api/v0/resources Создать ресурс
GET /api/v0/resources/:id Ресурс по id
PUT /api/v0/resources/:id Обновить ресурс
PATCH /api/v0/resources/:id Частично обновить ресурс
DELETE /api/v0/resources/:id Удалить ресурс

Projects v0 (/api/v0/projects)

Метод Путь Назначение
GET /api/v0/projects Список проектов
POST /api/v0/projects Создать проект
GET /api/v0/projects/:publicID Проект по public id
PUT /api/v0/projects/:publicID Обновить проект
PATCH /api/v0/projects/:publicID Частично обновить проект
DELETE /api/v0/projects/:publicID Удалить проект

Widgets v0 (/api/v0/widgets)

Метод Путь Назначение
GET /api/v0/widgets Список виджетов
POST /api/v0/widgets Создать виджет
GET /api/v0/widgets/:publicID Виджет по public id
PUT /api/v0/widgets/:publicID Обновить виджет
PATCH /api/v0/widgets/:publicID Частично обновить виджет
DELETE /api/v0/widgets/:publicID Удалить виджет

Resources v1 (/api/v1/resource, /api/v1/targets, /api/v1/service-accounts)

Метод Путь Назначение
GET /api/v1/resource Список ресурсов (v1)
POST /api/v1/resource Создать ресурс
GET /api/v1/resource/:publicID Ресурс по public id
PUT /api/v1/resource/:publicID Обновить ресурс
PATCH /api/v1/resource/:publicID Частично обновить ресурс
DELETE /api/v1/resource/:publicID Удалить ресурс
GET /api/v1/targets/:target_id/resource Ресурс по target id (только внутренний)
GET /api/v1/resources-grouped-by-sa Ресурсы, сгруппированные по сервисному аккаунту (если включено)
GET /api/v1/service-accounts Список сервисных аккаунтов

Widgets v2 (/api/v2/resource)

Метод Путь Назначение
GET /api/v2/resource Список виджетов (v2)
POST /api/v2/resource Создать виджет
GET /api/v2/resource/:publicID Виджет по public id
PUT /api/v2/resource/:publicID Обновить виджет
PATCH /api/v2/resource/:publicID Частично обновить виджет
DELETE /api/v2/resource/:publicID Удалить виджет

Permissions v1 (/api/v1)

Метод Путь Назначение
GET /api/v1/resource_permission Список прав на ресурсы
POST /api/v1/resource_permission Создать права (пакет items[])
GET /api/v1/resource_permission/:id Право по id
DELETE /api/v1/resource_permission/:id Удалить право
PATCH /api/v1/permissions-bulk Массовое изменение прав (tenant_id, permissions)
GET /api/v1/company_resource_permission Список прав компании на ресурсы
POST /api/v1/company_resource_permission Создать права компании (пакет items[])
GET /api/v1/company_resource_permission/:id Право компании по id
DELETE /api/v1/company_resource_permission/:id Удалить право компании

Внешний контур (/external/api/*, только при AUTH_ENABLED=true)

Публикуется подмножество внутренних маршрутов; часть — только на чтение. Пути идентичны внутренним, но с префиксом /external/api.

Группа Маршруты Отличия от внутреннего контура
/external/api/v0/users GET /, GET /:id, PATCH / Только чтение + массовый PATCH (bulk)
/external/api/admin/v0/users POST /activation, полный CRUD /users Полный доступ (админ-группа)
/external/api/admin/v0/positions /positions (CRUD) Как внутренний
/external/api/admin/v0/departments /departments (CRUD) Как внутренний
/external/api/admin/v0/groups /groups (CRUD + search) Как внутренний
/external/api/admin/v0/permissions /permissions (django) Как внутренний
/external/api/v0/resource-types /resource-types (CRUD) Как внутренний
/external/api/v0/resources /resources (CRUD, v0) Как внутренний
/external/api/v0/projects GET /, GET /:publicID Только чтение
/external/api/v0/widgets /widgets (CRUD) Как внутренний
/external/api/v1/resource GET /, GET /:publicID Только чтение
/external/api/v2/resource /resource (виджеты v2, CRUD) Как внутренний
/external/api/v1/resource_permission CRUD-подмножество Как внутренний
/external/api/v1/permissions-bulk PATCH / Как внутренний
/external/api/v1/company_resource_permission CRUD-подмножество Как внутренний

Часть маршрутов регистрируется условно — только если соответствующий хендлер/use case подключён при инициализации сервера (проверки Has* в хендлерах). При отсутствии сервиса группа не регистрируется.