diff --git a/src/Bridge/Symfony/Bundle/Resources/config/graphql.xml b/src/Bridge/Symfony/Bundle/Resources/config/graphql.xml
index 701a7ac9878..07617218bf5 100644
--- a/src/Bridge/Symfony/Bundle/Resources/config/graphql.xml
+++ b/src/Bridge/Symfony/Bundle/Resources/config/graphql.xml
@@ -53,12 +53,12 @@
-
+
-
+
diff --git a/src/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php b/src/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php
index 18a1e2ad18a..d6ab052d085 100644
--- a/src/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php
+++ b/src/GraphQl/Resolver/Stage/SecurityPostDenormalizeStage.php
@@ -30,7 +30,7 @@ final class SecurityPostDenormalizeStage implements SecurityPostDenormalizeStage
private $resourceMetadataFactory;
private $resourceAccessChecker;
- public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ResourceAccessCheckerInterface $resourceAccessChecker)
+ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker)
{
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->resourceAccessChecker = $resourceAccessChecker;
@@ -44,6 +44,7 @@ public function __invoke(string $resourceClass, string $operationName, array $co
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security_post_denormalize', null, true);
+
if (null === $isGranted) {
// Backward compatibility
$isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'access_control', null, true);
@@ -52,6 +53,10 @@ public function __invoke(string $resourceClass, string $operationName, array $co
}
}
+ if (null !== $isGranted && null === $this->resourceAccessChecker) {
+ throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".');
+ }
+
if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) {
return;
}
diff --git a/src/GraphQl/Resolver/Stage/SecurityStage.php b/src/GraphQl/Resolver/Stage/SecurityStage.php
index 36fa2e37619..b3afa035618 100644
--- a/src/GraphQl/Resolver/Stage/SecurityStage.php
+++ b/src/GraphQl/Resolver/Stage/SecurityStage.php
@@ -30,7 +30,7 @@ final class SecurityStage implements SecurityStageInterface
private $resourceMetadataFactory;
private $resourceAccessChecker;
- public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ResourceAccessCheckerInterface $resourceAccessChecker)
+ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, ?ResourceAccessCheckerInterface $resourceAccessChecker)
{
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->resourceAccessChecker = $resourceAccessChecker;
@@ -44,6 +44,11 @@ public function __invoke(string $resourceClass, string $operationName, array $co
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
$isGranted = $resourceMetadata->getGraphqlAttribute($operationName, 'security', null, true);
+
+ if (null !== $isGranted && null === $this->resourceAccessChecker) {
+ throw new \LogicException('Cannot check security expression when SecurityBundle is not installed. Try running "composer require symfony/security-bundle".');
+ }
+
if (null === $isGranted || $this->resourceAccessChecker->isGranted($resourceClass, (string) $isGranted, $context['extra_variables'])) {
return;
}
diff --git a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php
index 21f11dda5ce..301963c836a 100644
--- a/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php
+++ b/tests/GraphQl/Resolver/Stage/SecurityPostDenormalizeStageTest.php
@@ -115,4 +115,34 @@ public function testNotGranted(): void
'extra_variables' => $extraVariables,
]);
}
+
+ public function testNoSecurityBundleInstalled(): void
+ {
+ $this->securityPostDenormalizeStage = new SecurityPostDenormalizeStage($this->resourceMetadataFactoryProphecy->reveal(), null);
+
+ $operationName = 'item_query';
+ $resourceClass = 'myResource';
+ $isGranted = 'not_granted';
+ $resourceMetadata = (new ResourceMetadata())->withGraphql([
+ $operationName => ['security_post_denormalize' => $isGranted],
+ ]);
+ $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata);
+
+ $this->expectException(\LogicException::class);
+
+ ($this->securityPostDenormalizeStage)($resourceClass, 'item_query', []);
+ }
+
+ public function testNoSecurityBundleInstalledNoExpression(): void
+ {
+ $this->securityPostDenormalizeStage = new SecurityPostDenormalizeStage($this->resourceMetadataFactoryProphecy->reveal(), null);
+
+ $resourceClass = 'myResource';
+ $resourceMetadata = new ResourceMetadata();
+ $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata);
+
+ $this->resourceAccessCheckerProphecy->isGranted(Argument::any())->shouldNotBeCalled();
+
+ ($this->securityPostDenormalizeStage)($resourceClass, 'item_query', []);
+ }
}
diff --git a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php
index 4b18a7345fd..a49207679a2 100644
--- a/tests/GraphQl/Resolver/Stage/SecurityStageTest.php
+++ b/tests/GraphQl/Resolver/Stage/SecurityStageTest.php
@@ -96,4 +96,34 @@ public function testNotGranted(): void
'extra_variables' => $extraVariables,
]);
}
+
+ public function testNoSecurityBundleInstalled(): void
+ {
+ $this->securityStage = new SecurityStage($this->resourceMetadataFactoryProphecy->reveal(), null);
+
+ $operationName = 'item_query';
+ $resourceClass = 'myResource';
+ $isGranted = 'not_granted';
+ $resourceMetadata = (new ResourceMetadata())->withGraphql([
+ $operationName => ['security' => $isGranted],
+ ]);
+ $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata);
+
+ $this->expectException(\LogicException::class);
+
+ ($this->securityStage)($resourceClass, 'item_query', []);
+ }
+
+ public function testNoSecurityBundleInstalledNoExpression(): void
+ {
+ $this->securityStage = new SecurityStage($this->resourceMetadataFactoryProphecy->reveal(), null);
+
+ $resourceClass = 'myResource';
+ $resourceMetadata = new ResourceMetadata();
+ $this->resourceMetadataFactoryProphecy->create($resourceClass)->willReturn($resourceMetadata);
+
+ $this->resourceAccessCheckerProphecy->isGranted(Argument::any())->shouldNotBeCalled();
+
+ ($this->securityStage)($resourceClass, 'item_query', []);
+ }
}