Skip to content

Commit 6367972

Browse files
committed
Merge 3.3
2 parents f5511ee + ea7d443 commit 6367972

File tree

11 files changed

+93
-106
lines changed

11 files changed

+93
-106
lines changed

CHANGELOG.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## v3.3.11
4+
5+
### Features
6+
7+
* [344b8b245](https://github.com/api-platform/core/commit/344b8b245ac2a77e0b22b69e7976456c024a5dcb) Revert "feat(jsonschema): make JSON-LD specific properties required (#6366)" (#6484)
8+
9+
## v3.3.10
10+
11+
### Bug fixes
12+
13+
* [6776231ed](https://github.com/api-platform/core/commit/6776231eddebb8dbb9efdc66dec29247172cf0ea) fix: remove useless deprecation (#6481)
14+
* [71dbfb1af](https://github.com/api-platform/core/commit/71dbfb1af029b4c9e7d53d9e5c2b38ff97ac68a7) fix: property called default in ApiProperty has incorrect type (#6471) (#6472)
15+
* [c3e2e5b82](https://github.com/api-platform/core/commit/c3e2e5b8298f187f34e091af0f0a58e671ae853c) fix(symfony): securityPostValidation when use_symfony_listeners (#6479)
16+
* [e3013d40d](https://github.com/api-platform/core/commit/e3013d40dc601ff580d2d69d3228c36af3f457b6) Revert "fix(jsonschema): make all required properties optional in PATCH opera…" (#6476)
17+
* [aeca0149d](https://github.com/api-platform/core/commit/aeca0149dc488ac0fefd90adaae4a65df49bab1a) fix(jsonschema): make JSON-LD specific properties required in the output schema (#6366)
18+
319
## v3.3.9
420

521
### Bug fixes
@@ -264,6 +280,12 @@ api_platform:
264280
form: ['multipart/form-data']
265281
```
266282

283+
## v3.2.26
284+
285+
### Bug fixes
286+
287+
* [6776231ed](https://github.com/api-platform/core/commit/6776231eddebb8dbb9efdc66dec29247172cf0ea) fix: remove useless deprecation (#6481)
288+
267289
## v3.2.25
268290

269291
### Bug fixes
@@ -2394,4 +2416,4 @@ Please read #2825 if you have issues with the behavior of Readable/Writable Link
23942416
## 1.0.0 beta 2
23952417

23962418
* Preserve indexes when normalizing and denormalizing associative arrays
2397-
* Allow setting default order for property when registering a `Doctrine\Orm\Filter\OrderFilter` instance
2419+
* Allow setting default order for property when registering a `Doctrine\Orm\Filter\OrderFilter` instance

features/authorization/deny.feature

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,15 @@ Feature: Authorization checking
305305
Then the response status code should be 200
306306
And the response should contain "ownerOnlyProperty"
307307
And the response should contain "attributeBasedProperty"
308+
309+
Scenario: Security post validation should be hit
310+
When I add "Content-Type" header equal to "application/ld+json"
311+
And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg=="
312+
And I send a "POST" request to "/issue_6446" with body:
313+
"""
314+
{
315+
"title": ""
316+
}
317+
"""
318+
Then the response status code should be 403
319+

features/openapi/docs.feature

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ Feature: Documentation support
153153
And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters" should have 6 elements
154154

155155
# Subcollection - check schema
156-
And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.responses.200.content.application/ld+json.schema.properties.hydra:member.items.$ref" should be equal to "#/components/schemas/RelatedToDummyFriend.jsonld-fakemanytomany.output"
156+
And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.responses.200.content.application/ld+json.schema.properties.hydra:member.items.$ref" should be equal to "#/components/schemas/RelatedToDummyFriend.jsonld-fakemanytomany"
157157

158158
# Deprecations
159159
And the JSON node "paths./dummies.get.deprecated" should be false
@@ -165,8 +165,8 @@ Feature: Documentation support
165165
And the JSON node "paths./deprecated_resources/{id}.patch.deprecated" should be true
166166

167167
# Formats
168-
And the OpenAPI class "Dummy.jsonld.output" exists
169-
And the "@id" property exists for the OpenAPI class "Dummy.jsonld.output"
168+
And the OpenAPI class "Dummy.jsonld" exists
169+
And the "@id" property exists for the OpenAPI class "Dummy.jsonld"
170170
And the JSON node "paths./dummies.get.responses.200.content.application/ld+json" should be equal to:
171171
"""
172172
{
@@ -176,7 +176,7 @@ Feature: Documentation support
176176
"hydra:member": {
177177
"type": "array",
178178
"items": {
179-
"$ref": "#/components/schemas/Dummy.jsonld.output"
179+
"$ref": "#/components/schemas/Dummy.jsonld"
180180
}
181181
},
182182
"hydra:totalItems": {

src/Documentation/Action/DocumentationAction.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ class: OpenApi::class,
101101
// TODO: support laravel this bounds Documentation with Symfony so it's not perfect
102102
$operation = $operation->withProcessor('api_platform.swagger_ui.processor')->withWrite(true);
103103
}
104-
if ('json' === $format) {
105-
trigger_deprecation('api-platform/core', '3.2', 'The "json" format is too broad, use "jsonopenapi" instead.');
106-
}
107104

108105
return $this->processor->process($this->provider->provide($operation, [], $context), $operation, [], $context);
109106
}

src/Hydra/JsonSchema/SchemaFactory.php

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareInterface
2828
{
2929
private const BASE_PROP = [
30+
'readOnly' => true,
3031
'type' => 'string',
3132
];
3233
private const BASE_PROPS = [
@@ -35,6 +36,7 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
3536
];
3637
private const BASE_ROOT_PROPS = [
3738
'@context' => [
39+
'readOnly' => true,
3840
'oneOf' => [
3941
['type' => 'string'],
4042
[
@@ -72,43 +74,18 @@ public function buildSchema(string $className, string $format = 'jsonld', string
7274
return $schema;
7375
}
7476

75-
if (($key = $schema->getRootDefinitionKey() ?? $schema->getItemsDefinitionKey()) !== null) {
76-
$postfix = '.'.$type;
77-
$definitions = $schema->getDefinitions();
78-
$definitions[$key.$postfix] = $definitions[$key];
79-
unset($definitions[$key]);
80-
81-
if (($schema['type'] ?? '') === 'array') {
82-
$schema['items']['$ref'] .= $postfix;
83-
} else {
84-
$schema['$ref'] .= $postfix;
85-
}
77+
if ('input' === $type) {
78+
return $schema;
8679
}
8780

8881
$definitions = $schema->getDefinitions();
8982
if ($key = $schema->getRootDefinitionKey()) {
9083
$definitions[$key]['properties'] = self::BASE_ROOT_PROPS + ($definitions[$key]['properties'] ?? []);
91-
if (Schema::TYPE_OUTPUT === $type) {
92-
foreach (array_keys(self::BASE_ROOT_PROPS) as $property) {
93-
$definitions[$key]['required'] ??= [];
94-
if (!\in_array($property, $definitions[$key]['required'], true)) {
95-
$definitions[$key]['required'][] = $property;
96-
}
97-
}
98-
}
9984

10085
return $schema;
10186
}
10287
if ($key = $schema->getItemsDefinitionKey()) {
10388
$definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []);
104-
if (Schema::TYPE_OUTPUT === $type) {
105-
foreach (array_keys(self::BASE_PROPS) as $property) {
106-
$definitions[$key]['required'] ??= [];
107-
if (!\in_array($property, $definitions[$key]['required'], true)) {
108-
$definitions[$key]['required'][] = $property;
109-
}
110-
}
111-
}
11289
}
11390

11491
if (($schema['type'] ?? '') === 'array') {

src/Hydra/Tests/JsonSchema/SchemaFactoryTest.php

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
use ApiPlatform\Metadata\ApiResource;
2323
use ApiPlatform\Metadata\Get;
2424
use ApiPlatform\Metadata\GetCollection;
25-
use ApiPlatform\Metadata\Post;
2625
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2726
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2827
use ApiPlatform\Metadata\Property\PropertyNameCollection;
@@ -50,7 +49,6 @@ protected function setUp(): void
5049

5150
$propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
5251
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_OUTPUT])->willReturn(new PropertyNameCollection());
53-
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_INPUT])->willReturn(new PropertyNameCollection());
5452
$propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
5553

5654
$definitionNameFactory = new DefinitionNameFactory(['jsonapi' => true, 'jsonhal' => true, 'jsonld' => true]);
@@ -70,12 +68,7 @@ public function testBuildSchema(): void
7068
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class);
7169

7270
$this->assertTrue($resultSchema->isDefined());
73-
$this->assertSame('Dummy.jsonld.output', $resultSchema->getRootDefinitionKey());
74-
75-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_INPUT, new Post());
76-
77-
$this->assertTrue($resultSchema->isDefined());
78-
$this->assertSame('Dummy.jsonld.input', $resultSchema->getRootDefinitionKey());
71+
$this->assertSame('Dummy.jsonld', $resultSchema->getRootDefinitionKey());
7972
}
8073

8174
public function testCustomFormatBuildSchema(): void
@@ -100,6 +93,7 @@ public function testHasRootDefinitionKeyBuildSchema(): void
10093
$this->assertArrayHasKey('@context', $properties);
10194
$this->assertEquals(
10295
[
96+
'readOnly' => true,
10397
'oneOf' => [
10498
['type' => 'string'],
10599
[
@@ -127,7 +121,7 @@ public function testHasRootDefinitionKeyBuildSchema(): void
127121
public function testSchemaTypeBuildSchema(): void
128122
{
129123
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection());
130-
$definitionName = 'Dummy.jsonld.output';
124+
$definitionName = 'Dummy.jsonld';
131125

132126
$this->assertNull($resultSchema->getRootDefinitionKey());
133127
// @noRector
@@ -156,12 +150,6 @@ public function testSchemaTypeBuildSchema(): void
156150
$this->assertArrayNotHasKey('@context', $properties);
157151
$this->assertArrayHasKey('@type', $properties);
158152
$this->assertArrayHasKey('@id', $properties);
159-
160-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_INPUT, new Post());
161-
$definitionName = 'Dummy.jsonld.input';
162-
163-
$this->assertSame($definitionName, $resultSchema->getRootDefinitionKey());
164-
$this->assertFalse(isset($resultSchema['properties']));
165153
}
166154

167155
public function testHasHydraViewNavigationBuildSchema(): void
@@ -179,36 +167,4 @@ public function testHasHydraViewNavigationBuildSchema(): void
179167
$this->assertArrayHasKey('hydra:previous', $resultSchema['properties']['hydra:view']['properties']);
180168
$this->assertArrayHasKey('hydra:next', $resultSchema['properties']['hydra:view']['properties']);
181169
}
182-
183-
public function testRequiredBasePropertiesBuildSchema(): void
184-
{
185-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class);
186-
$definitions = $resultSchema->getDefinitions();
187-
$rootDefinitionKey = $resultSchema->getRootDefinitionKey();
188-
189-
$this->assertTrue(isset($definitions[$rootDefinitionKey]));
190-
$this->assertTrue(isset($definitions[$rootDefinitionKey]['required']));
191-
$requiredProperties = $resultSchema['definitions'][$rootDefinitionKey]['required'];
192-
$this->assertContains('@context', $requiredProperties);
193-
$this->assertContains('@id', $requiredProperties);
194-
$this->assertContains('@type', $requiredProperties);
195-
196-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection());
197-
$definitions = $resultSchema->getDefinitions();
198-
$itemsDefinitionKey = array_key_first($definitions->getArrayCopy());
199-
200-
$this->assertTrue(isset($definitions[$itemsDefinitionKey]));
201-
$this->assertTrue(isset($definitions[$itemsDefinitionKey]['required']));
202-
$requiredProperties = $resultSchema['definitions'][$itemsDefinitionKey]['required'];
203-
$this->assertNotContains('@context', $requiredProperties);
204-
$this->assertContains('@id', $requiredProperties);
205-
$this->assertContains('@type', $requiredProperties);
206-
207-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_INPUT, new Post());
208-
$definitions = $resultSchema->getDefinitions();
209-
$itemsDefinitionKey = array_key_first($definitions->getArrayCopy());
210-
211-
$this->assertTrue(isset($definitions[$itemsDefinitionKey]));
212-
$this->assertFalse(isset($definitions[$itemsDefinitionKey]['required']));
213-
}
214170
}

src/Metadata/ApiProperty.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ final class ApiProperty
2828
* @param bool|null $writableLink https://api-platform.com/docs/core/serialization/#force-iri-with-relations-of-the-same-type-parentchilds-relations
2929
* @param bool|null $required https://api-platform.com/docs/admin/validation/#client-side-validation
3030
* @param bool|null $identifier https://api-platform.com/docs/core/identifiers/
31-
* @param string|null $default
3231
* @param mixed $example https://api-platform.com/docs/core/openapi/#using-the-openapi-and-swagger-contexts
3332
* @param string|null $deprecationReason https://api-platform.com/docs/core/deprecations/#deprecating-resource-classes-operations-and-properties
3433
* @param bool|null $fetchEager https://api-platform.com/docs/core/performance/#eager-loading
@@ -51,7 +50,7 @@ public function __construct(
5150
private ?bool $writableLink = null,
5251
private ?bool $required = null,
5352
private ?bool $identifier = null,
54-
private $default = null,
53+
private mixed $default = null,
5554
private mixed $example = null,
5655
/**
5756
* The `deprecationReason` option deprecates the current operation with a deprecation message.

src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ private function registerSecurityConfiguration(ContainerBuilder $container, arra
818818

819819
$loader->load('state/security.xml');
820820

821-
if (interface_exists(ValidatorInterface::class) && !$config['use_symfony_listeners']) {
821+
if (interface_exists(ValidatorInterface::class)) {
822822
$loader->load('state/security_validator.xml');
823823
}
824824

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6446;
15+
16+
use ApiPlatform\Metadata\Post;
17+
use Symfony\Component\Validator\Constraints\NotNull;
18+
19+
#[Post(uriTemplate: 'issue_6446', securityPostValidation: 'is_granted(\'ROLE_ADMIN\')')]
20+
class SecurityPostValidation
21+
{
22+
#[NotNull]
23+
public string $title;
24+
}

0 commit comments

Comments
 (0)