Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom authorization message #578

Merged
merged 1 commit into from
Jan 19, 2020
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ CHANGELOG
[Next release](https://github.com/rebing/graphql-laravel/compare/4.0.0...master)
--------------

### Added
- Add support for custom authorization message

2019-12-09, 4.0.0
-----------------
### Added
Expand Down
27 changes: 27 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,33 @@ class UsersQuery extends Query
}
```

You can also provide a custom error message when the authorization fails (defaults to Unauthorized):

```php
use Auth;
use Closure;
use GraphQL\Type\Definition\ResolveInfo;

class UsersQuery extends Query
{
public function authorize($root, array $args, $ctx, ResolveInfo $resolveInfo = null, Closure $getSelectFields = null): bool
{
if (isset($args['id'])) {
return Auth::id() == $args['id'];
}

return true;
}

public function getAuthorizationMessage(): string
{
return 'You are not authorized to perform this action';
}

// ...
}
```

### Privacy

You can set custom privacy attributes for every Type's Field. If a field is not
Expand Down
7 changes: 6 additions & 1 deletion src/Support/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ protected function getResolver(): ?Closure

// Authorize
if (true != call_user_func_array($authorize, $arguments)) {
throw new AuthorizationError('Unauthorized');
throw new AuthorizationError($this->getAuthorizationMessage());
}

$method = new ReflectionMethod($this, 'resolve');
Expand Down Expand Up @@ -290,6 +290,11 @@ public function getAttributes(): array
return $attributes;
}

public function getAuthorizationMessage(): string
{
return 'Unauthorized';
}

/**
* Convert the Fluent instance to an array.
*
Expand Down
53 changes: 53 additions & 0 deletions tests/Support/Objects/ExamplesAuthorizeMessageQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Rebing\GraphQL\Tests\Support\Objects;

use Closure;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;

class ExamplesAuthorizeMessageQuery extends Query
{
protected $attributes = [
'name' => 'Examples authorize query',
];

public function authorize($root, array $args, $ctx, ResolveInfo $resolveInfo = null, Closure $getSelectFields = null): bool
{
return false;
}

public function getAuthorizationMessage(): string
{
return 'You are not authorized to perform this action';
}

public function type(): Type
{
return Type::listOf(GraphQL::type('Example'));
}

public function args(): array
{
return [
'index' => ['name' => 'index', 'type' => Type::int()],
];
}

public function resolve($root, $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
$data = include __DIR__.'/data.php';

if (isset($args['index'])) {
return [
$data[$args['index']],
];
}

return $data;
}
}
8 changes: 8 additions & 0 deletions tests/Support/Objects/queries.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@
}
',

'examplesWithAuthorizeMessage' => '
query QueryExamplesAuthorizeMessage {
examplesAuthorizeMessage {
test
}
}
',

'examplesWithError' => '
query QueryExamplesWithError {
examplesQueryNotFound {
Expand Down
2 changes: 2 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Rebing\GraphQL\GraphQLServiceProvider;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Tests\Support\Objects\ExampleFilterInputType;
use Rebing\GraphQL\Tests\Support\Objects\ExamplesAuthorizeMessageQuery;
use Rebing\GraphQL\Tests\Support\Objects\ExamplesAuthorizeQuery;
use Rebing\GraphQL\Tests\Support\Objects\ExamplesConfigAliasQuery;
use Rebing\GraphQL\Tests\Support\Objects\ExamplesFilteredQuery;
Expand Down Expand Up @@ -53,6 +54,7 @@ protected function getEnvironmentSetUp($app)
'query' => [
'examples' => ExamplesQuery::class,
'examplesAuthorize' => ExamplesAuthorizeQuery::class,
'examplesAuthorizeMessage' => ExamplesAuthorizeMessageQuery::class,
'examplesPagination' => ExamplesPaginationQuery::class,
'examplesFiltered' => ExamplesFilteredQuery::class,
'examplesConfigAlias' => ExamplesConfigAliasQuery::class,
Expand Down
18 changes: 18 additions & 0 deletions tests/Unit/EndpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ public function testGetUnauthorized(): void
$this->assertNull($content['data']['examplesAuthorize']);
}

/**
* Test get with unauthorized query and custom error message.
*/
public function testGetUnauthorizedWithCustomError(): void
{
$response = $this->call('GET', '/graphql', [
'query' => $this->queries['examplesWithAuthorizeMessage'],
]);

$this->assertEquals($response->getStatusCode(), 200);

$content = $response->getData(true);
$this->assertArrayHasKey('data', $content);
$this->assertArrayHasKey('errors', $content);
$this->assertEquals($content['errors'][0]['message'], 'You are not authorized to perform this action');
$this->assertNull($content['data']['examplesAuthorizeMessage']);
}

/**
* Test support batched queries.
*/
Expand Down
12 changes: 12 additions & 0 deletions tests/Unit/GraphQLQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ public function testQueryAndReturnResultWithAuthorize(): void
$this->assertEquals('Unauthorized', $result['errors'][0]['message']);
}

/**
* Test query with authorize.
*/
public function testQueryAndReturnResultWithCustomAuthorizeMessage(): void
{
$result = $this->graphql($this->queries['examplesWithAuthorizeMessage'], [
'expectErrors' => true,
]);
$this->assertNull($result['data']['examplesAuthorizeMessage']);
$this->assertEquals('You are not authorized to perform this action', $result['errors'][0]['message']);
}

/**
* Test query with schema.
*/
Expand Down