Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ Expression | Description | Scope
**request** | Refers to the current request. | Request
**token** | Refers to the token which is currently in the security token storage. | Token
**user** | Refers to the user which is currently in the security token storage. | Valid Token
**object** | Refers to the value of the field for which access is being requested. For array `object` will be each item of the array. For Relay connection `object` will be the node of each connection edges. | only available for `config.fields.*.access` with query operation type.
**object** | Refers to the value of the field for which access is being requested. For array `object` will be each item of the array. For Relay connection `object` will be the node of each connection edges. | only available for `config.fields.*.access` with query operation or mutation payload type.
**value** | Resolver value | only available in resolve context
**args** | Resolver args array | only available in resolve context
**info** | Resolver GraphQL\Type\Definition\ResolveInfo Object | only available in resolve context
Expand Down
3 changes: 2 additions & 1 deletion Resolver/Config/FieldsConfigSolution.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ private function resolveAccessAndWrapResolveCallback($expression, callable $reso

$info = $values['info'];

if ($info instanceof ResolveInfo && $info->operation->operation === 'mutation') {
// operation is mutation and is mutation field
if ($info instanceof ResolveInfo && $info->operation->operation === 'mutation' && $info->parentType === $info->schema->getMutationType()) {
$checkAccess = $this->checkAccessCallback($expression, $values);
$result = $checkAccess(null, $values) ? call_user_func_array($resolveCallback, $args) : null;
} else {
Expand Down
76 changes: 76 additions & 0 deletions Tests/Functional/Security/AccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Overblog\GraphQLBundle\Tests\Functional\Security;

use Overblog\GraphQLBundle\Tests\Functional\app\Mutation\SimpleMutationWithThunkFieldsMutation;
use Overblog\GraphQLBundle\Tests\Functional\TestCase;

class AccessTest extends TestCase
Expand All @@ -37,6 +38,15 @@ class AccessTest extends TestCase
}
}
}
EOF;

private $simpleMutationWithThunkQuery = <<<EOF
mutation M {
simpleMutationWithThunkFields(input: {inputData: %d, clientMutationId: "bac"}) {
result
clientMutationId
}
}
EOF;

public function testNotAuthenticatedUserAccessToUserName()
Expand Down Expand Up @@ -131,6 +141,72 @@ public function testUserAccessToUserIsEnabledWithExpressionLanguageEvaluationFai
$this->assertResponse($this->userIsEnabledQuery, $expected, static::USER_ADMIN);
}

public function testMutationAllowedUser()
{
$result = 123;

$expected = [
'data' => [
'simpleMutationWithThunkFields' => [
'result' => $result,
'clientMutationId' => 'bac',
],
],
];

$this->assertResponse(sprintf($this->simpleMutationWithThunkQuery, $result), $expected, static::USER_ADMIN);
$this->assertTrue(SimpleMutationWithThunkFieldsMutation::hasMutate(true));
}

public function testMutationAllowedButNoRightsToDisplayPayload()
{
$expected = [
'data' => [
'simpleMutationWithThunkFields' => [
'result' => null,
'clientMutationId' => 'bac',
],
],
'errors' => [
[
'message' => 'Access denied to this field.',
'locations' => [
[
'line' => 3,
'column' => 5,
],
],
],
],
];

$this->assertResponse(sprintf($this->simpleMutationWithThunkQuery, 321), $expected, static::USER_ADMIN);
$this->assertTrue(SimpleMutationWithThunkFieldsMutation::hasMutate(true));
}

public function testMutationNotAllowedUser()
{
$expected = [
'data' => [
'simpleMutationWithThunkFields' => null,
],
'errors' => [
[
'message' => 'Access denied to this field.',
'locations' => [
[
'line' => 2,
'column' => 3,
],
],
],
],
];

$this->assertResponse(sprintf($this->simpleMutationWithThunkQuery, 123), $expected, static::USER_RYAN);
$this->assertFalse(SimpleMutationWithThunkFieldsMutation::hasMutate(true));
}

private function expectedFailedUserRoles()
{
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,28 @@

class SimpleMutationWithThunkFieldsMutation
{
private static $hasMutate = false;

public static function hasMutate($reset = false)
{
$hasMutate = self::$hasMutate;

if ($reset) {
static::resetHasMutate();
}

return $hasMutate;
}

public static function resetHasMutate()
{
self::$hasMutate = false;
}

public function mutate($value)
{
self::$hasMutate = true;

return ['result' => $value['inputData']];
}
}
5 changes: 3 additions & 2 deletions Tests/Functional/app/config/access/config.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
imports:
- { resource: ../config.yml }
- { resource: ../connection/services.yml }
- { resource: ../mutation/services.yml }

overblog_graphql:
definitions:
schema:
query: Query
mutation: ~
query: RootQuery
mutation: RootMutation
mappings:
types:
-
Expand Down
35 changes: 34 additions & 1 deletion Tests/Functional/app/config/access/mapping/access.types.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
Query:
RootQuery:
type: object
config:
fields:
user:
type: User
resolve: '@=resolver("query")'

Mutation:
type: object
config:
fields:
Expand Down Expand Up @@ -40,3 +48,28 @@ friendConnection:
totalCount:
type: Int
resolve: '@=resolver("connection")'

#Mutation
RootMutation:
type: object
config:
fields:
simpleMutationWithThunkFields:
builder: Mutation
access: "@=hasRole('ROLE_ADMIN')"
builderConfig:
inputType: simpleMutationWithThunkFieldsInput
payloadType: simpleMutationWithThunkFieldsPayload
mutateAndGetPayload: "@=mutation('simple_mutation_with_thunk_fields', [value])"

simpleMutationWithThunkFieldsInput:
type: relay-mutation-input
config:
fields:
inputData : { type: "Int" }

simpleMutationWithThunkFieldsPayload:
type: relay-mutation-payload
config:
fields:
result: { type: "Int", access: "@=object === 123" }
7 changes: 1 addition & 6 deletions Tests/Functional/app/config/mutation/config.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
imports:
- { resource: ../config.yml }

services:
overblog_graphql.test.mutation:
class: Overblog\GraphQLBundle\Tests\Functional\app\Mutation\SimpleMutationWithThunkFieldsMutation
tags:
- { name: "overblog_graphql.mutation", alias: "simple_mutation_with_thunk_fields", method: "mutate" }
- { resource: services.yml }

overblog_graphql:
definitions:
Expand Down
5 changes: 5 additions & 0 deletions Tests/Functional/app/config/mutation/services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
overblog_graphql.test.mutation:
class: Overblog\GraphQLBundle\Tests\Functional\app\Mutation\SimpleMutationWithThunkFieldsMutation
tags:
- { name: "overblog_graphql.mutation", alias: "simple_mutation_with_thunk_fields", method: "mutate" }
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"symfony/expression-language": "^2.7|^3.0",
"symfony/options-resolver": "^2.7|^3.0",
"doctrine/doctrine-cache-bundle": "^1.2",
"webonyx/graphql-php": "^0.6.0",
"webonyx/graphql-php": "0.6.0",
"symfony/property-access": "^2.7|^3.0"
},
"suggest": {
Expand Down