Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/GraphQl/Executor.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use GraphQL\Type\Schema;
use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\DisableIntrospection;
use GraphQL\Validator\Rules\QueryComplexity;
use GraphQL\Validator\Rules\QueryDepth;

/**
* Wrapper for the GraphQL facade.
Expand All @@ -26,13 +28,19 @@
*/
final class Executor implements ExecutorInterface
{
public function __construct(private readonly bool $graphQlIntrospectionEnabled = true)
public function __construct(private readonly bool $graphQlIntrospectionEnabled = true, private readonly int $maxQueryComplexity = 500, private readonly int $maxQueryDepth = 20)
{
DocumentValidator::addRule(
new DisableIntrospection(
$this->graphQlIntrospectionEnabled ? DisableIntrospection::DISABLED : DisableIntrospection::ENABLED
)
);

$queryComplexity = new QueryComplexity($this->maxQueryComplexity);
DocumentValidator::addRule($queryComplexity);

$queryDepth = new QueryDepth($this->maxQueryDepth);
DocumentValidator::addRule($queryDepth);
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/GraphQl/Tests/ExecutorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use ApiPlatform\GraphQl\Executor;
use GraphQL\Validator\DocumentValidator;
use GraphQL\Validator\Rules\DisableIntrospection;
use GraphQL\Validator\Rules\QueryComplexity;
use GraphQL\Validator\Rules\QueryDepth;
use PHPUnit\Framework\TestCase;

/**
Expand All @@ -38,4 +40,20 @@ public function testDisableIntrospectionQuery(): void
$expected = new DisableIntrospection(DisableIntrospection::ENABLED);
$this->assertEquals($expected, DocumentValidator::getRule(DisableIntrospection::class));
}

public function testChangeValueOfMaxQueryDepth(): void
{
$executor = new Executor(true, 20);

$expected = new QueryComplexity(20);
$this->assertEquals($expected, DocumentValidator::getRule(QueryComplexity::class));
}

public function testChangeValueOfMaxQueryComplexity(): void
{
$executor = new Executor(true, maxQueryDepth: 20);

$expected = new QueryDepth(20);
$this->assertEquals($expected, DocumentValidator::getRule(QueryDepth::class));
}
}
2 changes: 1 addition & 1 deletion src/Laravel/ApiPlatformProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -1294,7 +1294,7 @@ private function registerGraphQl(Application $app): void
/** @var ConfigRepository */
$config = $app['config'];

return new Executor($config->get('api-platform.graphql.introspection.enabled') ?? false);
return new Executor($config->get('api-platform.graphql.introspection.enabled') ?? false, $config->get('api-platform.graphql.max_query_complexity'), $config->get('api-platform.graphql.max_query_depth'));
});

$app->singleton(GraphiQlController::class, function (Application $app) {
Expand Down
4 changes: 3 additions & 1 deletion src/Laravel/config/api-platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@
'graphql' => [
'enabled' => false,
'nesting_separator' => '__',
'introspection' => ['enabled' => true]
'introspection' => ['enabled' => true],
'max_query_complexity' => 500,
'max_query_depth' => 200
],

'exception_to_status' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,14 +565,17 @@ private function registerGraphQlConfiguration(ContainerBuilder $container, array
{
$enabled = $this->isConfigEnabled($container, $config['graphql']);
$graphqlIntrospectionEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['introspection']);

$graphiqlEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['graphiql']);
$graphqlPlayGroundEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['graphql_playground']);
$maxQueryDepth = (int) $config['graphql']['max_query_depth'];
$maxQueryComplexity = (int) $config['graphql']['max_query_complexity'];
if ($graphqlPlayGroundEnabled) {
trigger_deprecation('api-platform/core', '3.1', 'GraphQL Playground is deprecated and will be removed in API Platform 4.0. Only GraphiQL will be available in the future. Set api_platform.graphql.graphql_playground to false in the configuration to remove this deprecation.');
}

$container->setParameter('api_platform.graphql.enabled', $enabled);
$container->setParameter('api_platform.graphql.max_query_depth', $maxQueryDepth);
$container->setParameter('api_platform.graphql.max_query_complexity', $maxQueryComplexity);
$container->setParameter('api_platform.graphql.introspection.enabled', $graphqlIntrospectionEnabled);
$container->setParameter('api_platform.graphql.graphiql.enabled', $graphiqlEnabled);
$container->setParameter('api_platform.graphql.graphql_playground.enabled', $graphqlPlayGroundEnabled);
Expand Down
7 changes: 5 additions & 2 deletions src/Symfony/Bundle/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
namespace ApiPlatform\Symfony\Bundle\DependencyInjection;

use ApiPlatform\Doctrine\Common\Filter\OrderFilterInterface;
use ApiPlatform\Elasticsearch\State\Options;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
use ApiPlatform\Metadata\Post;
Expand Down Expand Up @@ -165,7 +164,7 @@ public function getConfigTreeBuilder(): TreeBuilder
$this->addExceptionToStatusSection($rootNode);

$this->addFormatSection($rootNode, 'formats', [
'jsonld' => ['mime_types' => ['application/ld+json']]
'jsonld' => ['mime_types' => ['application/ld+json']],
]);
$this->addFormatSection($rootNode, 'patch_formats', [
'json' => ['mime_types' => ['application/merge-patch+json']],
Expand Down Expand Up @@ -267,6 +266,10 @@ private function addGraphQlSection(ArrayNodeDefinition $rootNode): void
->arrayNode('introspection')
->canBeDisabled()
->end()
->integerNode('max_query_depth')->defaultValue(20)
->end()
->integerNode('max_query_complexity')->defaultValue(500)
->end()
->scalarNode('nesting_separator')->defaultValue('_')->info('The separator to use to filter nested fields.')->end()
->arrayNode('collection')
->addDefaultsIfNotSet()
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Bundle/Resources/config/graphql.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<services>
<service id="api_platform.graphql.executor" class="ApiPlatform\GraphQl\Executor" public="false">
<argument>%api_platform.graphql.introspection.enabled%</argument>
<argument>%api_platform.graphql.max_query_complexity%</argument>
<argument>%api_platform.graphql.max_query_depth%</argument>
</service>

<!-- Resolvers -->
Expand Down
1 change: 1 addition & 0 deletions tests/Fixtures/app/AppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ class_exists(NativePasswordHasher::class) ? 'password_hashers' : 'encoders' => [
],
'graphql' => [
'graphql_playground' => false,
'max_query_depth' => 200,
],
'use_symfony_listeners' => $useSymfonyListeners,
'defaults' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ private function runDefaultConfigTests(array $doctrineIntegrationsToLoad = ['orm
'introspection' => [
'enabled' => true,
],
'max_query_depth' => 20,
'max_query_complexity' => 500,
'nesting_separator' => '_',
'collection' => [
'pagination' => [
Expand Down
Loading