diff --git a/src/Resolver/AccessResolver.php b/src/Resolver/AccessResolver.php index 3ce0de708..7eb7d999c 100644 --- a/src/Resolver/AccessResolver.php +++ b/src/Resolver/AccessResolver.php @@ -7,6 +7,8 @@ use GraphQL\Executor\Promise\Adapter\SyncPromise; use GraphQL\Executor\Promise\Promise; use GraphQL\Executor\Promise\PromiseAdapter; +use GraphQL\Type\Definition\ListOfType; +use GraphQL\Type\Definition\ResolveInfo; use Overblog\GraphQLBundle\Error\UserError; use Overblog\GraphQLBundle\Error\UserWarning; use Overblog\GraphQLBundle\Relay\Connection\Output\Connection; @@ -59,7 +61,9 @@ function ($result) use ($accessChecker, $resolveArgs) { private function processFilter($result, $accessChecker, $resolveArgs) { - if (\is_array($result)) { + /** @var ResolveInfo $resolveInfo */ + $resolveInfo = $resolveArgs[3]; + if (\is_array($result) && $resolveInfo->returnType instanceof ListOfType) { $result = \array_map( function ($object) use ($accessChecker, $resolveArgs) { return $this->hasAccess($accessChecker, $object, $resolveArgs) ? $object : null; diff --git a/tests/Functional/App/config/access/mapping/access.types.yml b/tests/Functional/App/config/access/mapping/access.types.yml index 7836bbf68..5be91d1c2 100644 --- a/tests/Functional/App/config/access/mapping/access.types.yml +++ b/tests/Functional/App/config/access/mapping/access.types.yml @@ -6,6 +6,10 @@ RootQuery: user: type: User resolve: '@=resolver("query")' + youShallNotSeeThisUnauthenticated: + type: SecureField + access: '@=isFullyAuthenticated()' + resolve: '@=[]' Mutation: type: object @@ -48,6 +52,17 @@ User: interfaces: [Human] isTypeOf: true +SecureField: + type: object + config: + fields: + secretValue: + type: String! + resolve: 'top secret' + youAreAuthenticated: + type: Boolean! + resolve: '@=isFullyAuthenticated()' + friendConnection: type: relay-connection config: diff --git a/tests/Functional/Security/AccessTest.php b/tests/Functional/Security/AccessTest.php index 27d820f26..385a5d07a 100644 --- a/tests/Functional/Security/AccessTest.php +++ b/tests/Functional/Security/AccessTest.php @@ -91,6 +91,41 @@ public function testNotAuthenticatedUserAccessToUserName(): void $this->assertResponse($this->userNameQuery, $expected, static::ANONYMOUS_USER, 'access'); } + public function testNonAuthenticatedUserAccessSecuredFieldWhichInitiallyResolvesToArray(): void + { + $expected = [ + 'data' => [ + 'youShallNotSeeThisUnauthenticated' => null, + ], + 'extensions' => [ + 'warnings' => [ + [ + 'message' => 'Access denied to this field.', + 'locations' => [ + [ + 'line' => 2, + 'column' => 3, + ], + ], + 'path' => ['youShallNotSeeThisUnauthenticated'], + 'category' => 'user', + ], + ], + ], + ]; + + $query = <<<'EOF' +{ + youShallNotSeeThisUnauthenticated { + secretValue + youAreAuthenticated + } +} +EOF; + + $this->assertResponse($query, $expected, static::ANONYMOUS_USER, 'access'); + } + public function testFullyAuthenticatedUserAccessToUserName(): void { $expected = [