...

Аутентификация в спецификации OpenAPI: расширенный пример интернет-магазина с JWT

аутентификация JWT пример, OpenAPI спецификация примеры курсы обучение REST API Swagger, Swagger REST API примеры курсы обучение, ликбез по Swagger и SwaggerHub для аналитика, тестирование REST API интеграция информационных системы примеры, REST Swagger JSON YAML примеры курсы обучение, интеграция информационных систем REST API простыми словами для начинающих примеры курсы обучение, интеграция информационных систем простыми словами для начинающих примеры курсы обучение, основы интеграции информационных систем для бизнес-аналитика, интеграция информационных систем основы введение, краткий ликбез по интеграции информационных систем, обучение системных и бизнес-аналитиков, курсы системного и бизнес-анализа, Школа прикладного бизнес-анализа Учебный Центр Коммерсант

Как определить права на манипуляции с ресурсами для разных пользователей REST-приложения в спецификации OpenAPI: пример аутентификации с JWT-токеном для микросервисной системы интернет-магазина.

Проектирование REST API

Продолжим проектирование микросервисной системы интернет-магазина из прошлой статьи и составим спецификацию OpenAPI для REST-приложения, которое принимает запросы с клиента и направляет их к разным микросервисам, реализуя паттерн API Gateway. Напомню, проектируемая система предназначена обслуживания запросов следующих пользователей:

  • Покупатель может просматривать товары, добавлять их в корзину и покупать товары, делая заказы. Также покупателю доступны функции управления своими заказами (создать, изменить, отменить) и манипулирования составом корзины (добавить товар, удалить товар, изменить количество товара).
  • Менеджер интернет-магазина отвечает за управление товарами и поставщиками (создать, изменить, удалить). Также ему доступен просмотр активных заказов и просмотр отчетов по выполненным заказам согласно заданным параметрам фильтрации.
  • Оператор склада изменяет состояние заказа, поскольку управляет упаковкой товаров в заказы.
Схема системного ландшафта С4, нотация С4 примеры курсы обучение, архитектура ИС для аналитика, проектирование ИС примеры курсы обучение
Схема контекста (системного ландшафта) С4

При проектировании REST API важно помнить принцип работы этого архитектурного стиля построения выб-приложения. По сути, методы HTTP-запросов, которые направляет клиент на сервер для доступа к ресурсу можно представить в виде штекеров (коннекторов) для соединения с определенными розетками. Как я уже отмечала здесь,

Маршрут (Route) — это URL-адрес, который направляет запрос к определенным конечным точкам с помощью HTTP-методов. Маршрут может иметь несколько конечных точек. Конечная точка (Endpoint) — это непосредственно обращение к маршруту конкретным HTTP-методом, чтобы выполнить определенную задачу и вернуть данные с сервера клиенту.

REST API HTTP ресурсы конечные точки проектирование веб-приложений
Ресурсы REST-приложения, HTTP-методы и операции/данные бэкэнда

А за розеткой, т.е. маршрутом, скрывается класс, таблица БД или другое материализованное представление для работы с сущностью домена, т.е. операций с данными. В коде такое сопоставление маршрута с функцией обработки данных выполняется, как правило, средствами специализированных фреймворков. Например, для Python есть фреймворк Flask API, пример использования которого я описывала здесь. Flask API предоставляет декорированный метод @route() для реализации конечных точек, позволяя обратиться к маршруту указанными HTTP-методами, чтобы выполнять необходимые манипуляции с данными.

Flask API REST API пример кода Python
пример Python-кода REST-приложения с фреймворком Flask API

Возвращаясь к рассматриваемому кейсу интернет-магазина, составим перечень сущностей домена, которые будут скрываться за маршрутами веб-приложения.

