kogosoftwarellc / open-api

A Monorepo of various packages to power OpenAPI in node
MIT License
895 stars 237 forks source link

openapi-request-validator: Add ability to validate schemas that references schema object properties. #708

Closed zishone closed 3 years ago

zishone commented 3 years ago

Hello!

I am opening this PR to add the ability to validate schemas that reference properties of object schema definitions.

Given

{
  "paths": {
    "/login": {
      "requestBody": {
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "login": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/User/properties/username"
                    },
                    {
                      "$ref": "#/components/schemas/User/properties/email"
                    }
                  ]
                },
                "password": {
                  "$ref": "#/components/schemas/schemas/User/properties/password"
                }
              }
            }
          }
        },
        "required": true
      }
    }
  },
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "username": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "minLength": 8
          },
          "data": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "foo": {
                    "type": "number"
                  }
                }
              },
              {
                "type": "object",
                "properties": {
                  "bar": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "list": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "baz": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      }
    }
  }
}

The Problem

Currently when a request is made, the validation responds that it cannot resolve the following references:

[
  {
    "path": "login",
    "message": "can't resolve reference #/components/schemas/User/properties/username",
    "location": "body",
    "schema": {
      "$ref": "#/components/schemas/User/properties/username"
    }
  },
  {
    "path": "login",
    "message": "can't resolve reference #/components/schemas/User/properties/email",
    "location": "body",
    "schema": {
      "$ref": "#/components/schemas/User/properties/email"
    }
  },
  {
    "path": "login",
    "errorCode": "oneOf.openapi.requestValidation",
    "message": "should match exactly one schema in oneOf",
    "location": "body"
  },
  {
    "path": "password",
    "message": "can't resolve reference #/components/schemas/User/properties/password",
    "location": "body",
    "schema": {
      "$ref": "#/components/schemas/User/properties/password"
    }
  }
]

The Solution

I added the addSchemaProperties method that will traverse each schema's nested properties recursively and add it to the v. With this, properties should be reference-able no matter how deep they are in their schema definitions.

It also takes into account:

Regards, @zishone