Skip to content

Commit e223921

Browse files
authored
fix(state): security parameter with listeners (#6457)
1 parent 090b2fb commit e223921

File tree

4 files changed

+16
-21
lines changed

4 files changed

+16
-21
lines changed

src/State/Provider/SecurityParameterProvider.php

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
use ApiPlatform\Metadata\GraphQl\Operation as GraphQlOperation;
1717
use ApiPlatform\Metadata\Operation;
1818
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
19+
use ApiPlatform\State\ParameterNotFound;
1920
use ApiPlatform\State\ProviderInterface;
2021
use ApiPlatform\State\Util\ParameterParserTrait;
2122
use ApiPlatform\Symfony\Security\Exception\AccessDeniedException;
22-
use Symfony\Component\HttpFoundation\Request;
2323
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
2424

2525
/**
@@ -30,36 +30,31 @@ final class SecurityParameterProvider implements ProviderInterface
3030
{
3131
use ParameterParserTrait;
3232

33-
public function __construct(private readonly ?ProviderInterface $decorated = null, private readonly ?ResourceAccessCheckerInterface $resourceAccessChecker = null)
33+
public function __construct(private readonly ProviderInterface $decorated, private readonly ?ResourceAccessCheckerInterface $resourceAccessChecker = null)
3434
{
3535
}
3636

3737
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
3838
{
39-
if (!($request = $context['request']) instanceof Request) {
40-
return $this->decorated->provide($operation, $uriVariables, $context);
41-
}
42-
43-
/** @var Operation $apiOperation */
44-
$apiOperation = $request->attributes->get('_api_operation');
39+
$body = $this->decorated->provide($operation, $uriVariables, $context);
40+
$request = $context['request'] ?? null;
4541

46-
foreach ($apiOperation->getParameters() ?? [] as $parameter) {
42+
$operation = $request?->attributes->get('_api_operation') ?? $operation;
43+
foreach ($operation->getParameters() ?? [] as $parameter) {
4744
if (null === $security = $parameter->getSecurity()) {
4845
continue;
4946
}
5047

51-
$key = $this->getParameterFlattenKey($parameter->getKey(), $this->extractParameterValues($parameter, $request, $context));
52-
$apiValues = $parameter->getExtraProperties()['_api_values'] ?? [];
53-
if (!isset($apiValues[$key])) {
48+
if (($v = $parameter->getValue()) instanceof ParameterNotFound) {
5449
continue;
5550
}
56-
$value = $apiValues[$key];
5751

58-
if (!$this->resourceAccessChecker->isGranted($context['resource_class'], $security, [$key => $value])) {
52+
$securityContext = [$parameter->getKey() => $v, 'object' => $body];
53+
if (!$this->resourceAccessChecker->isGranted($context['resource_class'], $security, $securityContext)) {
5954
throw $operation instanceof GraphQlOperation ? new AccessDeniedHttpException($parameter->getSecurityMessage() ?? 'Access Denied.') : new AccessDeniedException($parameter->getSecurityMessage() ?? 'Access Denied.');
6055
}
6156
}
6257

63-
return $this->decorated->provide($operation, $uriVariables, $context);
58+
return $body;
6459
}
6560
}

src/Symfony/Bundle/Resources/config/state/provider.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,5 @@
4848
<argument type="service" id="api_platform.state_provider.parameter.inner" />
4949
<argument type="tagged_locator" tag="api_platform.parameter_provider" index-by="key" />
5050
</service>
51-
52-
<service id="api_platform.state_provider.security_parameter" class="ApiPlatform\State\Provider\SecurityParameterProvider" decorates="api_platform.state_provider.main" decoration-priority="200">
53-
<argument type="service" id="api_platform.state_provider.security_parameter.inner" />
54-
<argument type="service" id="api_platform.security.resource_access_checker" />
55-
</service>
5651
</services>
5752
</container>

src/Symfony/Bundle/Resources/config/state/security.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,10 @@
1414
<argument type="service" id="api_platform.security.resource_access_checker" />
1515
<argument>post_denormalize</argument>
1616
</service>
17+
18+
<service id="api_platform.state_provider.security_parameter" class="ApiPlatform\State\Provider\SecurityParameterProvider" decorates="api_platform.state_provider.access_checker">
19+
<argument type="service" id="api_platform.state_provider.security_parameter.inner" />
20+
<argument type="service" id="api_platform.security.resource_access_checker" />
21+
</service>
1722
</services>
1823
</container>

tests/Functional/Parameters/SecurityTests.php renamed to tests/Functional/Parameters/SecurityTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Symfony\Component\HttpFoundation\Response;
1818
use Symfony\Component\Security\Core\User\InMemoryUser;
1919

20-
class SecurityTests extends ApiTestCase
20+
class SecurityTest extends ApiTestCase
2121
{
2222
public function dataUserAuthorization(): iterable
2323
{

0 commit comments

Comments
 (0)