iac/apps/documentations/api-v2.openapi.yaml

1259 lines
44 KiB
YAML
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.

openapi: 3.0.3
info:
title: Documentation API v2
version: "1.0"
description: |
REST API сервиса **documentation-api-v2** (`pdm/documentation-api-v2`) —
Go-сервис домена «documentations» (v2): управление дисками, документами,
бандлами, data source, страницами, публичными ссылками, workflow-обработкой
и загрузкой файлов (в т.ч. multipart).
Сервис написан на Go (**Fiber v2**, `github.com/gofiber/fiber/v2`). HTTP-сервер
собирается в `internal/api/httpserver/server.go`. Спецификация ниже получена
конвертацией сгенерированной `swag`-схемы (`docs/swagger.yaml`, Swagger 2.0)
в OpenAPI 3.0.3 и нормализацией путей под реальные маршруты Fiber.
Роутинг состоит из двух групп (`server.go`, `App.Run`):
- публичный API — префикс `/api/v1`;
- внутренний API — префикс `/internal/v1` (для вызовов внутри кластера).
Интерактивная документация Swagger UI доступна по `/swagger/*`.
Служебный эндпоинт проб k8s — `GET /ping` (вне групп, без аутентификации).
### Аутентификация
JWT-middleware (`pkg/middleware/jwt_auth`) подключён **только к группе
`/api/v1`**. Токен передаётся заголовком `Authorization: Bearer <jwt>`
либо query-параметром `?auth_jwt=<jwt>` (`JWTToCtx`). Поддерживаются два
режима (`jwtauth.New`):
1. **Zitadel** — если передан заголовок `Identity: Bearer <jwt>`, полезная
нагрузка (`urn:zitadel:iam:user:metadata`) берётся из identity-токена
без проверки подписи (доверие обеспечивает Istio).
2. **sarex-backend** — если заголовка `Identity` нет, подпись основного
токена проверяется публичным RSA-ключом `PUBLIC_KEY` (PKIX).
Для маршрутов публичных/временных ссылок (`/api/v1/public/*` и
`download_type=temporary`) токен проверяется HMAC-секретом
`DOCUMENT_PUBLIC_LINK_JWT_SECRET`.
Эндпоинты `/internal/v1/*` middleware аутентификации на уровне приложения
**не проходят** — доступ ограничивается сетевым слоем кластера. (В исходной
swag-схеме параметр `Authorization` у них помечен как обязательный —
это артефакт аннотаций, а не рантайм-поведение.)
### Пагинация
Явной пагинации у списочных ответов нет: коллекции возвращаются целиком
(массивом или объектом-обёрткой, напр. `GetDiskListResponse.disks`,
`ServiceAccountsResponse.service_account`). Часть выборок ограничивается
параметрами запроса (`company_id`, `extend`, `upload_path`).
### Обработка ошибок
Ошибки возвращаются как JSON `application/json` со схемой `AppError` —
`{ message, error_code }` (`internal/api/apperrors`). Код `error_code`
определяет HTTP-статус (`apperrors/error_response.go`):
| `error_code` | Константа | HTTP-статус |
| --- | --- | --- |
| `PDM-0000` | SystemErrorCode | 500 |
| `PDM-0001` | ErrNotFoundCode | 404 |
| `PDM-0002` | ErrNoAuthCode | (ошибки авторизации → 401) |
| `PDM-0003` | ErrNoAccessCode | 403 |
| `PDM-0004` | ErrInvalidCode | 400 |
| `PDM-0005` | ErrGoneCode | 410 |
### Замечания (расхождения кода/схемы)
- Ошибки аутентификации middleware отдаёт статусом **401** (в swag-схеме
эти ответы не описаны — там только `400`/`404`/`500`).
- Ошибка «истёкшая публичная ссылка» маппится на **`410 Gone`**
(`ErrGoneCode`), а не на `404`.
- Путь загрузки части файла содержит двойной слэш —
`POST /api/v1/uploads//multipart/{upload_id}/{part_num}` (так в схеме и
маршруте).
- `api_server` задаёт очень большой `BodyLimit` (5 ТБ) для загрузки файлов.
contact:
name: Sarex
url: https://gitlab/pdm/documentation-api-v2
servers:
- url: http://api-v2-service.documentations
description: Stage (ClusterIP, порт 80 → 8080)
- url: http://api-v2-service.documentations-preprod
description: Preprod (ClusterIP)
- url: http://api-v2-service.documentations-prod
description: Production (ClusterIP)
- url: http://localhost:8000
description: Локальный запуск (API_ADDRESS)
tags:
- name: document
description: Документы (создание, изменение, перемещение, скачивание)
- name: disk
description: Диски и их проекты/сервис-аккаунты
- name: bundle
description: Бандлы и загрузка файлов
- name: page
description: Страницы data source
- name: upload
description: Multipart-загрузка
- name: workflow
description: Workflow-обработка и вебхуки
- name: workspace
description: Рабочие области
- name: permission
description: Типы прав доступа
- name: data_source
description: Data source (внутренние проверки)
security:
- bearerAuth: []
paths:
# ==========================================================================
# Documents (public /api/v1)
# ==========================================================================
/api/v1/documents:
post:
tags: [document]
summary: create document
description: Create document with bundle and data_sources.
operationId: createDocument
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateDocumentRequest'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Document'
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/types:
get:
tags: [document]
summary: types
description: Descriptions of possible documents.
operationId: getDocumentTypes
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/BundleTypeStruct'
/api/v1/documents/{document_id}:
get:
tags: [document]
summary: get document
description: >-
Get document by document_id and optional "extend". If "extend" is
"bundles", returns bundles with all data_sources and pages.
operationId: getDocument
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
- { name: extend, in: query, required: false, schema: { type: string }, example: bundles }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
patch:
tags: [document]
summary: change document
description: Change document's name.
operationId: changeDocument
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PatchDocument' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
delete:
tags: [document]
summary: delete document
description: Delete document (soft delete).
operationId: deleteDocument
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_id}/update-path:
patch:
tags: [document]
summary: move document to another folder
description: Move document to another folder.
operationId: updateDocumentPath
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PatchDocumentPath' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_id}/move_bundles:
patch:
tags: [document]
summary: move bundles
description: >-
Move bundles to document. The source document is marked as deleted if it
has no bundles left after the move.
operationId: moveBundles
parameters:
- { name: document_id, in: path, required: true, schema: { type: string }, example: "1" }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MoveBundleRequest' }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/Bundle' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_id}/add_bundle:
post:
tags: [document]
summary: add bundle to document
description: Add created and uploaded bundle to an existing document.
operationId: addBundleToDocument
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AddBundleRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Bundle' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_id}/ancestors:
get:
tags: [document]
summary: get ancestors of documents
operationId: getDocumentAncestors
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_id}/download:
get:
tags: [document]
summary: get url for download document
operationId: getDocumentDownloadURL
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/DownloadURLResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/documents/{document_ids}/company:
get:
tags: [document]
summary: get company_ids by document_ids
description: Get map of documents and companies.
operationId: getDocumentsCompanyMap
parameters:
- { name: document_ids, in: path, required: true, schema: { type: string }, example: "1,2,3,4,5" }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/DocumentCompanyMap' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Disks
# ==========================================================================
/api/v1/disks:
get:
tags: [disk]
summary: get disks
description: >-
Get disks. company_id requests disks of a specific company; by default
the user gets disks of all their companies.
operationId: getDisks
parameters:
- { name: company_id, in: query, required: true, schema: { type: integer }, example: 1 }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/GetDiskListResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
post:
tags: [disk]
summary: create disk
description: Create disk. Requires admin permissions in Django.
operationId: createDisk
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreateDiskRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Disk' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
delete:
tags: [disk]
summary: delete disk
description: >-
Soft delete of a disk (marks the disk, not the document, as deleted).
Requires admin permissions in Django. disk_id passed as path in the
underlying route.
operationId: deleteDisk
parameters:
- { name: disk_id, in: path, required: true, schema: { type: string }, example: 2e3bda68-09bb-4bc0-b3c3-984117256c8b }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/disks/{disk_id}/projects:
get:
tags: [disk]
summary: get projects
description: Get projects by disk_id.
operationId: getDiskProjects
parameters:
- { name: disk_id, in: path, required: true, schema: { type: string }, example: 2e3bda68-09bb-4bc0-b3c3-984117256c8b }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/GetDiskListResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/disks/{disk_id}/service_accounts:
get:
tags: [disk]
summary: get service accounts
description: Get service accounts by disk_id.
operationId: getDiskServiceAccounts
parameters:
- { name: disk_id, in: path, required: true, schema: { type: string }, example: 2e3bda68-09bb-4bc0-b3c3-984117256c8b }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/ServiceAccountsResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Bundles
# ==========================================================================
/api/v1/bundles/{bundle_id}/bucket_name:
get:
tags: [bundle]
summary: get bucket name
description: Get bucket name by bundle_id.
operationId: getBucketName
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/BucketNameResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/bundles/{bundle_id}/download:
get:
tags: [bundle]
summary: get url for download bundle
operationId: getBundleDownloadURL
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/DownloadURLResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/bundles/{bundle_id}/{bundle_key}/download:
get:
tags: [bundle]
summary: get url for download bundle (data_source)
description: Get url for download of a specific data_source of a bundle.
operationId: getBundleDataSourceDownloadURL
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
- { name: bundle_key, in: path, required: true, schema: { type: string }, example: las }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/DownloadURLResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/bundles/{bundle_id}/{bundle_key}/upload_multipart:
post:
tags: [bundle]
summary: initial multipart upload
description: Initialize a multipart upload for chunked file upload to storage.
operationId: initMultipartUpload
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
- { name: bundle_key, in: path, required: true, schema: { type: string }, example: potree }
- { name: upload_path, in: query, required: false, schema: { type: string }, example: r/1/1/2 }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/MultipartUpload' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/bundles/{bundle_id}/{bundle_key}/upload_single:
post:
tags: [bundle]
summary: upload single file
description: >-
Upload a single file to storage for a specific bundle. Bundle and
DataSource must already exist.
operationId: uploadSingleFile
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
- { name: bundle_key, in: path, required: true, schema: { type: string }, example: potree }
- { name: upload_path, in: query, required: false, schema: { type: string }, example: data/r/r.bin }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/bundles/{bundle_id}/upload_finish:
post:
tags: [bundle]
summary: finish upload
description: >-
Finish upload: change bundle status from "created" to "uploaded", update
data_source file sizes, check for files in storage.
operationId: finishUpload
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Bundle' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Pages
# ==========================================================================
/api/v1/pages:
post:
tags: [page]
summary: create page
description: Creates a page for a specified data_source_id.
operationId: createPage
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreatePageRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Page' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/pages/{data_source}/{page_key}/download:
get:
tags: [page]
summary: get download url page
operationId: getPageDownloadURL
parameters:
- { name: data_source, in: path, required: true, schema: { type: string }, example: "1" }
- { name: page_key, in: path, required: true, schema: { type: string }, example: "2" }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/DownloadURLResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Permissions
# ==========================================================================
/api/v1/permissions:
get:
tags: [permission]
summary: permission types
operationId: getPermissionTypes
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/PermissionType' }
# ==========================================================================
# Uploads (multipart parts)
# ==========================================================================
/api/v1/uploads//multipart/{upload_id}/{part_num}:
post:
tags: [upload]
summary: upload multipart upload part
description: >-
Upload a part of a file to storage. NB: the route contains a double
slash after `uploads` (as registered).
operationId: uploadMultipartPart
parameters:
- { name: upload_id, in: path, required: true, schema: { type: string } }
- { name: part_num, in: path, required: true, schema: { type: integer }, example: 1 }
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
required: [file]
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/uploads/multipart/{upload_id}/abort:
post:
tags: [upload]
summary: abort multipart upload
operationId: abortMultipartUpload
parameters:
- { name: upload_id, in: path, required: true, schema: { type: string } }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/uploads/multipart/{upload_id}/complete:
post:
tags: [upload]
summary: complete multipart upload
description: >-
Complete a multipart upload. When all parts are uploaded, marks parts in
storage and database as "completed".
operationId: completeMultipartUpload
parameters:
- { name: upload_id, in: path, required: true, schema: { type: string } }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Workflows
# ==========================================================================
/api/v1/workflows/{workflow_id}:
get:
tags: [workflow]
summary: get workflow
operationId: getWorkflow
parameters:
- { name: workflow_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Workflow' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
post:
tags: [workflow]
summary: webhook
description: >-
Determines and updates workflow status (and bundle workflow status). On
success both are set to "done"; if bundle has no document_id, status is
set to "No document".
operationId: workflowWebhook
parameters:
- { name: workflow_id, in: path, required: true, schema: { type: string } }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Workspaces
# ==========================================================================
/api/v1/workspaces:
post:
tags: [workspace]
summary: create workspace
description: Creates a workspace document that may include other documents.
operationId: createWorkspace
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreateWorkspaceRequest' }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/api/v1/workspaces/{ws_id}:
get:
tags: [workspace]
summary: get workspace document
description: Get document with workspace type.
operationId: getWorkspace
parameters:
- { name: ws_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Document' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
# ==========================================================================
# Internal (/internal/v1) — без app-аутентификации, только внутри кластера
# ==========================================================================
/internal/v1/bundles/{bundle_id}:
get:
tags: [bundle]
summary: get internal bundle
description: Get internal bundle by bundle_id.
operationId: getInternalBundle
security: []
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Bundle' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/internal/v1/bundles/{bundle_id}/workflow:
post:
tags: [bundle]
summary: add workflow
description: Add workflow to bundle.
operationId: addBundleWorkflow
security: []
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/Workflow' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/internal/v1/documents/{document_id}:
delete:
tags: [document]
summary: internal delete document
description: Internal delete document (soft delete).
operationId: internalDeleteDocument
security: []
parameters:
- { name: document_id, in: path, required: true, schema: { type: integer }, example: 999 }
responses:
'200': { description: OK }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
/internal/v1/is_folder/bundles/{bundle_id}/{bundle_key}:
get:
tags: [data_source]
summary: is data_source folder handler
description: Returns whether the data_source is a folder or not.
operationId: isDataSourceFolder
security: []
parameters:
- { name: bundle_id, in: path, required: true, schema: { type: string } }
- { name: bundle_key, in: path, required: true, schema: { type: string }, example: potree }
responses:
'200':
description: OK
content:
application/json:
schema: { $ref: '#/components/schemas/IsDataSourceFolderResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'404': { $ref: '#/components/responses/NotFound' }
'500': { $ref: '#/components/responses/ServerError' }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: >-
JWT в заголовке `Authorization: Bearer <jwt>` или в query-параметре
`auth_jwt`. Режим sarex-backend проверяется RSA-ключом `PUBLIC_KEY`;
режим Zitadel — по заголовку `Identity`.
responses:
BadRequest:
description: Bad Request
content:
application/json:
schema: { $ref: '#/components/schemas/AppError' }
NotFound:
description: Not Found
content:
application/json:
schema: { $ref: '#/components/schemas/AppError' }
ServerError:
description: Internal Server Error
content:
application/json:
schema: { $ref: '#/components/schemas/AppError' }
schemas:
ErrCodeType:
type: string
enum: [PDM-0000, PDM-0001, PDM-0002, PDM-0003, PDM-0004, PDM-0005]
description: >-
SystemErrorCode / ErrNotFoundCode / ErrNoAuthCode / ErrNoAccessCode /
ErrInvalidCode / ErrGoneCode
AppError:
type: object
properties:
message: { type: string }
error_code: { $ref: '#/components/schemas/ErrCodeType' }
AddBundleRequest:
type: object
required: [bundle_id]
properties:
bundle_id: { type: string }
BucketNameResponse:
type: object
properties:
bucket_name: { type: string }
Bundle:
type: object
properties:
attributes: { type: object, additionalProperties: true }
author: { $ref: '#/components/schemas/User' }
bim_id: { type: integer }
bundle_copied_from: { type: string }
created_at: { type: string }
data_sources:
type: array
items: { $ref: '#/components/schemas/DataSource' }
date: { type: string, description: optional field for django integration }
document_id: { type: integer }
has_digital_signature: { type: boolean }
has_qr_code: { type: boolean }
has_stamp: { type: boolean }
id: { type: string }
size: { type: integer }
type: { $ref: '#/components/schemas/BundleType' }
upload_status: { $ref: '#/components/schemas/BundleUploadStatus' }
workflow: { $ref: '#/components/schemas/Workflow' }
workflow_status: { $ref: '#/components/schemas/BundleWorkflowStatus' }
BundleKey:
type: string
enum:
- las
- potree
- e57
- clouds
- panoramas_json
- panoramas
- glb
- original
- tiles
- tif
- tif_dem
- metadata
- colored-relief-tif
- topographic_tiles
- geojson
- ap_rasterized_las
- ap_rasterized_potree
- ab_las
- ab_potree
- deviation_json
- bim
- bim_optimized
- bim_optimizedGz
- bim_metadata
- bim_metadataGz
- bim_metadata_static
- bim_metadata_staticGz
- diff_json
- ifc
- nwd
- rvt
- nwc
- abap_json
- cloud_ooc
- debug_abap_json
- pdf
- p7s
- xlsx
- dxf
- docx
- dwg
BundleKeyField:
type: object
properties:
allowed_extensions:
type: array
items: { type: string }
can_be_downloaded_by_user: { type: boolean }
can_be_uploaded_by_user: { type: boolean }
file: { type: boolean }
folder: { type: boolean }
key: { $ref: '#/components/schemas/BundleKey' }
required: { type: boolean }
title: { type: string }
BundleType:
type: string
enum:
- cloud
- bim
- bimv2
- surface
- other_files
- deviation
- dem
- orthophoto
- dxf
- ksg
- docx
- dwg
- pdf
- xlsx
- abap
- c2c
- c2s
BundleTypeStruct:
type: object
properties:
fields:
type: array
items: { $ref: '#/components/schemas/BundleKeyField' }
name: { $ref: '#/components/schemas/BundleType' }
title: { type: string }
BundleUploadStatus:
type: string
enum: [created, uploaded]
BundleWorkflowStatus:
type: string
enum: [created, skipped, done, errored]
CreateDiskRequest:
type: object
required: [admin_ids, company_id, storage_type]
properties:
admin_ids:
type: array
minItems: 1
items: { type: integer }
company_id: { type: integer }
storage_type:
type: string
maxLength: 50
enum: [sarex]
CreateDocumentRequest:
type: object
required: [disk_id, is_folder, name, parent_id]
properties:
bundle_id: { type: string }
disk_id: { type: string }
is_folder: { type: boolean }
is_project: { type: boolean }
name: { type: string, maxLength: 250 }
parent_id: { type: integer }
target_id: { type: integer }
CreatePageRequest:
type: object
properties:
data_source: { type: string }
id: { type: string }
page_order: { type: integer }
thumbnail: { type: string }
CreateWorkspaceRequest:
type: object
required: [disk_id, documents, name, parent_id]
properties:
disk_id: { type: string }
documents:
type: array
items: { type: integer }
name: { type: string, maxLength: 250 }
parent_id: { type: integer }
DataSource:
type: object
properties:
file_name: { type: string }
format: { $ref: '#/components/schemas/DataSourceFormat' }
id: { type: string }
key: { $ref: '#/components/schemas/BundleKey' }
pages:
type: array
items: { $ref: '#/components/schemas/Page' }
size: { type: integer }
type: { $ref: '#/components/schemas/DataSourceUploadType' }
DataSourceFormat:
type: string
enum: [glb, json, gz, s3d]
DataSourceUploadType:
type: string
enum: [file, folder]
DisableButton:
type: string
enum: [workspace, delete, rename, create, project, download, history, add_doc_to_ws, del_doc_from_ws]
Disk:
type: object
properties:
admin_ids:
type: array
items: { type: integer }
bucket_name: { type: string }
company_id: { type: integer }
created_at: { type: string }
disable_button:
type: array
items: { $ref: '#/components/schemas/DisableButton' }
document_id: { type: integer }
id: { type: string }
name: { type: string }
permissions_editable: { type: boolean }
storage_type: { type: string }
Document:
type: object
properties:
author: { $ref: '#/components/schemas/User' }
bundles:
type: array
items: { $ref: '#/components/schemas/Bundle' }
created_at: { type: string }
dashboard_id: { type: integer }
disable_button:
type: array
items: { $ref: '#/components/schemas/DisableButton' }
disk_id: { type: string }
document_copied_from: { type: integer }
files:
type: array
items: { type: integer }
folders:
type: array
items: { type: integer }
has_digital_signature: { type: boolean }
has_public_link: { type: boolean }
has_qr_code: { type: boolean }
has_stamp: { type: boolean }
id: { type: integer }
is_folder: { type: boolean }
name: { type: string }
path: { type: string }
project_id: { type: integer }
public_link: { type: string }
public_link_available: { type: boolean }
public_link_expiration_time: { type: string }
public_link_id: { type: string }
type: { $ref: '#/components/schemas/DocumentType' }
workspace_id: { type: string }
DocumentCompanyMap:
type: object
properties:
result:
type: object
additionalProperties: { type: integer }
DocumentType:
type: string
enum:
- workspace
- dashboard
- cloud
- bim
- bimv2
- project
- folder
- root
- surface
- pdf
- xlsx
- orthophoto
- dem
- dxf
- ksg
- docx
- dwg
DownloadURLResponse:
type: object
properties:
download_url: { type: string }
GetDiskListResponse:
type: object
properties:
disks:
type: array
items: { $ref: '#/components/schemas/Disk' }
IsDataSourceFolderResponse:
type: object
properties:
result: { type: boolean }
MoveBundleRequest:
type: object
required: [bundle_ids]
properties:
bundle_ids:
type: array
items: { type: string }
MultipartUpload:
type: object
properties:
upload_id: { type: string }
Page:
type: object
properties:
id: { type: string }
page_order: { type: integer }
thumbnail: { type: string }
PatchDocument:
type: object
required: [name]
properties:
name: { type: string }
PatchDocumentPath:
type: object
required: [parent_id]
properties:
parent_id: { type: integer }
PermissionType:
type: object
properties:
label: { type: string }
value: { type: string }
ServiceAccount:
type: object
properties:
id: { type: string }
name: { type: string }
type: { type: string }
username: { type: string }
ServiceAccountsResponse:
type: object
properties:
service_account:
type: array
items: { $ref: '#/components/schemas/ServiceAccount' }
User:
type: object
properties:
companies:
type: array
items: { type: integer }
departments:
type: array
items: { $ref: '#/components/schemas/UserDepartment' }
first_name: { type: string }
id: { type: integer }
is_superuser: { type: boolean }
last_name: { type: string }
positions:
type: array
items: { $ref: '#/components/schemas/UserPosition' }
service_account_id: { type: string }
username: { type: string }
UserDepartment:
type: object
properties:
id: { type: integer }
service_account_id: { type: string }
UserPosition:
type: object
properties:
id: { type: integer }
service_account_id: { type: string }
Workflow:
type: object
properties:
company_id: { type: integer }
created_at: { type: string }
id: { type: string }
name: { type: string }
state: { type: string }
task_runs:
type: array
items: { type: object, additionalProperties: true }
tasks:
type: array
items: { type: object, additionalProperties: true }
updated_at: { type: string }
valid_until: { type: string }