794 lines
26 KiB
YAML
794 lines
26 KiB
YAML
openapi: 3.0.3
|
||
|
||
info:
|
||
title: Comparisons Service API
|
||
version: "1.0.0"
|
||
description: |
|
||
REST API сервиса **comparisons-backend** (`pdm/comparisons-backend`) — создание и
|
||
просмотр сравнений (облако-BIM отклонение/статусы, облако-облако, облако-поверхность,
|
||
pdf-pdf), их элементов, изменений и фильтров.
|
||
|
||
Сервис написан на Go (роутер **gorilla/mux**). Сервер собирается функцией
|
||
`bootstrapAPI` в `cmd/api/bootstrap.go`. Роутинг состоит из двух групп:
|
||
|
||
- публичный API — префикс `/api/v1` (`cmd/api/routes_api.go`);
|
||
- внутренний API — префикс `/internal/v1` (`cmd/api/routes_internal.go`),
|
||
предназначен для вызовов внутри кластера (через ingress не публикуется).
|
||
|
||
### Аутентификация
|
||
Публичные эндпоинты (`/api/v1/*`) требуют JWT: middleware `auth.JWTToCtx` +
|
||
`auth.JWTUserExtractorFromCtx` (`gitlab.com/sarex-team/gotools/auth`). Токен
|
||
передаётся заголовком `Authorization: Bearer <jwt>`; middleware
|
||
`auth.DeleteJWTFromQueryMiddleware` дополнительно позволяет передать токен
|
||
query-параметром `jwt` (он удаляется из запроса после разбора).
|
||
|
||
Внутренние эндпоинты (`/internal/v1/*`) аутентификации на уровне приложения
|
||
не требуют — ограничение доступа обеспечивается сетевым слоем.
|
||
|
||
### Обработка ошибок
|
||
Ошибки возвращаются функцией `httperror.Write` (`gotools/httperror`). Основные
|
||
статусы: `400` — некорректный запрос/параметры, `404` — сравнение не найдено,
|
||
`500` — внутренняя ошибка. Идентификатор запроса пробрасывается middleware
|
||
`reqid`.
|
||
|
||
### Замечания (расхождения кода)
|
||
- `GET /api/v1/comparisons` возвращает данные разной формы в зависимости от
|
||
query-параметра: `workspace_id` → `{ comparisons: [] }`, `document_id` →
|
||
`{ results: [] }`, `bundle_id` → одиночный объект сравнения.
|
||
- `GET /api/v1/filter_fields` и `GET /api/v1/elements` работают только со
|
||
сравнениями типа `deviation`; для других типов вернётся `400`.
|
||
- Схема сравнения полиморфна по полю `type` (`deviation`/`c2c`/`c2s`/`abap`/`pdf2pdf`).
|
||
|
||
contact:
|
||
name: comparisons-backend
|
||
url: https://gitlab.com/sarex-team/comparisons-backend
|
||
|
||
servers:
|
||
- url: https://api.sarex.io/comparisons
|
||
description: Production (ingress)
|
||
- url: https://stage-api.sarex.io/comparisons
|
||
description: Stage (ingress)
|
||
- url: https://api.preprod.sarex.io/comparisons
|
||
description: Preprod (ingress)
|
||
- url: http://comparisons-backend-service.comparisons-stage
|
||
description: Внутрикластерный адрес (ClusterIP). Единственный способ достучаться до /internal/v1
|
||
- url: http://localhost:8080
|
||
description: Локальный запуск (API_ADDRESS по умолчанию 0.0.0.0:8080)
|
||
|
||
tags:
|
||
- name: types
|
||
description: Справочник типов сравнений
|
||
- name: comparisons
|
||
description: Сравнения — создание, просмотр, удаление
|
||
- name: elements
|
||
description: Элементы сравнения и их изменения
|
||
- name: internal
|
||
description: Внутренние эндпоинты (только внутри кластера)
|
||
|
||
security:
|
||
- bearerAuth: []
|
||
|
||
paths:
|
||
# ==========================================================================
|
||
# Types
|
||
# ==========================================================================
|
||
/api/v1/types:
|
||
get:
|
||
tags: [types]
|
||
summary: Справочник типов сравнений
|
||
description: Возвращает доступные типы сравнений и их параметры (для построения форм).
|
||
operationId: getTypes
|
||
responses:
|
||
'200':
|
||
description: Список типов сравнений
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
types:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/CompareType'
|
||
|
||
# ==========================================================================
|
||
# Comparisons
|
||
# ==========================================================================
|
||
/api/v1/comparisons:
|
||
post:
|
||
tags: [comparisons]
|
||
summary: Создать сравнение
|
||
description: |
|
||
Создаёт сравнение указанного типа. Автор берётся из JWT. Если `parent_doc_id`
|
||
и `parent_disk_id` не заданы — вычисляются по рабочей области.
|
||
operationId: createComparison
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CreateRequest'
|
||
responses:
|
||
'200':
|
||
description: Созданное сравнение
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Comparison'
|
||
'400':
|
||
description: Некорректный запрос / неизвестный тип сравнения
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
get:
|
||
tags: [comparisons]
|
||
summary: Список сравнений
|
||
description: |
|
||
Возвращает сравнения по одному из query-параметров. Форма ответа зависит
|
||
от параметра (см. описание в `info`). Должен быть задан ровно один параметр.
|
||
operationId: getComparisons
|
||
parameters:
|
||
- name: workspace_id
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
description: "Сравнения рабочей области → ответ `{ comparisons: [] }`"
|
||
- name: bundle_id
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
description: Сравнение по бандлу → ответ — одиночный объект
|
||
- name: document_id
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
description: "Сравнения документа → ответ `{ results: [] }`"
|
||
responses:
|
||
'200':
|
||
description: Результат (форма зависит от параметра запроса)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- type: object
|
||
properties:
|
||
comparisons:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Comparison'
|
||
- type: object
|
||
properties:
|
||
results:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Comparison'
|
||
- $ref: '#/components/schemas/Comparison'
|
||
'400':
|
||
description: Не задан workspace_id / bundle_id / document_id
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
/api/v1/comparisons/{comparison_id}:
|
||
parameters:
|
||
- name: comparison_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
get:
|
||
tags: [comparisons]
|
||
summary: Сравнение по id
|
||
operationId: getComparisonById
|
||
responses:
|
||
'200':
|
||
description: Сравнение
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Comparison'
|
||
'404':
|
||
description: Сравнение не найдено
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
delete:
|
||
tags: [comparisons]
|
||
summary: Удалить сравнение
|
||
description: Мягкое удаление сравнения. Автор берётся из JWT.
|
||
operationId: deleteComparisonById
|
||
responses:
|
||
'200':
|
||
description: Успешно удалено
|
||
'400':
|
||
description: Некорректный id
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
/api/v1/filter_fields:
|
||
get:
|
||
tags: [comparisons]
|
||
summary: Поля фильтрации сравнения
|
||
description: |
|
||
Возвращает набор полей фильтрации для сравнения типа `deviation` по документу.
|
||
Для полей отклонения (`deviation`, `deviation_x/y/z`) заполняются `min`/`max`.
|
||
Если сравнение по документу не найдено — вернётся пустой `results`.
|
||
operationId: getFilterFields
|
||
parameters:
|
||
- name: doc_id
|
||
in: query
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
responses:
|
||
'200':
|
||
description: Поля фильтрации
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
results:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/FilterFields'
|
||
'400':
|
||
description: Не задан doc_id / сравнение не типа deviation
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
/api/v1/tolerance:
|
||
get:
|
||
tags: [comparisons]
|
||
summary: Допуск (tolerance) сравнения
|
||
description: Возвращает значение допустимого отклонения для сравнения типа `deviation` по бандлу.
|
||
operationId: getTolerance
|
||
parameters:
|
||
- name: bundle_id
|
||
in: query
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Допуск
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
tolerance:
|
||
type: number
|
||
format: double
|
||
'400':
|
||
description: Не задан / некорректный bundle_id
|
||
'404':
|
||
description: Сравнение не найдено
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
# ==========================================================================
|
||
# Elements
|
||
# ==========================================================================
|
||
/api/v1/elements:
|
||
get:
|
||
tags: [elements]
|
||
summary: Список элементов сравнения
|
||
description: |
|
||
Постранично возвращает элементы сравнения типа `deviation` по документу.
|
||
Параметры отклонения задаются строкой вида `min:max`. Если сравнение не
|
||
найдено — вернётся пустой `results` с типами по умолчанию.
|
||
operationId: getListElements
|
||
parameters:
|
||
- name: doc_id
|
||
in: query
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
- name: limit
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
default: 10
|
||
minimum: 0
|
||
- name: offset
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
default: 0
|
||
minimum: 0
|
||
- name: order_by
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
enum: [deviation, deviation_x, deviation_y, deviation_z, sarex_id, name]
|
||
default: sarex_id
|
||
- name: order
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
enum: [asc, desc]
|
||
default: asc
|
||
- name: deviation
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
description: Диапазон общего отклонения в формате `min:max`
|
||
- name: deviation_x
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
description: Диапазон отклонения по X в формате `min:max`
|
||
- name: deviation_y
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
description: Диапазон отклонения по Y в формате `min:max`
|
||
- name: deviation_z
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
description: Диапазон отклонения по Z в формате `min:max`
|
||
- name: deviation_status
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
enum: [in_tolerance, out_of_tolerance]
|
||
- name: view_status
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: string
|
||
enum: [viewed, not_viewed]
|
||
- name: only_with_comment
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: boolean
|
||
responses:
|
||
'200':
|
||
description: Страница элементов
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ListElementsResponse'
|
||
'400':
|
||
description: Некорректные параметры запроса
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
/api/v1/elements/{element_id}:
|
||
parameters:
|
||
- name: element_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
patch:
|
||
tags: [elements]
|
||
summary: Обновить элемент
|
||
description: |
|
||
Обновляет один из атрибутов элемента: комментарий, статус отклонения или
|
||
статус просмотра. Должно быть задано ровно одно из полей. Изменение
|
||
фиксируется записью в истории изменений.
|
||
operationId: updateElement
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/UpdateElementRequest'
|
||
responses:
|
||
'200':
|
||
description: Успешно обновлено (тело не возвращается)
|
||
'400':
|
||
description: Некорректный запрос
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
/api/v1/elements/{element_id}/changes:
|
||
get:
|
||
tags: [elements]
|
||
summary: История изменений элемента
|
||
operationId: getElementChanges
|
||
parameters:
|
||
- name: element_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
responses:
|
||
'200':
|
||
description: Список изменений
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
changes:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Change'
|
||
'400':
|
||
description: Некорректный element_id
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
# ==========================================================================
|
||
# Internal
|
||
# ==========================================================================
|
||
/internal/v1/comparisons/{comparison_id}/webhook:
|
||
post:
|
||
tags: [internal]
|
||
summary: Webhook результата сравнения (внутренний)
|
||
description: |
|
||
Вызывается после завершения обработки сравнения типа `deviation`. Скачивает
|
||
`deviation_json` из PDM-хранилища по бандлу, создаёт элементы сравнения и
|
||
возвращает содержимое `deviation_json`. Аутентификация на уровне приложения
|
||
не требуется.
|
||
operationId: comparisonWebhook
|
||
security: []
|
||
parameters:
|
||
- name: comparison_id
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
format: int64
|
||
responses:
|
||
'200':
|
||
description: Содержимое deviation_json
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DeviationJSON'
|
||
'404':
|
||
description: Сравнение не найдено
|
||
'500':
|
||
description: Внутренняя ошибка
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
JWT в заголовке `Authorization: Bearer <jwt>`. Допускается передача
|
||
query-параметром `jwt` (удаляется middleware после разбора).
|
||
|
||
schemas:
|
||
ComparisonType:
|
||
type: string
|
||
enum: [c2c, c2s, deviation, abap, pdf2pdf]
|
||
|
||
CompareType:
|
||
type: object
|
||
description: Тип сравнения и набор его параметров (для формы создания).
|
||
properties:
|
||
name:
|
||
$ref: '#/components/schemas/ComparisonType'
|
||
verbose_name:
|
||
type: string
|
||
params:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/CompareFormParam'
|
||
|
||
CompareFormParam:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
verbose_name:
|
||
type: string
|
||
hint:
|
||
type: string
|
||
source:
|
||
type: string
|
||
enum: [form, viewer]
|
||
type:
|
||
type: string
|
||
description: Тип поля (напр. cloud, bimv2, number, multichoice, choice, array, pdf, surface)
|
||
options:
|
||
type: array
|
||
items:
|
||
type: object
|
||
additionalProperties: true
|
||
default: {}
|
||
min:
|
||
type: number
|
||
format: double
|
||
max:
|
||
type: number
|
||
format: double
|
||
|
||
CreateRequest:
|
||
type: object
|
||
required: [name, workspace_id, type, company_id, params]
|
||
properties:
|
||
name:
|
||
type: string
|
||
workspace_id:
|
||
type: string
|
||
format: uuid
|
||
parent_doc_id:
|
||
type: integer
|
||
format: int64
|
||
nullable: true
|
||
parent_disk_id:
|
||
type: string
|
||
format: uuid
|
||
nullable: true
|
||
type:
|
||
$ref: '#/components/schemas/ComparisonType'
|
||
company_id:
|
||
type: integer
|
||
format: int64
|
||
params:
|
||
type: object
|
||
description: Параметры сравнения, зависят от type (см. /api/v1/types).
|
||
additionalProperties: true
|
||
|
||
Comparison:
|
||
type: object
|
||
description: |
|
||
Полиморфное сравнение. Поле `type` определяет набор `params`. Ниже приведён
|
||
пример для типа `deviation`; для других типов набор params отличается.
|
||
properties:
|
||
id:
|
||
type: integer
|
||
format: int64
|
||
type:
|
||
$ref: '#/components/schemas/ComparisonType'
|
||
created_by:
|
||
type: integer
|
||
format: int64
|
||
name:
|
||
type: string
|
||
workspace_id:
|
||
type: string
|
||
format: uuid
|
||
workflow_id:
|
||
type: string
|
||
format: uuid
|
||
nullable: true
|
||
document_id:
|
||
type: integer
|
||
format: int64
|
||
nullable: true
|
||
bundle_id:
|
||
type: string
|
||
format: uuid
|
||
nullable: true
|
||
params:
|
||
$ref: '#/components/schemas/DeviationParams'
|
||
|
||
DeviationParams:
|
||
type: object
|
||
properties:
|
||
cloud_bundle_id:
|
||
type: string
|
||
format: uuid
|
||
model_bundle_id:
|
||
type: string
|
||
format: uuid
|
||
down_sample_size:
|
||
type: number
|
||
format: double
|
||
resolution:
|
||
type: number
|
||
format: double
|
||
linear_margin:
|
||
type: number
|
||
format: double
|
||
tolerance:
|
||
type: number
|
||
format: double
|
||
sarex_ids:
|
||
type: array
|
||
items:
|
||
type: integer
|
||
format: int64
|
||
transformation:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
applied_statuses:
|
||
type: array
|
||
items:
|
||
type: string
|
||
crop_margin:
|
||
type: number
|
||
format: double
|
||
nullable: true
|
||
|
||
Element:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
format: int64
|
||
sarex_id:
|
||
type: integer
|
||
format: int64
|
||
name:
|
||
type: string
|
||
deviation_status:
|
||
type: string
|
||
enum: [in_tolerance, out_of_tolerance]
|
||
view_status:
|
||
type: string
|
||
enum: [viewed, not_viewed]
|
||
deviation:
|
||
type: number
|
||
format: double
|
||
deviation_x:
|
||
type: number
|
||
format: double
|
||
deviation_y:
|
||
type: number
|
||
format: double
|
||
deviation_z:
|
||
type: number
|
||
format: double
|
||
axis_and_angle:
|
||
type: object
|
||
description: Ось и угол поворота (utils.AxisAndAngle)
|
||
additionalProperties: true
|
||
comment:
|
||
type: string
|
||
nullable: true
|
||
bbox_matrix:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
reg_matrix:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
|
||
ListElementsResponse:
|
||
type: object
|
||
properties:
|
||
count:
|
||
type: integer
|
||
next:
|
||
type: string
|
||
nullable: true
|
||
previous:
|
||
type: string
|
||
nullable: true
|
||
types:
|
||
type: object
|
||
additionalProperties:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Option'
|
||
crop_margin:
|
||
type: number
|
||
format: double
|
||
nullable: true
|
||
results:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Element'
|
||
|
||
UpdateElementRequest:
|
||
type: object
|
||
description: |
|
||
Должно быть задано ровно одно из полей (`comment`, `deviation_status`,
|
||
`view_status`) — валидатор `required_without_all`.
|
||
properties:
|
||
comment:
|
||
type: string
|
||
deviation_status:
|
||
type: string
|
||
enum: [in_tolerance, out_of_tolerance]
|
||
view_status:
|
||
type: string
|
||
enum: [viewed, not_viewed]
|
||
|
||
Change:
|
||
type: object
|
||
properties:
|
||
id:
|
||
type: integer
|
||
format: int64
|
||
element_id:
|
||
type: integer
|
||
format: int64
|
||
created_at:
|
||
type: string
|
||
format: date-time
|
||
author:
|
||
type: integer
|
||
format: int64
|
||
changed_field:
|
||
type: string
|
||
enum: [deviation_status, view_status, comment]
|
||
old_value:
|
||
type: string
|
||
new_value:
|
||
type: string
|
||
|
||
FilterFields:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
enum: [deviation, deviation_x, deviation_y, deviation_z, deviation_status, view_status, only_with_comment]
|
||
verbose_name:
|
||
type: string
|
||
type:
|
||
type: string
|
||
enum: [checkbox, selector, slider]
|
||
options:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Option'
|
||
min:
|
||
type: number
|
||
format: double
|
||
nullable: true
|
||
max:
|
||
type: number
|
||
format: double
|
||
nullable: true
|
||
|
||
Option:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
verbose_name:
|
||
type: string
|
||
|
||
DeviationJSON:
|
||
type: object
|
||
properties:
|
||
crop_margin:
|
||
type: number
|
||
format: double
|
||
nodes:
|
||
type: object
|
||
additionalProperties:
|
||
$ref: '#/components/schemas/Node'
|
||
|
||
Node:
|
||
type: object
|
||
properties:
|
||
bbox_matrix:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
reg_matrix:
|
||
type: array
|
||
items:
|
||
type: number
|
||
format: double
|
||
node_name:
|
||
type: string
|