From 9470ed8af1982ebeacc3c5eb1b26f67ac67bd7cb Mon Sep 17 00:00:00 2001 From: Viacheslav Poturaev Date: Mon, 19 Aug 2019 13:36:53 +0200 Subject: [PATCH 1/2] Restrict references to typed components --- schemas/v3.0/schema.json | 261 ++++++++++++++++++++++++++++++++++----- schemas/v3.0/schema.yaml | 177 +++++++++++++++++++++----- 2 files changed, 376 insertions(+), 62 deletions(-) diff --git a/schemas/v3.0/schema.json b/schemas/v3.0/schema.json index 71808402f6..e393bece01 100644 --- a/schemas/v3.0/schema.json +++ b/schemas/v3.0/schema.json @@ -46,8 +46,7 @@ } }, "patternProperties": { - "^x-": { - } + "^x-": {} }, "additionalProperties": false, "definitions": { @@ -199,7 +198,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] } @@ -211,7 +210,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ResponseReference" }, { "$ref": "#/definitions/Response" @@ -226,7 +225,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ParameterReference" }, { "$ref": "#/definitions/Parameter" @@ -241,7 +240,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ExampleReference" }, { "$ref": "#/definitions/Example" @@ -256,7 +255,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/RequestBodyReference" }, { "$ref": "#/definitions/RequestBody" @@ -271,7 +270,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/HeaderReference" }, { "$ref": "#/definitions/Header" @@ -286,7 +285,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SecuritySchemeReference" }, { "$ref": "#/definitions/SecurityScheme" @@ -301,7 +300,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/LinkReference" }, { "$ref": "#/definitions/Link" @@ -316,7 +315,7 @@ "^[a-zA-Z0-9\\.\\-_]+$": { "oneOf": [ { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/CallbackReference" }, { "$ref": "#/definitions/Callback" @@ -332,6 +331,28 @@ }, "additionalProperties": false }, + "SchemaReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/schemas/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Schema": { "type": "object", "properties": { @@ -424,7 +445,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] }, @@ -436,7 +457,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] } @@ -449,7 +470,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] } @@ -462,7 +483,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] } @@ -473,7 +494,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] }, @@ -485,7 +506,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] } @@ -496,7 +517,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" }, { "type": "boolean" @@ -591,6 +612,28 @@ }, "additionalProperties": false }, + "ResponseReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/responses/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Response": { "type": "object", "required": [ @@ -608,7 +651,7 @@ "$ref": "#/definitions/Header" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/HeaderReference" } ] } @@ -627,7 +670,7 @@ "$ref": "#/definitions/Link" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/LinkReference" } ] } @@ -648,7 +691,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] }, @@ -662,7 +705,7 @@ "$ref": "#/definitions/Example" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ExampleReference" } ] } @@ -685,6 +728,28 @@ } ] }, + "ExampleReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/examples/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Example": { "type": "object", "properties": { @@ -707,6 +772,28 @@ }, "additionalProperties": false }, + "HeaderReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/headers/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Header": { "type": "object", "properties": { @@ -745,7 +832,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] }, @@ -767,7 +854,7 @@ "$ref": "#/definitions/Example" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ExampleReference" } ] } @@ -824,7 +911,7 @@ "$ref": "#/definitions/Parameter" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ParameterReference" } ] }, @@ -872,7 +959,7 @@ "$ref": "#/definitions/Parameter" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ParameterReference" } ] }, @@ -884,7 +971,7 @@ "$ref": "#/definitions/RequestBody" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/RequestBodyReference" } ] }, @@ -899,7 +986,7 @@ "$ref": "#/definitions/Callback" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/CallbackReference" } ] } @@ -936,7 +1023,7 @@ "$ref": "#/definitions/Response" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ResponseReference" } ] } @@ -948,7 +1035,7 @@ "$ref": "#/definitions/Response" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ResponseReference" } ] }, @@ -1077,6 +1164,28 @@ } ] }, + "ParameterReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/parameters/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Parameter": { "type": "object", "properties": { @@ -1117,7 +1226,7 @@ "$ref": "#/definitions/Schema" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/SchemaReference" } ] }, @@ -1139,7 +1248,7 @@ "$ref": "#/definitions/Example" }, { - "$ref": "#/definitions/Reference" + "$ref": "#/definitions/ExampleReference" } ] } @@ -1248,6 +1357,28 @@ } ] }, + "RequestBodyReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/requestBodies/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "RequestBody": { "type": "object", "required": [ @@ -1274,6 +1405,28 @@ }, "additionalProperties": false }, + "SecuritySchemeReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/securitySchemes/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "SecurityScheme": { "oneOf": [ { @@ -1572,6 +1725,28 @@ }, "additionalProperties": false }, + "LinkReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/links/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Link": { "type": "object", "properties": { @@ -1609,6 +1784,28 @@ ] } }, + "CallbackReference": { + "type": "object", + "required": [ + "$ref" + ], + "patternProperties": { + "^\\$ref$": { + "type": "string", + "format": "uri-reference", + "oneOf": [ + { + "pattern": "^#/components/callbacks/" + }, + { + "not": { + "pattern": "^#/" + } + } + ] + } + } + }, "Callback": { "type": "object", "additionalProperties": { diff --git a/schemas/v3.0/schema.yaml b/schemas/v3.0/schema.yaml index 13e47ff08d..9196c5d602 100644 --- a/schemas/v3.0/schema.yaml +++ b/schemas/v3.0/schema.yaml @@ -139,67 +139,80 @@ definitions: '^[a-zA-Z0-9\.\-_]+$': oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' responses: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ResponseReference' - $ref: '#/definitions/Response' parameters: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ParameterReference' - $ref: '#/definitions/Parameter' examples: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ExampleReference' - $ref: '#/definitions/Example' requestBodies: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/RequestBodyReference' - $ref: '#/definitions/RequestBody' headers: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/HeaderReference' - $ref: '#/definitions/Header' securitySchemes: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SecuritySchemeReference' - $ref: '#/definitions/SecurityScheme' links: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/LinkReference' - $ref: '#/definitions/Link' callbacks: type: object patternProperties: '^[a-zA-Z0-9\.\-_]+$': oneOf: - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/CallbackReference' - $ref: '#/definitions/Callback' patternProperties: '^x-': {} additionalProperties: false + SchemaReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/schemas/' + - not: + pattern: '^#/' + Schema: type: object properties: @@ -269,39 +282,39 @@ definitions: not: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' allOf: type: array items: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' oneOf: type: array items: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' anyOf: type: array items: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' items: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' properties: type: object additionalProperties: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' additionalProperties: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' - type: boolean default: true description: @@ -364,6 +377,19 @@ definitions: '^x-': {} additionalProperties: false + ResponseReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/responses/' + - not: + pattern: '^#/' + Response: type: object required: @@ -376,7 +402,7 @@ definitions: additionalProperties: oneOf: - $ref: '#/definitions/Header' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/HeaderReference' content: type: object additionalProperties: @@ -386,7 +412,7 @@ definitions: additionalProperties: oneOf: - $ref: '#/definitions/Link' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/LinkReference' patternProperties: '^x-': {} additionalProperties: false @@ -397,14 +423,14 @@ definitions: schema: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' example: {} examples: type: object additionalProperties: oneOf: - $ref: '#/definitions/Example' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ExampleReference' encoding: type: object additionalProperties: @@ -415,6 +441,19 @@ definitions: allOf: - $ref: '#/definitions/ExampleXORExamples' + ExampleReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/examples/' + - not: + pattern: '^#/' + Example: type: object properties: @@ -430,6 +469,19 @@ definitions: '^x-': {} additionalProperties: false + HeaderReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/headers/' + - not: + pattern: '^#/' + Header: type: object properties: @@ -457,7 +509,7 @@ definitions: schema: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' content: type: object additionalProperties: @@ -470,7 +522,7 @@ definitions: additionalProperties: oneOf: - $ref: '#/definitions/Example' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ExampleReference' patternProperties: '^x-': {} additionalProperties: false @@ -504,7 +556,7 @@ definitions: items: oneOf: - $ref: '#/definitions/Parameter' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ParameterReference' uniqueItems: true patternProperties: '^(get|put|post|delete|options|head|patch|trace)$': @@ -534,12 +586,12 @@ definitions: items: oneOf: - $ref: '#/definitions/Parameter' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ParameterReference' uniqueItems: true requestBody: oneOf: - $ref: '#/definitions/RequestBody' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/RequestBodyReference' responses: $ref: '#/definitions/Responses' callbacks: @@ -547,7 +599,7 @@ definitions: additionalProperties: oneOf: - $ref: '#/definitions/Callback' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/CallbackReference' deprecated: type: boolean default: false @@ -569,12 +621,12 @@ definitions: default: oneOf: - $ref: '#/definitions/Response' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ResponseReference' patternProperties: '^[1-5](?:\d{2}|XX)$': oneOf: - $ref: '#/definitions/Response' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ResponseReference' '^x-': {} minProperties: 1 additionalProperties: false @@ -641,6 +693,19 @@ definitions: - not: required: [examples] + ParameterReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/parameters/' + - not: + pattern: '^#/' + Parameter: type: object properties: @@ -669,7 +734,7 @@ definitions: schema: oneOf: - $ref: '#/definitions/Schema' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/SchemaReference' content: type: object additionalProperties: @@ -682,7 +747,7 @@ definitions: additionalProperties: oneOf: - $ref: '#/definitions/Example' - - $ref: '#/definitions/Reference' + - $ref: '#/definitions/ExampleReference' patternProperties: '^x-': {} additionalProperties: false @@ -733,6 +798,19 @@ definitions: enum: [form] default: form + RequestBodyReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/requestBodies/' + - not: + pattern: '^#/' + RequestBody: type: object required: @@ -751,6 +829,19 @@ definitions: '^x-': {} additionalProperties: false + SecuritySchemeReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/securitySchemes/' + - not: + pattern: '^#/' + SecurityScheme: oneOf: - $ref: '#/definitions/APIKeySecurityScheme' @@ -949,6 +1040,19 @@ definitions: '^x-': {} additionalProperties: false + LinkReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/links/' + - not: + pattern: '^#/' + Link: type: object properties: @@ -972,6 +1076,19 @@ definitions: description: Operation Id and Operation Ref are mutually exclusive required: [operationId, operationRef] + CallbackReference: + type: object + required: + - $ref + patternProperties: + '^\$ref$': + type: string + format: uri-reference + oneOf: + - pattern: '^#/components/callbacks/' + - not: + pattern: '^#/' + Callback: type: object additionalProperties: From f54e5fea0889130383488306d905d4acbb632d97 Mon Sep 17 00:00:00 2001 From: Viacheslav Poturaev Date: Mon, 19 Aug 2019 17:27:10 +0200 Subject: [PATCH 2/2] Move shared response to components to reduce code duplication of example schema --- examples/v3.0/petstore.yaml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/examples/v3.0/petstore.yaml b/examples/v3.0/petstore.yaml index 534bb0cd77..2adc81b53a 100644 --- a/examples/v3.0/petstore.yaml +++ b/examples/v3.0/petstore.yaml @@ -30,15 +30,11 @@ paths: schema: type: string content: - application/json: + application/json: schema: $ref: "#/components/schemas/Pets" default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/responses/UnexpectedError" post: summary: Create a pet operationId: createPets @@ -48,11 +44,7 @@ paths: '201': description: Null response default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/responses/UnexpectedError" /pets/{petId}: get: summary: Info for a specific pet @@ -74,12 +66,16 @@ paths: schema: $ref: "#/components/schemas/Pet" default: - description: unexpected error - content: - application/json: - schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/responses/UnexpectedError" components: + responses: + UnexpectedError: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + schemas: Pet: type: object