Ресурс (Сущность) Поле Смысл поля Тип данных
Product (Товар) id Идентификатор товара integer
name Название товара string
category Категория товара string
provider Поставщик товара object
price Стоимость товара number
quantity Количество единиц товара integer
Provider (Поставщик) id Идентификатор поставщика integer
name Название поставщика string
INN ИНН поставщика string
site Сайт поставщика string
phone Телефон поставщика string
address Адрес поставщика string
Order (Заказ) id Идентификатор заказа integer
start_date Дата и время создания заказа string, т.к. в JSON нет типа данных для даты и времени. Указать, что это дата можно через format data
state Состояние заказа (новый, принят, найден, подтвержден, собран, оплачен, отменен) string
items Массив товаров, добавленных в заказ, с указанием количества каждого товара object
sum Сумма заказа number
Item (Товар в корзине) id Идентификатор товара в корзине
item Товар, добавленный в корзину object
quantity Количество единиц товара integer

Далее составим перечень вариантов использования (ВИ), сопоставив их с маршрутами и конечными точками, т.е. методами HTTP-запросов, которые будут отправляться к этим URL-адресам. Также сразу отметим необходимость аутентификации для доступа к тем или иным данным посредством HTTP-запросов.

Актор Use Case (ВИ) Маршрут Конечная точка  (HTTP-метод) Аутентификация
·                  Менеджер

·                  Покупатель

UC-1. Посмотреть каталог товаров /product GET Не нужна
UC-2. Найти товар /product GET с параметрами фильтрации Не нужна
Менеджер UC-3. Добавить товар /product POST
·                  Менеджер

·                  Покупатель

UC-4. Посмотреть товар /product/{id} GET Не нужна
Менеджер UC-6. Изменить товар /product/{id} PUT Нужна
Менеджер UC-5. Удалить товар /product/{id} DELETE Нужна
·                  Менеджер

·                  Покупатель

UC-7. Посмотреть список поставщиков /provider GET Не нужна
UC-8. Найти поставщика /provider GET с параметрами фильтрации Не нужна
Менеджер UC-10. Добавить поставщика /provider POST Нужна
·                  Менеджер

·                  Покупатель

UC-9. Посмотреть поставщика /provider/{id} GET Нужна
Менеджер UC-11. Изменить поставщика /provider/{id} PUT Нужна
Менеджер UC-12. Удалить поставщика /provider/{id} DELETE Нужна
Менеджер UC-12. Получить аналитический отчет по выполненным заказам /analytics POST (в теле запроса параметры фильтрации данных для генерации отчета) Нужна
Менеджер UC-13. Посмотреть все заказы /order GET Нужна
·                  Покупатель

·                  Менеджер

UC-14. Посмотреть все свои заказы /order GET с параметрами фильтрации Нужна
·                  Менеджер

·                  Покупатель

·                  Оператор склада

UC-15. Найти заказ /order GET с параметрами фильтрации Нужна
Покупатель UC-16. Посмотреть товары в корзине /item GET Нужна
Покупатель UC-17. Добавить товар в корзину /item POST Нужна
Покупатель UC-18. Изменить количество товара в корзине /item/{id} PUT со значением Нужна
Покупатель UC-19. Удалить товар из корзины /item/{id} DELETE Нужна
Покупатель UC-20. Создать заказ /order POST Нужна
Покупатель UC-21. Подтвердить заказ /order/{id} PATCH Нужна
Покупатель UC-22. Оплатить заказ /order/{id} PATCH Нужна
·                  Менеджер

·                  Покупатель

UC-23. Отменить заказ /order/{id} PATCH Нужна
Оператор склада UC-24. Собрать заказ /order/{id} PATCH Нужна

Для аутентификации пользователя будем использовать довольно простой метод — токен на предъявителя (Bearer token) – веб-маркер JSON (JWT, JSON Web Token), который представляет собой текстовую строку, включенную в заголовок запроса. Использование токена не требует  от предъявителя доказательства владения. Имея токен, можно получить доступ к ресурсам. Токен можно отозвать, и обычно он выдается на ограниченный период времени, чтобы снизить риск несанкционированного доступа к данным. Про этот и другие методы аутентификации в веб-приложениях я упоминала здесь.

