diff --git a/infrastructure/open-api.yaml b/infrastructure/open-api.yaml new file mode 100644 index 0000000..f979dce --- /dev/null +++ b/infrastructure/open-api.yaml @@ -0,0 +1,1212 @@ +openapi: 3.0.3 +info: + title: NoCopy API + description: API NoCopy + version: 1.0.0 + contact: + name: NoCopy + +servers: + - url: http://localhost:8080 + description: Локальный + - url: https://dev-workspace.not-copy.com/ + description: Дев + +tags: + - name: Auth + description: Аутентификация и регистрация + - name: Files + description: Работа с файлами (загрузка, скачивание, проверка) + - name: Data + description: Основные операции с данными + - name: Internal + description: Внутренние эндпоинты для администрирования + +paths: + /api/auth: + post: + tags: + - Auth + summary: Универсальный эндпоинт аутентификации + description: | + Обрабатывает запросы аутентификации по msg_id: + - **20001** - Вход в систему + - **20002** - Регистрация + - **20010** - Сброс пароля + operationId: handleAuth + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BaseRequest' + examples: + login: + summary: Вход в систему + value: + msg_id: 20001 + message_body: + email: "user@example.com" + password: "securePassword123" + register: + summary: Регистрация + value: + msg_id: 20002 + message_body: + fullName: "Vladislav Sergevich" + email: "321@mail.ru" + password: "qweqweqwe123" + phone: "+79994521523" + mail_verified: "false" + accountType: "b2c" + ip: "127.0.0.1" + user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)" + resetPassword: + summary: Сброс пароля + value: + version: 1 + msg_id: 20010 + message_body: + email: "user@example.com" + responses: + '200': + description: Успешный ответ + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + loginSuccess: + summary: Успешный вход + value: + msg_id: 20001 + message_code: 0 + message_desc: "Operation successful" + message_body: + token: "eyJhbGciOiJIUzI1NiIs..." + user_id: 123 + invalidCredentials: + summary: Неверные учетные данные + value: + msg_id: 20001 + message_code: 2 + message_desc: "Invalid credentials" + message_body: {} + userNotFound: + summary: Пользователь не найден + value: + msg_id: 20010 + message_code: 2 + message_desc: "User not found" + message_body: {} + + # = INTERNAL ENDPOINTS предназначены для работы с данными = + # = Для использования эндпоинтов предусмотрен только внутренний ключ X-Internal-Key (header) = + + /api/internal/data-info: + post: + tags: + - Internal + summary: Внутренняя информация (статистика) + description: | + Эндпоинт для получения внутренней статистики и информации. + operationId: handleInternalInfo + parameters: + - name: X-Internal-Key + in: header + required: true + description: Внутренний ключ для доступа к API + schema: + type: string + example: "your-internal-key-here" + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BaseRequest' + examples: + userInfo: + summary: Информация о пользователе + value: + msg_id: 30014 + message_body: + user_id: 123 + userFileInfo: + summary: Информация по файлам + value: + msg_id: 30019 + message_body: + top: 10, + type: "image" + tariffStatistic: + summary: Информация по таррифам + value: + msg_id: 30020 + message_body: + active_only: true + dynamicStatistic: + summary: Динамика + value: + msg_id: 30021 + fileUserStatistic: + summary: Статистика по файлам пользователей + value: + msg_id: 30022 + message_body: + active_only: true + violations: + summary: Нарушения + value: + msg_id: 30023 + subscribesStatistic: + summary: Подписки + value: + msg_id: 30024 + tokenStatistic: + summary: Подписки + value: + msg_id: 30025 + incomingStatistic: + summary: Доходы статистика + value: + msg_id: 30026 + complaintStatistic: + summary: Жалобы + value: + msg_id: 30029 + filesInfo: + summary: Информация о файлах + value: + msg_id: 40001 + message_body: + action: "get_all" + page: 1 + page_size: 10 + sort_by: "createdAt" + sort_direction: "desc" + tariffsInfo: + summary: Информация о тарифах + value: + msg_id: 40004 + message_body: + action: "get_all" + page: 1 + page_size: 10 + sort_by: "createdAt" + sort_direction: "desc" + + responses: + '200': + description: Ответ с запрашиваемой информацией + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + + /api/internal/data-control: + post: + tags: + - Internal + summary: Управление контентом + description: Эндпоинт для модерации и управления контентом. + operationId: handleInternalControl + parameters: + - name: X-Internal-Key + in: header + required: true + description: Внутренний ключ для доступа к API + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BaseRequest' + examples: + userInfoGetAll: + summary: Получить всех пользователей с пагинацией + value: + msg_id: 30014 + message_body: + action: "getAllWithPagination" + page: 0 + size: 10 + sort_by: "createdAt" + sort_direction: "desc" + userInfoGetById: + summary: Получить информацию о пользователе по ID + value: + msg_id: 30014 + message_body: + action: "getInfoById" + user_id: 123 + userInfoUpdate: + summary: Обновить дополнительную информацию пользователя + value: + msg_id: 30014 + message_body: + action: "update" + user_id: 123 + ip_address: "192.168.1.1" + user_agent: "Mozilla/5.0" + userInfoDelete: + summary: Удалить дополнительную информацию пользователя + value: + msg_id: 30014 + message_body: + action: "delete" + user_id: 123 + complaintCreate: + summary: Создать жалобу + value: + msg_id: 30030 + message_body: + action: "create" + violation_id: 456 + complaint_text: "Нарушение правил использования" + complaintUpdateStatus: + summary: Обновить статус жалобы + value: + msg_id: 30030 + message_body: + action: "update_status" + id: "complaint-uuid" + status: "RESOLVED" + complaintUpdate: + summary: Обновить жалобу + value: + msg_id: 30030 + message_body: + action: "update" + id: "complaint-uuid" + complaint_text: "Обновленный текст жалобы" + complaintDelete: + summary: Удалить жалобу + value: + msg_id: 30030 + message_body: + action: "delete" + id: "complaint-uuid" + fileModerate: + summary: Модерировать файл + value: + msg_id: 40002 + message_body: + action: "moderate_file" + file_id: "file-uuid" + file_status: "APPROVED" + comment: "Файл проверен" + fileChangeStatus: + summary: Изменить статус файла + value: + msg_id: 40002 + message_body: + action: "change_file_status" + file_id: "file-uuid" + file_status: "BLOCKED" + fileReviewAppeal: + summary: Рассмотреть апелляцию + value: + msg_id: 40002 + message_body: + action: "review_appeal" + appeal_id: "appeal-uuid" + approve: true + comment: "Апелляция одобрена" + tariffAdd: + summary: Добавить тариф + value: + msg_id: 40003 + message_body: + action: "add" + name: "Premium" + price: 999.99 + type: "MONTHLY" + tokens: 1000 + disk_size: 50 + max_users: 5 + max_files_count: 100 + tariff_term: "MONTHLY" + description: "Премиум тариф" + account_type: "PREMIUM" + tariffRemove: + summary: Удалить тариф + value: + msg_id: 40003 + message_body: + action: "remove" + id: "tariff-uuid" + tariffUpdate: + summary: Обновить тариф + value: + msg_id: 40003 + message_body: + action: "update" + id: "tariff-uuid" + name: "Premium Plus" + price: 1499.99 + description: "Обновленный премиум тариф" + responses: + '200': + description: Результат операции управления + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + '401': + description: Неверный или отсутствующий внутренний ключ + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + + /api/internal/data-download/{fileId}: + get: + tags: + - Internal + summary: Внутреннее скачивание файла + description: Прямое скачивание файла из хранилища для внутренних нужд + operationId: internalDownloadFile + parameters: + - name: X-Internal-Key + in: header + required: true + description: Внутренний ключ для доступа к API + schema: + type: string + - name: fileId + in: path + required: true + schema: + type: string + description: ID файла + responses: + '200': + description: Файл + content: + application/octet-stream: + schema: + type: string + format: binary + '404': + description: Файл не найден + + # ========== DATA ENDPOINTS TODO ========== + /api/v{version}/data: + post: + tags: + - Data + summary: Основной эндпоинт обработки данных + description: | + Обрабатывает запросы по msg_id. Доступные операции: + + **Файлы:** + - **20004** - Инициализация загрузки/информация о типах файлов/статус чанков (FileUploadHandler) + - **20005** - Операции с файлами (FileEntityHandler) + - **20007** - Поиск по изображению (ImageFoundRequestHandler) + + **Пользователи:** + - **20008** - Авторизация через сторонние сервисы (AuthRequestHandler) + - **20009** - Верификация регистрации (VerifyRegisterUserHandler) + - **30014** - Информация о пользователе (UserInfoHandler) + - **30016** - Верификация пользователя (UserVerificationHandler) + + **Компании и тарифы:** + - **30000** - Управление компанией (CompanyHandler) + - **30001** - Управление тарифами (TariffHandler) + - **30002** - Информация о тарифах (TariffInfoHandler) + - **30003** - Реферальная система (ReferralHandler) + + **Платежи:** + - **30005** - Платежи (PaymentHandler) + - **30008** - Расчет стоимости (CostHandler) + + **Мониторинг и нарушения:** + - **30007** - Мониторинг (MonitoringHandler) + - **30009** - Нарушения (ViolationHandler) + - **30010** - Статистика нарушений (ViolationStatisticsHandler) + - **30027** - Статистика мониторинга (MonitoringStatisticHandler) + + **Поиск и жалобы:** + - **30011** - Глобальный поиск (GlobalSearchHandler) + - **30012** - Уведомления о нарушениях (ViolationNotionHandler) + - **30013** - Жалобы (ComplaintEntityHandler) + + **Уведомления:** + - **30015** - Уведомления (NotificationHandler) + + **Юридические дела:** + - **30017** - Управление делами (LawCaseHandler) + + **Токены:** + - **30018** - Операции с токенами (TokenOperationHandler) + + **Просмотр документов:** + - **30028** - Просмотр документов (DockViewFileHandler) + operationId: handleDataRequest + parameters: + - name: version + in: path + required: true + schema: + type: integer + minimum: 1 + description: Версия API + example: 1 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BaseRequest' + examples: + fileUploadInit: + summary: Инициализация загрузки файла + value: + msg_id: 20004 + message_body: + action: "init" + file_name: "document.pdf" + file_type: "document" + extension: "pdf" + convert_to: "protected" + file_size: 1048576 + fileTypes: + summary: Получение типов файлов + value: + msg_id: 20004 + message_body: + action: "file_types" + fileExtensions: + summary: Получение расширений для типа + value: + msg_id: 20004 + message_body: + action: "file_extension" + file_type: "image" + companyInfo: + summary: Информация о компании + value: + msg_id: 30000 + message_body: + action: "get_info" + globalSearch: + summary: Глобальный поиск + value: + msg_id: 30011 + message_body: + query: "изображение кота" + filters: + file_type: "image" + responses: + '200': + description: Успешный ответ + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + fileUploadInitSuccess: + summary: Успешная инициализация загрузки + value: + msg_id: 20004 + message_code: 0 + message_desc: "Operation successful" + message_body: + upload_id: "550e8400-e29b-41d4-a716-446655440000" + file_name: "document.pdf" + total_chunks: 5 + chunk_size: 209715 + status: "INITIALIZED" + fileTypesSuccess: + summary: Типы файлов + value: + msg_id: 20004 + message_code: 0 + message_desc: "Operation successful" + message_body: + file_types: + - "IMAGE" + - "DOCUMENT" + - "AUDIO" + count: 3 + invalidMsgId: + summary: Неверный msg_id + value: + msg_id: 99999 + message_code: 4 + message_desc: "Message id not found" + message_body: {} + + # ========== FILE UPLOAD ENDPOINTS ========== + /api/v{version}/files/chunk: + post: + tags: + - Files + summary: Загрузка чанка файла + description: Загрузка части файла (чанка) в рамках multipart-загрузки + operationId: uploadChunk + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: upload_id + in: query + required: true + schema: + type: string + format: uuid + description: ID сессии загрузки + - name: chunk_number + in: query + required: true + schema: + type: integer + minimum: 0 + description: Номер чанка (начиная с 0) + - name: findSimilar + in: query + required: false + schema: + type: integer + default: 0 + description: Искать похожие файлы (1 - да, 0 - нет) + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - chunk + properties: + chunk: + type: string + format: binary + description: Файл чанка + responses: + '200': + description: Результат загрузки чанка + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + success: + summary: Чанк загружен успешно + value: + msg_id: 20000 + message_code: 0 + message_desc: "Chunk uploaded successfully" + message_body: + upload_id: "550e8400-e29b-41d4-a716-446655440000" + chunk_number: 0 + chunk_size: 209715 + file_id: "abc123" + message: "Chunk uploaded successfully" + duplicateFile: + summary: Найден дубликат файла + value: + msg_id: 20004 + message_code: 2 + message_desc: "Duplicate file upload" + message_body: + duplicate_file_id: "xyz789" + user_id: 123 + message: "Duplicate file found" + + /api/v{version}/files/{uploadId}/complete: + post: + tags: + - Files + summary: Завершение загрузки файла + description: Подтверждение завершения загрузки всех чанков + operationId: completeUpload + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: uploadId + in: path + required: true + schema: + type: string + format: uuid + description: ID сессии загрузки + responses: + '200': + description: Статус завершения загрузки + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + success: + summary: Сборка файла запущена + value: + msg_id: 20004 + message_code: 0 + message_desc: "File assembly in progress" + message_body: + upload_id: "550e8400-e29b-41d4-a716-446655440000" + status: "COMPLETING" + uploaded_chunks: 5 + total_chunks: 5 + message: "File assembly in progress" + incomplete: + summary: Не все чанки загружены + value: + msg_id: 20004 + message_code: 2 + message_desc: "Not all chunks uploaded" + message_body: + upload_id: "550e8400-e29b-41d4-a716-446655440000" + status: "IN_PROGRESS" + uploaded_chunks: 3 + total_chunks: 5 + message: "Not all chunks uploaded" + + /api/v{version}/files/progress/{uploadId}: + get: + tags: + - Files + summary: Прогресс загрузки файла + description: Получение текущего статуса загрузки + operationId: getUploadProgress + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: uploadId + in: path + required: true + schema: + type: string + format: uuid + description: ID сессии загрузки + responses: + '200': + description: Прогресс загрузки + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + inProgress: + summary: Загрузка в процессе + value: + msg_id: 20004 + message_code: 0 + message_desc: "Operation successful" + message_body: + upload_id: "550e8400-e29b-41d4-a716-446655440000" + file_name: "document.pdf" + total_chunks: 5 + uploaded_chunks: 3 + status: "IN_PROGRESS" + progress_percentage: 60.0 + file_path: "/uploads/user123/doc.pdf" + remaining_chunks: 2 + + # ========== FILE DOWNLOAD ENDPOINTS ========== + /api/v{version}/files/download/{fileId}: + get: + tags: + - Files + summary: Скачивание защищенного файла + description: | + Скачивание файла с проверкой прав доступа. Требуется авторизация. + Проверяет права пользователя на скачивание файла. + operationId: downloadFile + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: fileId + in: path + required: true + schema: + type: string + description: ID файла + - name: Authorization + in: header + required: true + schema: + type: string + description: Токен авторизации + example: "Bearer eyJhbGciOiJIUzI1NiIs..." + responses: + '200': + description: Файл для скачивания + content: + application/octet-stream: + schema: + type: string + format: binary + headers: + Content-Disposition: + schema: + type: string + description: Имя файла для сохранения + example: 'attachment; filename="document.pdf"' + '200-json': + description: Ошибка при скачивании + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + fileBlocked: + summary: Файл заблокирован + value: + msg_id: 20004 + message_code: 1 + message_desc: "File is blocked,deleted or removed" + message_body: + file_id: "abc123" + noPermission: + summary: Нет прав на скачивание + value: + msg_id: 20004 + message_code: 2 + message_desc: "Not have permission for download" + message_body: + file_id: "abc123" + + /api/v{version}/files/public-download/{fileId}: + get: + tags: + - Files + summary: Публичное скачивание файла + description: Скачивание файла без авторизации (если разрешено) + operationId: publicDownloadFile + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: fileId + in: path + required: true + schema: + type: string + description: ID файла + responses: + '200': + description: Файл для скачивания + content: + application/octet-stream: + schema: + type: string + format: binary + + /api/file/link: + post: + tags: + - Files + summary: Получение ссылки на файл для DocViewer + description: Создает ссылку для просмотра документа и логирует просмотр + operationId: getFileLink + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DocViewerRequest' + responses: + '200': + description: Файл для скачивания/просмотра + content: + application/octet-stream: + schema: + type: string + format: binary + + # ========== FILE SIMILARITY ENDPOINTS ========== + /api/v{version}/files/{fileId}/similar: + get: + tags: + - Files + summary: Поиск похожих файлов + description: | + Поиск файлов, похожих на указанный. + Для изображений использует алгоритм перцептивного хеша. + Для документов и аудио проверяет на полные дубликаты. + operationId: findSimilarFiles + parameters: + - name: version + in: path + required: true + schema: + type: integer + description: Версия API + - name: fileId + in: path + required: true + schema: + type: string + description: ID файла для поиска похожих + - name: similarityLevels + in: query + required: false + schema: + type: array + items: + type: string + description: Уровни схожести для фильтрации + example: ["HIGH", "MEDIUM"] + - name: page + in: query + required: false + schema: + type: integer + default: 0 + description: Номер страницы + - name: size + in: query + required: false + schema: + type: integer + default: 20 + description: Размер страницы + - name: sort + in: query + required: false + schema: + type: string + default: "hammingDistance" + description: Поле для сортировки + responses: + '200': + description: Список похожих файлов + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + examples: + success: + summary: Найдены похожие файлы + value: + msg_id: 20004 + message_code: 0 + message_desc: "Similar files found" + message_body: + content: + - file_id: "xyz789" + similarity: 95.5 + file_name: "similar_image.jpg" + page: 0 + size: 20 + total_elements: 1 + total_pages: 1 + has_next: false + has_previous: false + + + + /api/check/{fileId}: + get: + tags: + - Files + summary: Проверка защиты файла + description: Проверяет, защищен ли файл системой NoCopy + operationId: checkFileProtection + parameters: + - name: fileId + in: path + required: true + schema: + type: string + description: ID файла для проверки + responses: + '200': + description: Результат проверки + content: + application/json: + schema: + $ref: '#/components/schemas/BaseResponse' + + /api/check/file_stats: + get: + tags: + - Files + summary: Статистика защиты файлов + description: Получение статистики по защищенным файлам пользователя + operationId: checkFileProtectStats + responses: + '200': + description: Статистика по типам файлов + content: + application/json: + schema: + type: object + additionalProperties: true + example: + IMAGE: 150 + DOCUMENT: 45 + AUDIO: 12 + +# ========== COMPONENTS ========== +components: + schemas: + BaseRequest: + type: object + required: + - msg_id + - message_body + properties: + msg_id: + type: integer + description: Идентификатор сообщения/операции + example: 20004 + message_body: + type: object + description: Тело запроса с параметрами операции + additionalProperties: true + + BaseResponse: + type: object + properties: + msg_id: + type: integer + description: Идентификатор сообщения (копируется из запроса) + example: 20004 + message_code: + type: integer + description: | + Код результата: + - 0 - Успешно + - 1 - Предупреждение/особый случай + - 2 - Ошибка валидации/бизнес-логики + - 4 - Ресурс не найден + example: 0 + message_desc: + type: string + description: Описание результата операции + example: "Operation successful" + message_body: + type: object + description: Данные ответа + additionalProperties: true + + DocViewerRequest: + type: object + required: + - file_id + properties: + file_id: + type: string + description: ID файла для просмотра + user_id: + type: integer + description: ID пользователя (если не передан в заголовке) + action: + type: string + description: Действие с документом + + FileUploadRequest: + type: object + properties: + action: + type: string + description: | + Действие с загрузкой: + - init - инициализация загрузки + - file_types - получение доступных типов файлов + - file_extension - получение расширений для типа + - chunks - статус чанков + - cancel - отмена загрузки + - progress - прогресс загрузки + enum: [init, file_types, file_extension, chunks, cancel, progress] + example: init + file_name: + type: string + description: Имя файла (для action=init) + example: "document.pdf" + file_type: + type: string + description: Тип файла (image, document, audio) + enum: [IMAGE, DOCUMENT, AUDIO] + example: DOCUMENT + extension: + type: string + description: Расширение файла + example: "pdf" + convert_to: + type: string + description: Формат конвертации + example: "protected" + file_size: + type: integer + format: int64 + description: Размер файла в байтах + example: 1048576 + upload_id: + type: string + format: uuid + description: ID сессии загрузки (для action=cancel, chunks, progress) + + InitFileResponse: + type: object + properties: + upload_id: + type: string + format: uuid + description: ID сессии загрузки + file_name: + type: string + description: Имя файла + total_chunks: + type: integer + description: Общее количество чанков + chunk_size: + type: integer + description: Размер одного чанка в байтах + status: + type: string + description: Статус загрузки + example: "INITIALIZED" + + ChunkUploadResponse: + type: object + properties: + upload_id: + type: string + format: uuid + chunk_number: + type: integer + chunk_size: + type: integer + format: int64 + file_id: + type: string + message: + type: string + + UploadProgressResponse: + type: object + properties: + upload_id: + type: string + format: uuid + file_name: + type: string + total_chunks: + type: integer + uploaded_chunks: + type: integer + status: + type: string + progress_percentage: + type: number + format: float + file_path: + type: string + remaining_chunks: + type: integer + + CompleteUploadResponse: + type: object + properties: + upload_id: + type: string + format: uuid + status: + type: string + uploaded_chunks: + type: integer + total_chunks: + type: integer + message: + type: string + file_path: + type: string + + ChunkStatusResponse: + type: object + properties: + upload_id: + type: string + format: uuid + total_chunks: + type: integer + uploaded_chunks: + type: integer + missing_chunks: + type: integer + chunk_status: + type: object + additionalProperties: + type: boolean + + FileTypesResponse: + type: object + properties: + file_types: + type: array + items: + type: string + example: ["IMAGE", "DOCUMENT", "AUDIO"] + count: + type: integer + example: 3 + + FileExtensionResponse: + type: object + properties: + extension: + type: array + items: + type: string + example: ["jpg", "jpeg", "png", "gif"] + count: + type: integer + max_file_size: + type: integer + format: int64 + description: Максимальный размер файла в байтах + + CanceledUploadResponse: + type: object + properties: + upload_id: + type: string + format: uuid + message: + type: string + + ActionResponse: + type: object + properties: + action: + type: string + available_actions: + type: array + items: + type: string + + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + description: JWT токен для авторизации + +security: + - BearerAuth: [] \ No newline at end of file