Skip to content

Commit

Permalink
fix(graphql): validate before resolver, no validate on delete
Browse files Browse the repository at this point in the history
fixes #6370
  • Loading branch information
soyuka committed May 24, 2024
1 parent 77a917f commit fea7f0a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
22 changes: 20 additions & 2 deletions features/graphql/mutation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ Feature: GraphQL mutation support
And the JSON node "data.uploadMultipleMediaObject.mediaObject.contentUrl" should be equal to "test.gif"

@!mongodb
Scenario: Mutation should run before validation
Scenario: Mutation should run after validation
When I send the following GraphQL request:
"""
mutation {
Expand All @@ -1050,4 +1050,22 @@ Feature: GraphQL mutation support
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON node "data.createActivityLog.activityLog.name" should be equal to "hi"
And the JSON node "errors[0].message" should be equal to "name: This value should not be blank."

@!mongodb
Scenario: Delete an invalid item through a mutation
When I send the following GraphQL request:
"""
mutation {
deleteActivityLog(input: {id: "/activity_logs/1"}) {
activityLog {
id
}
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON node "errors" should not exist
And the JSON node "data.deleteActivityLog.activityLog" should exist
3 changes: 2 additions & 1 deletion src/GraphQl/Resolver/Factory/ResolverFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace ApiPlatform\GraphQl\Resolver\Factory;

use ApiPlatform\GraphQl\State\Provider\NoopProvider;
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Metadata\GraphQl\Operation;
use ApiPlatform\Metadata\GraphQl\Query;
Expand Down Expand Up @@ -75,7 +76,7 @@ private function resolve(?array $source, array $args, ResolveInfo $info, ?string
$context = ['source' => $source, 'args' => $args, 'info' => $info, 'root_class' => $rootClass, 'graphql_context' => &$graphQlContext];

if (null === $operation->canValidate()) {
$operation = $operation->withValidate($operation instanceof Mutation);
$operation = $operation->withValidate($operation instanceof Mutation && !$operation instanceof DeleteMutation);
}

$body ??= $this->provider->provide($operation, [], $context);
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bundle/Resources/config/graphql.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@
<argument type="tagged_locator" tag="api_platform.parameter_provider" index-by="key" />
</service>

<!-- Validation occurs at 200, we want validation to be after we reach custom resolvers -->
<service id="api_platform.graphql.state_provider.resolver" class="ApiPlatform\GraphQl\State\Provider\ResolverProvider" decorates="api_platform.graphql.state_provider" decoration-priority="220">
<!-- Validation occurs at 200, we want validation to be over when we reach custom resolvers -->
<service id="api_platform.graphql.state_provider.resolver" class="ApiPlatform\GraphQl\State\Provider\ResolverProvider" decorates="api_platform.graphql.state_provider" decoration-priority="190">
<argument type="service" id="api_platform.graphql.state_provider.resolver.inner" />
<argument type="service" id="api_platform.graphql.resolver_locator" />
</service>
Expand Down
18 changes: 17 additions & 1 deletion tests/Fixtures/TestBundle/ApiResource/Issue6354/ActivityLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,36 @@
namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue6354;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Metadata\Operation;
use Symfony\Component\Validator\Constraints\NotBlank;

#[ApiResource(
operations: [
new Get(
provider: [self::class, 'provide']
),
],
graphQlOperations: [
new Mutation(
resolver: 'app.graphql.mutation_resolver.activity_log',
name: 'create'
),
new DeleteMutation(
name: 'delete'
),
]
)]
class ActivityLog
{
public function __construct(#[NotBlank()] public ?string $name = null)
public function __construct(public ?int $id = null, #[NotBlank()] public ?string $name = null)
{
}

public static function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
return new self(1);
}
}

0 comments on commit fea7f0a

Please sign in to comment.