Apicurio / apicurio-studio

Open Source API Design
https://www.apicur.io/studio/
Apache License 2.0
988 stars 495 forks source link

Add support for $ref'd parameters in Editor #1240

Closed lina2358 closed 3 years ago

lina2358 commented 4 years ago

syndesis 2.0.0-20200626 apicurio: https://github.com/syndesisio/syndesis/blame/87de25aaf4a03f9ca5e9db09bc7b9f86e7be31b5/app/pom.xml#L2842 ?!?

Given

components:
  parameters:
    DocType:
      in: path
      name: DocType
      required: true
      schema:
        type: string
    Fields:
      in: query
      name: fields
      schema:
        type: array
        items:
          type: string
        default: ["name"]

Fails

[...]
  /api/resource/{DocType}:
    get:
        [...]
        parameters:
             -
                 $ref: '#/components/parameters/Fields'
        [...]
    post:
         [...]
[...]

Works

[...]
  /api/resource/{DocType}:
     get:
        [...]
        parameters:
            -
                $ref: '#/components/parameters/DocType'
        [...]
    post:
        [...]
[...]

To reproduce:

```yaml openapi: 3.0.0 info: version: "13" title: Frappe / ERPNext API contact: name: ALYF GmbH url: https://alyf.de email: hallo@alyf.de license: name: GPL-3.0 url: http://www.gnu.de/documents/gpl-3.0.en.html servers: - url: https://demo.erpnext.com description: Demo server - url: https://{company}.erpnext.com description: Custom ERPNext.com instance variables: company: default: demo description: Subdomain of your company's custom ERPNext instance tags: - name: Naive Authentication description: If you are developing something serious, you may want to use oAuth2. - name: Resources description: Work with DocTypes or Lists of DocTypes - name: RPC description: Call remote procedures paths: /api/method/{dotted_path_to_method}: get: tags: - RPC parameters: - in: path name: dotted_path_to_method required: true schema: type: string example: frappe.auth.get_logged_user description: | Path to the function you'd like to call, separated by dots. summary: Call a remote procedure responses: '200': description: Successful '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' post: tags: - RPC parameters: - in: path name: dotted_path_to_method required: true schema: type: string example: frappe.auth.get_logged_user description: | Path to the function you'd like to call, separated by dots. summary: Post data to a remote procedure responses: '200': description: Successful '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/resource/{DocType}: post: tags: - Resources summary: Create a new document parameters: - $ref: '#/components/parameters/DocType' requestBody: content: application/json: schema: type: object application/x-www-form-urlencoded: schema: type: object properties: data: type: object responses: "200": description: Document created content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DocType' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' get: tags: - Resources summary: Get a list of documents description: Returns a list of documents of the given type parameters: - $ref: '#/components/parameters/DocType' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': description: | Found requested DocType. By default, only the "name" field is included in the listing, to add more fields, you can pass the fields param to GET request. content: application/json: schema: $ref: '#/components/schemas/DocList' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/resource/{DocType}/{DocumentName}: get: tags: - Resources summary: Get a specific document description: Get a document by it's name, for example EMP001 of DocType Employee. parameters: - $ref: '#/components/parameters/DocType' - in: path name: DocumentName required: true schema: type: string description: | The name (ID) of the document you'd like to receive. For example EMP001 (of type Employee). - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' responses: '200': $ref: '#/components/responses/GetDocumentOK' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' put: tags: - Resources summary: Update a specific document description: TBD parameters: - $ref: '#/components/parameters/DocType' - in: path name: DocumentName required: true schema: type: string description: | The name (ID) of the document you'd like to update. For example EMP001 (of type Employee). requestBody: content: application/json: schema: type: object responses: '200': description: Updated specified document content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DocType' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' delete: tags: - Resources summary: Delete a specific document description: TBD parameters: - in: path name: DocType required: true schema: type: string description: | The type of the document you'd like to delete. For example Customer, Supplier, Employee, Account, Lead, Company, Sales Invoice, Purchase Invoice, Stock Entry, etc. - in: path name: DocumentName required: true schema: type: string description: | The name (ID) of the document you'd like to delete. For example EMP001 (of type Employee). responses: '202': description: Deleted specified document content: application/json: schema: type: object properties: message: type: string '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/method/login: post: tags: - Naive Authentication - Examples summary: Authenticate yourself operationId: login parameters: - in: query name: usr schema: type: string example: Administrator required: false description: Your username - in: query name: pwd schema: type: string example: admin required: false description: Your password requestBody: content: application/json: schema: type: object properties: usr: type: string example: Administrator pwd: type: string example: admin application/x-www-form-urlencoded: schema: type: object properties: data: type: object responses: '200': description: Login successful content: application/json: schema: type: object properties: full_name: type: string example: Administrator message: type: string example: Logged in home_page: type: string example: /desk '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/method/logout: get: tags: - Naive Authentication - Examples summary: Logout from current session responses: '200': description: Logged out. content: application/json: schema: type: object /api/method/frappe.auth.get_logged_user: get: tags: - Naive Authentication - Examples summary: Get the user that is logged in operationId: authGetLoggedUser description: Get the currently logged in user responses: '200': description: search results matching criteria content: application/json: schema: $ref: '#/components/schemas/Message' example: {"message":"demo@erpnext.com"} '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/method/version: get: tags: - Examples summary: Get the version of the app responses: '200': description: Successful content: application/json: schema: $ref: '#/components/schemas/Message' example: {"message":"10.1.36"} '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/method/frappe.desk.tags.add_tag: post: tags: - Examples summary: Add a tag to a document parameters: - in: query name: tag description: Tag to add schema: type: string example: "My Tag" - in: query name: dt description: Target DocType schema: type: string example: "Sales Invoice" - in: query name: dn description: Target document schema: type: string example: "SINV-0001" responses: '200': description: Successful content: application/json: schema: $ref: '#/components/schemas/Message' example: {"message":"My Tag"} '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/resource/Project: get: tags: - Examples summary: Get a list of projects description: Returns a list of projects parameters: - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': description: | Found some projects. By default, only the "name" field is included in the listing, to add more fields, you can pass the fields param to GET request. content: application/json: schema: $ref: '#/components/schemas/DocList' example: data: [ {name: My Project 1}, {name: My Project 2} ] /api/resource/Employee: get: tags: - Examples summary: Get a list of Employees description: | For example, fields=["name","company","employee_name"]. To get the Employee for a specific user, pass filters=[["user_id","=","mail@example.com"]] parameters: - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': description: | Everything fine :) content: application/json: schema: $ref: '#/components/schemas/DocList' example: data: [ { name: 'EMP/0001', company: 'Google LLC', employee_name: 'Larry Page' }, { name: 'EMP/0002', company: 'Google LLC', employee_name: 'Sergey Brin' } ] /api/resource/Timesheet: post: tags: - Examples summary: Create a new timesheet requestBody: content: application/json: schema: type: object properties: company: type: string example: "Alyf" employee: type: string example: "EMP/0001" note: type: string example: "Built that feature" time_logs: type: array items: type: object properties: from_time: type: string example: "2019-02-28 00:00:00" to_time: type: string example: "2019-02-28 23:59:59" project: type: string example: "Timetracking App" activity_type: type: string example: "Development" application/x-www-form-urlencoded: schema: type: object properties: data: type: object responses: "200": description: Document created content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DocType' "403": description: Insufficient Permission content: application/json: schema: type: object properties: exc: type: string example: Traceback (most recent call last) ... _error_message: type: string example: Insufficient Permission for {DocType} text/html: schema: type: string get: tags: - Examples summary: Get a list of timesheets description: Returns a list of documents of the given type parameters: - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': description: | Found some timesheets. By default, only the "name" field is included in the listing, to add more fields, you can pass the fields param to GET request. content: application/json: schema: $ref: '#/components/schemas/DocList' example: {"data":[{"name":"TS-00001"},{"name":"TS-00002"}]} /api/resource/Webhook: post: tags: - Examples summary: Create a new Webhook requestBody: content: application/json: schema: type: object properties: webhook_doctype: type: string example: "Sales Invoice" webhook_docevent: type: string example: "on_submit" request_url: type: string example: "https://my.web.service/new/invoice" webhook_headers: type: array description: Request headers, for example for authorization items: type: object properties: key: type: string example: "Authorization" value: type: string example: "Basic tZaxXzUdgCXWhokGmoFNUJDfzpfmFwmbtgebyNRMm==" webhook_data: type: array description: Map document fields to keys items: type: object properties: key: type: string example: "invoice_no" fieldname: type: string example: "name" responses: '200': $ref: '#/components/responses/GetDocumentOK' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' get: tags: - Examples summary: Get a list of Webhooks parameters: - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': $ref: '#/components/responses/GetListOK' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' /api/resource/DocType: get: tags: - Examples summary: Get a list of Doctypes parameters: - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Filters' - $ref: '#/components/parameters/PageLength' - $ref: '#/components/parameters/PageStart' responses: '200': $ref: '#/components/responses/GetListOK' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/Forbidden' components: parameters: DocType: in: path name: DocType required: true schema: type: string description: | The DocType you'd like to receive. For example Customer, Supplier, Employee, Account, Lead, Company, Sales Invoice, Purchase Invoice, Stock Entry, etc. Fields: in: query name: fields schema: type: array items: type: string default: ["name"] description: | By default, only the "name" field is included in the listing, to add more fields, you can pass the fields param to GET request. For example, fields=["name","country"] Filters: in: query name: filters schema: type: array items: type: array items: type: string description: | You can filter the listing using sql conditions by passing them as the filters GET param. Each condition is an array of the format, [{doctype}, {field}, {operator}, {value}]. For example, filters=[["Customer", "country", "=", "India"]] PageLength: in: query name: limit_page_length schema: type: integer default: 20 description: | By default, all listings are returned paginated. With this parameter you can change the page size (how many items are teturned at once). PageStart: in: query name: limit_start schema: type: integer default: 0 description: | To request successive pages, pass a multiple of your limit_page_length as limit_start. For Example, to request the second page, pass limit_start as 20. schemas: DocType: type: object properties: name: type: string modified_by: type: string creation: type: string modified: type: string doctype: type: string owner: type: string docstatus: type: integer DocList: type: object properties: data: type: array items: type: object properties: name: type: string Message: type: object properties: message: type: string responses: GetDocumentOK: description: Found requested document content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DocType' GetListOK: description: Found requested documents content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/DocList' UnauthorizedError: description: Authentication information is missing or invalid content: application/json: schema: type: object properties: exc: type: string example: Traceback (most recent call last) ... _server_messages: type: string example: "[{\"message\": \"Not permitted\"}]" text/html: schema: type: string Forbidden: description: Authentication information is missing or invalid content: application/json: schema: type: object properties: locals: type: string exc: type: string example: Traceback (most recent call last) ... _server_messages: type: string example: Incorrect password text/html: schema: type: string securitySchemes: tokenAuth: # arbitrary name type: apiKey in: header name: Authorization description: | Get your API keys at User -> Api Access -> Generate Keys. "headers = {'Authorization': 'token :'}" basicAuth: # arbitrary name type: http scheme: basic description: | Get your API keys at User -> Api Access -> Generate Keys. username = api_key; password = api_secret [More info](https://frappe.io/docs/user/en/guides/integration/token_based_auth) oAuth2: # arbitrary name type: oauth2 description: | This API uses OAuth 2 with the authorization code flow. [More info]https://frappe.io/docs/user/en/guides/integration/using_oauth) flows: authorizationCode: authorizationUrl: /method/frappe.integrations.oauth2.authorize tokenUrl: /method/frappe.integrations.oauth2.get_token refreshUrl: /method/frappe.integrations.oauth2.get_token scopes: all: Same permissions as the user who created the oAuth client externalDocs: url: https://frappe.io/docs/user/en/api/rest ```
lina2358 commented 4 years ago

image


image

lina2358 commented 4 years ago

I can manually add the resolved query parameters, then it works.

lina2358 commented 4 years ago

Moving to https://github.com/Apicurio/apicurio-data-models/issues/177

EricWittmann commented 4 years ago

The issue here is that the Apicurio Studio editor (inherited by Syndesis) does not yet support referenced parameters. This is just a gap in the editor at the moment.

schelv commented 3 years ago

Is this a duplicate of #241 ?

EricWittmann commented 3 years ago

Yes it is. Closing as a duplicate.