В данном примере механизм JWT выбран из-за простоты, поскольку сообщение с JWT-токеном может быть реализовано любым языком программирования, поддерживающим криптографическое шифрование данных, например, алгоритмом HMAC SHA256 или RSA, сведения о котором содержатся в разделе заголовка токена, отделенного точкой от полезной нагрузки и подписи. Полезная нагрузка включает информацию о пользователе, а подпись подтверждает отправителя и гарантирует, что сообщение не было изменено во время передачи. JWT-токен с ограниченным временем жизни дает возможность регулировать длительность клиентской сессии и позволяет stateless-системе вести себя как stateful, когда ответ сервера зависит от состояния клиента. Обратной стороной достоинств JWT-токенов является их уязвимость из-за передачи в открытом виде: токен может быть расшифрован и даже изменен злоумышленником с помощью специализированных средств. Впрочем, вопросы информационной безопасности настолько глубокие и серьезные, что требуют проработки в отдельном материале, что я сделаю когда-нибудь в другой раз.

Закончив с предварительным проектированием REST API, можно перейти к детальному: разработке спецификации  OpenAPI, упрощенный пример которой рассмотрен в прошлой статье.

Основы архитектуры и интеграции информационных систем

Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.

Разработка спецификации OpenAPI с secure-схемой

Как обычно, формировать спецификацию будем с помощью редактора Swagger в веб-сервисе SwaggerHub, который доступен для бесплатного использования, но требует предварительной регистрации. Выбрав простой шаблон (Simple API), далее начнем разрабатывать саму спецификацию в формате YAML, внося своих акторов, маршруты и конечные точки, а также структуры данных.

Swagger SwaggerHub, OpenAPI, спецификация REST API
Создание нового проекта в SwaggerHub

Поскольку спецификация OpenAPI поддерживает вложенные структуры данных и возможность их переиспользования за счет механизма ссылок, разделим сущность домена Товар на Product, которым манипулирует менеджер, указывая количество на складе (свойство quantity) и SKU – товарную единицу номенклатуры. В спецификации OpenAPI для этого будут описаны соответствующие схемы данных. Аналогично зададим возможные значения для состояния товара, которые могут изменить разные пользователи. Например, заказ может быть отменен или самим клиентом, или менеджером магазина, если он не подтвержден / не оплачен в течении 3-х дней. Тогда схема данных для изменения состояния заказа в формате YAML будет выглядеть так:

CanceledOrder:
  required:
    - state
  properties:
    state:
      type: string
      enum:
        - отменен клиентом
        - отменен менеджером
      example: отменен

Кроме того, в разделе схемы описана схема безопасности:

securitySchemes:
  bearerAuth:            
    type: http
    scheme: bearer
    bearerFormat: JWT

Ссылка на эту схему указана в HTTP-методах обращения к ресурсам с помощью ключевого слова security:

security: - bearerAuth: []

Например, добавить новый товар в каталог может только менеджер, что описывает следующий участок спецификации OpenAPI:

paths:
 /product:       
    post:
      tags:
        - manager
      summary: 'Добавить товар'
      operationId: addProduct
      security:
        - bearerAuth: []
      description: Добавить новый товар в каталог
      responses:
        '201':
          description: товар добавлен
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    example: 1
                  product:  
                    $ref: '#/components/schemas/Product'
        '400':
          description: некорректный ввод
        '409':
          description: такой товар уже есть
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
        description: Новый товар для добавления в каталог

Указание схемы безопасности означает, что для доступа к ресурсу необходимо предоставить аутентификационный токен (bearer token). Как и базовая аутентификация с прямым указанием логина и пароля, аутентификацию с bearer token следует использовать только через HTTPS (SSL). Описав эту схему безопасности в разделе components/securitySchemes, можно использовать ключевое слово security, чтобы применить эту схему к желаемой области: глобальной, т.е. ко всем  конечным точкам или или конкретным операциям, как в рассмотренном примере.

Токен аутентификации передается в заголовке или в параметре запроса. Поскольку в квадратных скобках bearerAuth: [] пусто, области безопасности, т.е. конкретные требования или ограничения токена не указаны. Указав в скобках дополнительные параметры, можно регулировать разрешения на манипуляции с данными, ограничения IP-адреса и т.д. Однако, в спецификации OpenAPI области используются только с OAuth 2 и OpenID Connect, применяемыми для аутентификации через стороннего провайдера, например, ЕСИА, UML-диаграмму последовательности для которой я разбирала здесь.

