Skip to content

Commit cba3acf

Browse files
committed
fix(graphql): property security might be cached w/ different objects
1 parent f4c426d commit cba3acf

File tree

6 files changed

+403
-0
lines changed

6 files changed

+403
-0
lines changed

src/GraphQl/Serializer/ItemNormalizer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public function normalize(mixed $object, ?string $format = null, array $context
8989

9090
if ($this->isCacheKeySafe($context)) {
9191
$context['cache_key'] = $this->getCacheKey($format, $context);
92+
} else {
93+
$context['cache_key'] = false;
9294
}
9395

9496
unset($context['operation_name'], $context['operation']); // Remove operation and operation_name only when cache key has been created
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
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\Document;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\GraphQl\Query;
19+
use ApiPlatform\Metadata\GraphQl\QueryCollection;
20+
use ApiPlatform\Metadata\NotExposed;
21+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
22+
23+
/**
24+
* Secured resource.
25+
*/
26+
#[ApiResource(
27+
operations: [
28+
new NotExposed(),
29+
],
30+
graphQlOperations: [
31+
new Query(),
32+
new QueryCollection(),
33+
],
34+
security: 'is_granted(\'ROLE_USER\')'
35+
)]
36+
#[ODM\Document]
37+
class SecuredDummyCollection
38+
{
39+
#[ODM\Id(strategy: 'AUTO', type: 'integer')]
40+
public ?int $id = null;
41+
42+
/**
43+
* @var string The title
44+
*/
45+
#[ODM\Field]
46+
public string $title;
47+
48+
/**
49+
* @var string Secret property, only readable/writable by owners
50+
*/
51+
#[ApiProperty(security: 'object == null or object.owner == user', securityPostDenormalize: 'object.owner == user')]
52+
#[ODM\Field]
53+
public ?string $ownerOnlyProperty = null;
54+
55+
/**
56+
* @var string The owner
57+
*/
58+
#[ODM\Field]
59+
public string $owner;
60+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
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\Document;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\GraphQl\Query;
18+
use ApiPlatform\Metadata\GraphQl\QueryCollection;
19+
use ApiPlatform\Metadata\NotExposed;
20+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
21+
22+
/**
23+
* Secured resource.
24+
*/
25+
#[ApiResource(
26+
operations: [
27+
new NotExposed(),
28+
],
29+
graphQlOperations: [
30+
new Query(),
31+
new QueryCollection(),
32+
],
33+
security: 'is_granted(\'ROLE_USER\')'
34+
)]
35+
#[ODM\Document]
36+
class SecuredDummyCollectionParent
37+
{
38+
#[ODM\Id]
39+
#[ODM\Field(type: 'id')]
40+
public ?string $id = null;
41+
42+
#[ODM\ReferenceOne(targetDocument: SecuredDummyCollection::class, inversedBy: 'parents')]
43+
#[ODM\Field(nullable: false)]
44+
public SecuredDummyCollection $child;
45+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
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\Entity;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\GraphQl\Query;
19+
use ApiPlatform\Metadata\GraphQl\QueryCollection;
20+
use ApiPlatform\Metadata\NotExposed;
21+
use Doctrine\ORM\Mapping as ORM;
22+
23+
/**
24+
* Secured resource.
25+
*/
26+
#[ApiResource(
27+
operations: [
28+
new NotExposed(),
29+
],
30+
graphQlOperations: [
31+
new Query(),
32+
new QueryCollection(),
33+
],
34+
security: 'is_granted(\'ROLE_USER\')'
35+
)]
36+
#[ORM\Entity]
37+
class SecuredDummyCollection
38+
{
39+
#[ORM\Column(type: 'integer')]
40+
#[ORM\Id]
41+
#[ORM\GeneratedValue(strategy: 'AUTO')]
42+
public ?int $id = null;
43+
44+
/**
45+
* @var string The title
46+
*/
47+
#[ORM\Column]
48+
public string $title;
49+
50+
/**
51+
* @var string Secret property, only readable/writable by owners
52+
*/
53+
#[ApiProperty(security: 'object == null or object.owner == user', securityPostDenormalize: 'object.owner == user')]
54+
#[ORM\Column]
55+
public ?string $ownerOnlyProperty = null;
56+
57+
/**
58+
* @var string The owner
59+
*/
60+
#[ORM\Column]
61+
public string $owner;
62+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
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\Entity;
15+
16+
use ApiPlatform\Metadata\ApiResource;
17+
use ApiPlatform\Metadata\GraphQl\Query;
18+
use ApiPlatform\Metadata\GraphQl\QueryCollection;
19+
use ApiPlatform\Metadata\NotExposed;
20+
use Doctrine\ORM\Mapping as ORM;
21+
22+
/**
23+
* Secured resource.
24+
*/
25+
#[ApiResource(
26+
operations: [
27+
new NotExposed(),
28+
],
29+
graphQlOperations: [
30+
new Query(),
31+
new QueryCollection(),
32+
],
33+
security: 'is_granted(\'ROLE_USER\')'
34+
)]
35+
#[ORM\Entity]
36+
class SecuredDummyCollectionParent
37+
{
38+
#[ORM\Column(type: 'integer')]
39+
#[ORM\Id]
40+
#[ORM\GeneratedValue(strategy: 'AUTO')]
41+
public ?int $id = null;
42+
43+
#[ORM\ManyToOne]
44+
#[ORM\JoinColumn(nullable: false)]
45+
public SecuredDummyCollection $child;
46+
}

0 commit comments

Comments
 (0)