From 876e675fb8e4350ee61f3b03c46f637706c74fc2 Mon Sep 17 00:00:00 2001 From: Quentin de Longraye Date: Sat, 15 Feb 2020 11:26:53 +0100 Subject: [PATCH 1/3] set additional properties to false to allow better type checkings from json schemas --- src/JsonSchema/SchemaFactory.php | 1 + tests/JsonSchema/SchemaFactoryTest.php | 1 + .../DocumentationNormalizerV2Test.php | 24 +++++++++++++++++++ .../DocumentationNormalizerV3Test.php | 21 ++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index fe673a83bfc..0f51f4a2e57 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -110,6 +110,7 @@ public function buildSchema(string $className, string $format = 'json', string $ } $definition = new \ArrayObject(['type' => 'object']); + $definition["additionalProperties"] = false; $definitions[$definitionName] = $definition; if (null !== $resourceMetadata && null !== $description = $resourceMetadata->getDescription()) { $definition['description'] = $description; diff --git a/tests/JsonSchema/SchemaFactoryTest.php b/tests/JsonSchema/SchemaFactoryTest.php index 03e474716cc..f08cf011576 100644 --- a/tests/JsonSchema/SchemaFactoryTest.php +++ b/tests/JsonSchema/SchemaFactoryTest.php @@ -73,5 +73,6 @@ public function testBuildSchemaForNonResourceClass(): void $this->assertArrayHasKey('bar', $definitions[$rootDefinitionKey]['properties']); $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['bar']); $this->assertSame('integer', $definitions[$rootDefinitionKey]['properties']['bar']['type']); + $this->assertSame(false, $definitions[$rootDefinitionKey]['additionalProperties']); } } diff --git a/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php b/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php index c298da54a6c..5fe2791843f 100644 --- a/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php +++ b/tests/Swagger/Serializer/DocumentationNormalizerV2Test.php @@ -348,6 +348,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'description' => 'This is a \DateTimeInterface object.', 'format' => 'date-time', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -488,6 +489,7 @@ interface_exists(AdvancedNameConverterInterface::class) 'description' => 'This is a converted name.', ]), ], + 'additionalProperties' => false, ]), ]), 'securityDefinitions' => [ @@ -596,6 +598,7 @@ public function testNormalizeWithApiKeysEnabled(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), 'securityDefinitions' => [ @@ -786,6 +789,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), $ref => new \ArrayObject([ 'type' => 'object', @@ -797,6 +801,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -981,6 +986,7 @@ public function testNormalizeNotAddExtraBodyParameters(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), $ref => new \ArrayObject([ 'type' => 'object', @@ -992,6 +998,7 @@ public function testNormalizeNotAddExtraBodyParameters(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -1081,6 +1088,7 @@ public function testNormalizeWithSwaggerDefinitionName(): void 'readOnly' => true, ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -1250,6 +1258,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), 'Dummy-dummy' => new \ArrayObject([ 'type' => 'object', @@ -1261,6 +1270,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -1433,6 +1443,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), 'Dummy-dummy' => new \ArrayObject([ 'type' => 'object', @@ -1444,6 +1455,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -1625,6 +1637,7 @@ public function testNormalizeSkipsNotReadableAndNotWritableProperties(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2007,6 +2020,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), $ref => new \ArrayObject([ 'type' => 'object', @@ -2022,6 +2036,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void '$ref' => '#/definitions/'.$relatedDummyRef, ]), ], + 'additionalProperties' => false, ]), $relatedDummyRef => new \ArrayObject([ 'type' => 'object', @@ -2033,6 +2048,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2141,6 +2157,7 @@ private function normalizeWithFilters($filterLocator): void 'type' => 'string', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2303,6 +2320,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt 'items' => ['$ref' => '#/definitions/Answer'], ]), ], + 'additionalProperties' => false, ]), 'Answer' => new \ArrayObject([ 'type' => 'object', @@ -2315,6 +2333,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt 'items' => ['$ref' => '#/definitions/Answer'], ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2404,6 +2423,7 @@ public function testNormalizeWithPropertySwaggerContext(): void 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2504,6 +2524,7 @@ public function testNormalizeWithPaginationClientEnabled(): void 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2697,6 +2718,7 @@ private function doTestNormalizeWithCustomFormatsDefinedAtOperationLevel(Operati 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), ]; @@ -2911,6 +2933,7 @@ private function doTestNormalizeWithInputAndOutputClass(): void 'type' => 'integer', ]), ], + 'additionalProperties' => false, ]), 'Dummy:InputDto' => new \ArrayObject([ 'type' => 'object', @@ -2929,6 +2952,7 @@ private function doTestNormalizeWithInputAndOutputClass(): void 'type' => 'integer', ]), ], + 'additionalProperties' => false, ]), ]), ]; diff --git a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php index d6250fb3b90..f51d89ec11c 100644 --- a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php +++ b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php @@ -390,6 +390,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'format' => 'date-time', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -549,6 +550,7 @@ private function doTestNormalizeWithNameConverter(bool $legacy = false): void 'description' => 'This is a converted name.', ]), ], + 'additionalProperties' => false, ]), ]), 'securitySchemes' => [ @@ -677,6 +679,7 @@ public function testNormalizeWithApiKeysEnabled(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), 'securitySchemes' => [ @@ -907,6 +910,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), $ref => new \ArrayObject([ 'type' => 'object', @@ -918,6 +922,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -1031,6 +1036,7 @@ public function testNormalizeWithOpenApiDefinitionName(): void 'readOnly' => true, ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -1239,6 +1245,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), 'Dummy-dummy' => new \ArrayObject([ 'type' => 'object', @@ -1250,6 +1257,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -1460,6 +1468,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), 'Dummy-dummy' => new \ArrayObject([ 'type' => 'object', @@ -1471,6 +1480,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void 'description' => 'This is a gerard.', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -1985,6 +1995,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), $ref => new \ArrayObject([ 'type' => 'object', @@ -2000,6 +2011,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void '$ref' => '#/components/schemas/'.$relatedDummyRef, ]), ], + 'additionalProperties' => false, ]), $relatedDummyRef => new \ArrayObject([ 'type' => 'object', @@ -2011,6 +2023,7 @@ public function testNormalizeWithNestedNormalizationGroups(): void 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2155,6 +2168,7 @@ private function normalizeWithFilters($filterLocator): void 'type' => 'string', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2330,6 +2344,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt 'items' => ['$ref' => '#/components/schemas/Answer'], ]), ], + 'additionalProperties' => false, ]), 'Answer' => new \ArrayObject([ 'type' => 'object', @@ -2342,6 +2357,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt 'items' => ['$ref' => '#/components/schemas/Answer'], ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2456,6 +2472,7 @@ public function testNormalizeWithPropertyOpenApiContext(): void 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2583,6 +2600,7 @@ public function testNormalizeWithPaginationClientEnabled(): void 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2716,6 +2734,7 @@ public function testNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage(): vo 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -2853,6 +2872,7 @@ public function testLegacyNormalizeWithPaginationCustomDefaultAndMaxItemsPerPage 'example' => 'one', ]), ], + 'additionalProperties' => false, ]), ]), ], @@ -3089,6 +3109,7 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw 'description' => 'This is a name.', ]), ], + 'additionalProperties' => false, ]), ]), ], From f6cd25d249361f2824991a0dbbef64e83cb3ee0c Mon Sep 17 00:00:00 2001 From: Quentin de Longraye Date: Sat, 15 Feb 2020 11:34:58 +0100 Subject: [PATCH 2/3] update changelog file --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbbeca40277..70fea61fcf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * GraphQL: Allow to format GraphQL errors based on exceptions (#3063) * GraphQL: Add page-based pagination (#3175) * OpenAPI: Add PHP default values to the documentation (#2386) +* OpenAPI: Set additional properties to false on all definitions (#3388) ## 2.5.4 From 30cb24f2542ec0131f3d7167506bcff52624de7f Mon Sep 17 00:00:00 2001 From: Quentin de Longraye Date: Sat, 15 Feb 2020 11:41:06 +0100 Subject: [PATCH 3/3] cs fix --- src/JsonSchema/SchemaFactory.php | 2 +- tests/JsonSchema/SchemaFactoryTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index 0f51f4a2e57..cffd09cd6e7 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -110,7 +110,7 @@ public function buildSchema(string $className, string $format = 'json', string $ } $definition = new \ArrayObject(['type' => 'object']); - $definition["additionalProperties"] = false; + $definition['additionalProperties'] = false; $definitions[$definitionName] = $definition; if (null !== $resourceMetadata && null !== $description = $resourceMetadata->getDescription()) { $definition['description'] = $description; diff --git a/tests/JsonSchema/SchemaFactoryTest.php b/tests/JsonSchema/SchemaFactoryTest.php index f08cf011576..ffe726b8a1d 100644 --- a/tests/JsonSchema/SchemaFactoryTest.php +++ b/tests/JsonSchema/SchemaFactoryTest.php @@ -73,6 +73,6 @@ public function testBuildSchemaForNonResourceClass(): void $this->assertArrayHasKey('bar', $definitions[$rootDefinitionKey]['properties']); $this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['bar']); $this->assertSame('integer', $definitions[$rootDefinitionKey]['properties']['bar']['type']); - $this->assertSame(false, $definitions[$rootDefinitionKey]['additionalProperties']); + $this->assertFalse($definitions[$rootDefinitionKey]['additionalProperties']); } }