Поскольку за аутентификацию и авторизацию пользователей в проектируемой системе отвечает отдельный микросервис, описываемый REST API должен давать возможность каждому пользователю ввести свои учетные данные для входа и выдать JWT-токен зарегистрированным пользователям. Для этого я добавила маршрут /login, к которому можно обратиться любой пользователь (user) путем отправки HTTP-запроса POST с передачей в теле запроса учетных данных (логина и пароля). В спецификации OpenAPI это описывает следующий участок кода:

paths:
 /login:
    post:
      tags:
        - user
      summary: Вход пользователя в систему
      description: Аутентификация пользователя с использованием Bearer Token (токен на предъявителя)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                  description: Логин пользователя
                  example: anna_vichugova
                password:
                  type: string
                  format: password
                  description: Пароль пользователя
      responses:
        '200':
          description: Успешная аутентификация
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                    description: Bearer Token для дальнейшей аутентификации
                    example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
        '401':
          description: Ошибка аутентификации, неверные учетные данные
        '500':
          description: Внутренняя ошибка сервера

Основы архитектуры и интеграции информационных систем

Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.

Таким образом, итоговая спецификация для рассматриваемого шлюза REST API интернет-магазина выглядит следующим образом:

openapi: 3.0.0
servers:
  # Added by API Auto Mocking Plugin
  - description: SwaggerHub API Auto Mocking
    url: https://virtserver.swaggerhub.com/VICHIGOVAANNA/Internet-shop/2.0.0
info:
  description: 'Типичный интернет-магазин - демо-кейс Анны Вичуговой (расширенная версия для МСА, с JWT-аутентификацией)'
  version: 2.0.0
  title: API интернет-магазина
  contact:
    email: anna@mail.com

tags:
  - name: user
    description: Пользователь (все категории пользователей)
  - name: manager
    description: Менеджер
  - name: customer
    description: Покупатель
  - name: operator
    description: Оператор склада    

