Gi60s / openapi-enforcer

Apache License 2.0
94 stars 22 forks source link

`examples` validation does not match OAS 3 #88

Closed uglow closed 4 years ago

uglow commented 4 years ago

Firstly, great library! We're using it for the schema validation in oaat.

However, I think there's an issue in the way that examples are validated. According to https://swagger.io/docs/specification/adding-examples/ , It should be possible to have:

    "/foo/{requestType}": {
      "get": {
        "parameters": [
          {
            "name": "requestType",
            "in": "path",
            "description": "The requestType key",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "eligibility",
                "products",
                "products/eligibility",
                "services"
              ]
            },
            "examples": {
              "products": {
                "value": "products"
              },
              "service": {
                "value": "services"
              },
              "eligibility-enterprise": {
                "value": "eligibility"
              },
              "eligibility-inactive": {
                "value": "eligibility"
              },
              "invalidToken": {
                "value": "eligibility"
              }
            }
          }
  ...

However, the OpenAPI Enforcer says:

 One or more errors exist in the OpenApi definition
  at: paths
    at: /foo/{requestType} > get > parameters > 1 > examples
      at: products
        Unable to deserialize value
          Expected a string. Received: undefined
      at: service
        Unable to deserialize value
          Expected a string. Received: undefined
      at: eligibility-enterprise
        Unable to deserialize value
          Expected a string. Received: undefined
      at: eligibility-inactive
        Unable to deserialize value
          Expected a string. Received: undefined

Looking at the code, I think this line is the problem: https://github.com/byu-oit/openapi-enforcer/blob/4f2f64ebc70af54da5beca6f6fce4ddfec28bb65/src/validator-parameter-base.js#L99

It permits an examples object, but then expects that the child property will be an Example, rather than a { key: Example }, as OAS 3 indicates it should be.

In summary, this should be valid: examples: { key: { value: ... } }, but Open API Enforcer says that it is not.

Gi60s commented 4 years ago

Wow, it looks like you've done your research here. That and the fact that you've provided me an example should make this a pretty quick fix.

I'm glad your enjoying the library too.

I'll get working on this today.

Gi60s commented 4 years ago

Will you try out openapi-enforcer version 1.10.8? I fixed a problem with the example validator for issue #85. Running a test using your provided code I'm not picking up any errors, so I'm wondering if the 1.10.8 fix also fixed this problem.

uglow commented 4 years ago

Hi James, I've updated to 1.10.8, and the library is saying that this JSON is now valid:

{
  "openapi": "3.0.0",
  "info": {
    "description": "Fake Online REST API for Testing and Prototyping",
    "version": "1.0.0",
    "title": "JSON Placeholder"
  },
  "tags": [
    {
      "name": "posts"
    }
  ],
  "servers": [
    {
      "url": "https://jsonplaceholder.typicode.com"
    }
  ],
  "paths": {
    "/posts": {
      "get": {
        "tags": [
          "posts"
        ],
        "summary": "Get all available posts",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "description": "Filter by post ID",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "description": "Filter by user ID",
            "required": false,
            "schema": {
              "type": "string"
            },
            "examples": {
              "products": {
                "value": "products"
              },
              "service": {
                "value": "services"
              },
              "eligibility-enterprise": {
                "value": "eligibility"
              },
              "eligibility-inactive": {
                "value": "eligibility"
              },
              "invalidToken": {
                "value": "eligibility"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Post"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Post": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "userId": {
            "type": "integer",
            "format": "int64"
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "company": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "catchPhrase": {
                "type": "string"
              },
              "bs": {
                "type": "string"
              }
            }
          },
          "address": {
            "type": "object",
            "properties": {
              "street": {
                "type": "string"
              },
              "suite": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "zipcode": {
                "type": "string"
              },
              "geo": {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "string"
                  },
                  "lng": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Swagger UI: No errors

Upon further digging, I think the problem was on my end. I was generating some examples for a multi-parameter API, where the first parameter's examples were correct, but the second parameter's examples were:

"examples": {
              "products": {},
              "services": {},
              "eligibility-enterprise": {},
              "eligibility-inactive": {},
              "invalidToken": {
                "value": "not a valid token"
              }
            }

...which is wrong. Thanks for looking into this. 👍

Gi60s commented 4 years ago

Glad I could help.