paths:
 /login:
    get:
      tags:
       - user
      description: Просмотр страницы ввода логина и пароля (входа в систему)
      summary: Просмотр страницы ввода логина и пароля (входа в систему)
      responses:
        '200':
          description: Успешное отображение страницы аутентификации
          content:
            application/json:
              schema:
                type: object
                properties:
                  page:
                    type: object
                    description: Содержимое страницы для ввода логина и пароля

        '404':
          description: Страница не найдена
        '503':
          description: Сервер временно недоступен
    post:
      tags:
        - user
      summary: Вход пользователя в систему
      description: Аутентификация пользователя с использованием Bearer Token (токен на предъявителя)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                  description: Логин пользователя
                  example: anna@example.ru
                password:
                  type: string
                  format: password
                  description: Пароль пользователя
                role:
                  type: string
                  enum:
                   - manager
                   - customer
                   - operator
                  description: Роль пользователя
                  example: manager
      responses:
        '200':
          description: Успешная аутентификация
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                    description: Bearer Token для дальнейшей аутентификации
                    example: eyJ0eXAwcvvcb1QiLCJhbGciOsdfsUzI1NiJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIswwwfcI6MTU5NDIwOTYwMCwicm9sZSI6InVzZXIifQ.ZvkYYnyM92xvxcvNW9_hSis7_x3_9rymsDcvcbvuOcc1I
        '401':
          description: Ошибка аутентификации, неверные учетные данные
        '500':
          description: Внутренняя ошибка сервера
          
 /analytics:
    post:
      tags:
       - manager
      summary: Получить аналитический отчет
      operationId: getAnalytics
      security:
        - bearerAuth: []  
      description: Генерация pdf-отчета по заданным фильтрам
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                client:
                  type: string
                analysis_period:
                  type: string
                  format: date
              required:
               - client
               - analysis_period
      responses:
        '200':
          description: Отчет успешно сформирован
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '400':
          description: Некорректный запрос
        '500':
          description: Ошибка сервера
          
 /product:
    get:
      tags:
        - manager
        - customer
        - operator
        - user
      summary: Посмотреть каталог товаров
      operationId: viewProductCatalog
      description: Параметры фильтрации товаров в каталоге для поиска
      parameters:
        - in: query
          name: name
          description: название товара для поиска
          required: false
          schema:
            type: string
        - in: query
          name: category
          description: категория товара для поиска
          required: false
          schema:
            type: string
        - in: query
          name: provider
          description: поставщик товара для поиска
          required: false
          schema:
            type: string             
        - in: query
          name: min_price
          description: минимальная цена товара для поиска
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 100500
        - in: query
          name: max_price
          description: максимальная цена товара для поиска
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 10005000
      responses:
        '200':
          description: результаты поиска по запросу
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Product'
        '400':
          description: не верные параметры фильтрации
          
    post:
      tags:
        - manager
        - operator
      summary: 'Добавить товар'
      operationId: addProduct
      security:
        - bearerAuth: []
      description: Добавить новый товар в каталог
      responses:
        '201':
          description: товар добавлен
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    example: 1
                  product:  
                    $ref: '#/components/schemas/Product'
        '400':
          description: некорректный ввод
        '409':
          description: такой товар уже есть
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
        description: Новый товар для добавления в каталог

        
 /provider:
    get:
      tags:
        - manager
        - customer
        - user
      summary: Посмотреть список поставщиков
      operationId: viewProviderCatalog
      description: Параметры фильтрации поставщиков в каталоге для поиска
      parameters:
        - in: query
          name: name
          description: название поставщика для поиска
          required: false
          schema:
            type: string
        - in: query
          name: INN
          description: ИНН поставщика для поиска
          required: false
          schema:
            type: string
        - in: query
          name: phone
          description: телефон поставщика для поиска
          required: false
          schema:
            type: string
        - in: query
          name: address
          description: адрес поставщика для поиска
          required: false
          schema:
            type: string
      responses:
        '200':
          description: результаты поиска по запросу
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Provider'
        '400':
          description: не верные параметры фильтрации
          
    post:
      tags:
        - manager
      summary: Добавить поставщика
      operationId: addProvider
      security:
        - bearerAuth: []    
      description: Добавление нового поставщика в каталог
      responses:
        '201':
          description: поставщик добавлен
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    example: 1
                  product:  
                    $ref: '#/components/schemas/Provider'
        '400':
          description: некорректный ввод
        '409':
          description: такой поставщик уже есть
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Provider'
        description: Новый поставщик для добавления в каталог
        
 /product/{id}:
  get:
    tags:
      - manager
      - customer
      - operator
    summary: Посмотреть товар
    operationId: viewProduct
    description: Просмотр данных о конкретном товаре по его ID
    parameters:
      - in: path
        name: id
        description: ID
        required: true
        schema:
          type: integer
          format: int64
          example: 1
    responses:
      '200':
        description: Товар найден
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
      '404':
        description: 'Товар не найден'
  put:
      tags:
        - manager
      summary: Изменить товар
      operationId: updateProduct
      security:
        - bearerAuth: []    
      description: Изменение параметров товара
      parameters:
        - name: id
          in: path
          description: ID товара, параметры которого нужно изменить
          required: true
          schema:
            type: integer
            example: 1
      responses:
        '200':
          description: параметры товара изменены успешно
        '400':
          description: некорректный ввод
        '404':
          description: товар не найден
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
        description: Измененные параметры товара    
  delete:
    tags:
      - manager
    summary: 'Удалить товар'
    operationId: deleteProduct
    security:
        - bearerAuth: []  
    description: Удаление товара по его идентификатору
    parameters:
      - name: id
        in: path
        description: Идентификатор товара для удаления
        required: true
        schema:
          type: integer
        example: 1
    responses:
      '200':
        description: товар успешно удален
      '404':
        description: товар не найден
      '500':
        description: внутренняя ошибка сервера
        
 /provider/{id}:
  get:
    tags:
      - manager
      - customer
    summary: Посмотреть поставщика
    operationId: viewProvider
    security:
        - bearerAuth: []  
    description: Просмотр информации о конкретном поставщике по его ID
    parameters:
      - in: path
        name: id
        description: Идентификатор поставщика
        required: true
        schema:
          type: integer
          format: int64
          example: 1
    responses:
      '200':
        description: Поставщик найден
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Provider'
      '404':
        description: Поставщик не найден
  put:
      tags:
        - manager
      summary: Изменить поставщика
      operationId: updateProvider
      security:
        - bearerAuth: []    
      description: Изменение поставщика по его идентификатору
      parameters:
        - name: id
          in: path
          description: ID поставщика, параметры которого нужно изменить
          required: true
          schema:
            type: integer
            example: 1
      responses:
        '200':
          description: параметры поставщика изменены успешно
        '400':
          description: некорректный ввод
        '404':
          description: поставщик не найден
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Provider'
        description: Данные поставщика
        
  delete:
    tags:
      - manager
    summary: Удалить поставщика
    operationId: deleteProvider
    security:
        - bearerAuth: []  
    description: Удаление поставщика по его идентификатору
    parameters:
      - name: id
        in: path
        description: Идентификатор поставщика для удаления
        required: true
        schema:
          type: integer
        example: 1
    responses:
      '200':
        description: поставщик успешно удален
      '404':
        description: поставщик не найден
      '500':
        description: внутренняя ошибка сервера  

 /order:
    get:
      tags:
        - manager
        - customer
        - operator
      summary: Посмотреть заказы
      operationId: viewOrders
      security:
        - bearerAuth: []    
      description: Параметры фильтрации заказов для поиска
      parameters:
        - in: query
          name: id
          description: номер заказа для поиска
          required: false
          schema:
            type: integer
        - in: query
          name: start_date
          description: дата создания заказа
          required: false
          schema:
            type: string
            format: date
      responses:
        '200':
          description: результаты поиска по запросу
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Order'
        '400':
          description: не верные параметры фильтрации

 /order/{id}:
    patch:
      tags:
        - customer
        - manager
        - operator
      summary: Изменить состояние заказа
      security:
        - bearerAuth: []       
      operationId: changeOrderState
      description: Подтвердить, отменить или изменить статус заказа
      parameters:
        - name: id
          in: path
          description: ID заказа, статус которого надо изменить
          required: true
          schema:
            type: integer
            example: 1
      responses:
        '200':
          description: Заказ успешно изменен
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Order'
        '400':
          description: Некорректный ввод
        '404':
          description: Заказ не найден
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/approvedOrder'
                - $ref: '#/components/schemas/CanceledOrder'
                - $ref: '#/components/schemas/CollectedOrder'
                - $ref: '#/components/schemas/HoldedOrder'
              discriminator:
                propertyName: operationType
              description: Новый статус заказа

 /item:
    get:
      tags:
        - customer
      summary: Посмотреть товары в корзине
      operationId: viewItem
      security:
        - bearerAuth: []    
      description: Товары в корзине
      responses:
        '200':
          description: товары в корзине
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Item'
        '500':
          description: внутренняя ошибка сервера 
          
    post:
      tags:
        - customer
      summary: Добавить товар в корзину
      operationId: addItem
      security:
        - bearerAuth: []    
      responses:
        '201':
          description: товар добавлен
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    example: 1
                  product:  
                    $ref: '#/components/schemas/Item'
        '400':
          description: некорректный ввод
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Item'
        description: Товар для добавления в корзину

 /item/{id}:
    patch:
      tags:
        - customer
      summary: Изменить количество товара в корзине
      #operationId: updateItem
      security:
        - bearerAuth: []    
      description: Изменение количества товара по его идентификатору
      parameters:
        - name: id
          in: path
          description: ID товара, количество которого нужно изменить в корзине
          required: true
          schema:
            type: integer
            example: 1
      requestBody:
        content:
          application/json:
             schema:
                  type: integer              
                  minimum: 1
                  maximum: 100500
        description: Новое количество единиц товара в корзине
      responses:
        '200':
          description: 'Количество товара успешно изменено'
          content:
           application/json:
            schema:
             type: object
             properties:
               item:
                $ref: '#/components/schemas/SKU'
               quantity:
                type: integer
                description: Количество единиц товара в корзине
                example: 56

        '400':
          description: Некорректный ввод
        '404':
          description: Товар не найден в корзине

    delete:
      tags:
        - customer
      summary: Удалить товар из корзины
      operationId: deleteItem
      security:
        - bearerAuth: []    
      description: Удаление товара из корзины по его идентификатору
      parameters:
        - name: id
          in: path
          description: Идентификатор товара для удаления
          required: true
          schema:
            type: integer
            example: 1
      responses:
        '200':
          description: Товар успешно удален из корзины
        '404':
          description: Товар не найден
        '500':
          description: Внутренняя ошибка сервера
          
components:
  schemas:
    SKU:
      type: object
      required:
        - name
        - category
        - provider
        - price
      properties:
        name:
          type: string
          example: 'яблоки'
        category:
          type: string
          example: 'еда'
        provider:
          $ref: '#/components/schemas/Provider'  
        price:
          type: number
          minimum: 0.001
          maximum: 100500          
          example: 145.00
          
    Product:
      type: object
      required:
        - sku
        - quantity
      properties:
        sku:
          $ref: '#/components/schemas/SKU'       
        quantity:
          type: integer
          minimum: 1
          maximum: 100500          
          example: 10   
          
    Provider:
      required:
        - name
        - INN
        - phone
        - address
      properties:
        id:
          type: integer
          example: 1           
        name:
          type: string
          example: ООО Ромашка
        INN:
          type: string
          example: 1234567890          
        site:
          type: string
          format: url
          example: https://www.ooo-camomile.com
        phone:
          type: string
          example: 7-495-123-45-67
        address:
          type: string
          example: г. Москва, ул. Ленина, 123
          
    Order:
      required:
        - id
        - start_date
        - state
        - items
        - sum
      properties:
        id:
          type: integer
          example: 1        
        start_date:
          type: string
          format: date
          example: 2023-09-30
        items: 
          type: array
          items:
            $ref: '#/components/schemas/Item'
        state:
          type: string
          enum:
            - новый
            - принят
            - найден
            - подтвержден
            - собран
            - оплачен
            - отменен
          example: принят
        sum:
          type: number
          example: 145.00
          
    Item:
      required:
        - id
        - item
        - quantity
      properties:
        id:
          type: integer
          example: 1        
        item:
          $ref: '#/components/schemas/SKU'
        quantity:
          type: integer
          minimum: 1
          maximum: 100500
          example: 45
          
    approvedOrder:
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - подтвержден
            - не подтвержден
          example: подтвержден

    CanceledOrder:
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - отменен клиентом
            - отменен менеджером
          example: отменен
          
    CollectedOrder:
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - собран
            - на сборке
          example: собран

    HoldedOrder:
      required:
        - state
      properties:
        state:
          type: string
          enum:
            - на оплате
            - отказ от оплаты
          example: на оплате

  securitySchemes:
    bearerAuth:            
      type: http
      scheme: bearer
      bearerFormat: JWT

Помимо ранее показанных маршрутов и конечных точек с HTTP-методами со структурами данных и примерами их наполнения, в этой спецификации также показаны HTTP-ответы на запросы, подробнее о которых я писала здесь. Редактор Swagger сразу отображает UI для тестирования REST API. Также разработанная спецификация доступна по ссылке, поскольку при создании проекта для него была задана публичная видимость. Исходный код можно взять в моем Github-репозитории.

Спецификация OpenAPI в Swagger UI, проектирование REST-приложение, пример OpenAPI для аналитика и разработчика, OpenAPI secure shema JWT
Спецификация OpenAPI в Swagger UI

Надеюсь, что это небольшое руководство поможет начинающим аналитикам лучше понять основы проектирования REST API и принципов его документирования с помощью спецификаций OpenAPI. Про то, какие ошибки чаще всего встречаются при разработке спецификации OpenAPI и как их избежать, вы узнаете в этом материале.

Основы архитектуры и интеграции информационных систем

Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.

А подробнее познакомиться со всеми рассмотренными темами, а также другими основами архитектуры и интеграции информационных систем вы сможете на моих курсах в Школе прикладного бизнес-анализа на базе нашего лицензированного учебного центра обучения и повышения квалификации системных и бизнес-аналитиков в Москве:

 

Я даю свое согласие на обработку персональных данных и соглашаюсь с политикой конфиденциальности.

Добавить комментарий