Skip to content

Commit

Permalink
Add tests for privacy context.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Schekotov committed Mar 25, 2021
1 parent 4cab8db commit 468e593
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 20 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ CHANGELOG
[Next release](https://github.com/rebing/graphql-laravel/compare/6.3.0...master)
--------------

## Breaking changes
- Signtature of `\Rebing\GraphQL\Support\Privacy::validate` changed, now it accepts both query/mutation arguments and the query/mutation context.
Update your existing privacy policies this way:
```diff
-public function validate(array $queryArgs): bool
+public function validate(array $queryArgs, $queryContext = null): bool
```

### Added
- Ability to pass query/mutation context to the field privacy handler (both closure and class) [\#727 / torunar](https://github.com/rebing/graphql-laravel/pull/727)

2021-03-12, 6.3.0
-----------------

Expand Down Expand Up @@ -39,7 +50,7 @@ Same as 6.1.0-rc1!
Be sure to read up on breaking changes in graphql-php => https://github.com/webonyx/graphql-php/releases/tag/v14.0.0
- Remove support for Laravel < 6.0 [\#651 / mfn](https://github.com/rebing/graphql-laravel/pull/651)
This also bumps the minimum required version to PHP 7.2

### Added
- Support for Laravel 8 [\#672 / mfn](https://github.com/rebing/graphql-laravel/pull/672)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ use Rebing\GraphQL\Support\Privacy;

class MePrivacy extends Privacy
{
public function validate(array $queryArgs, $queryContext): bool
public function validate(array $queryArgs, $queryContext = null): bool
{
return $args['id'] == Auth::id();
}
Expand Down
4 changes: 2 additions & 2 deletions example/Privacy/MePrivacy.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

class MePrivacy extends Privacy
{
public function validate(array $args): bool
public function validate(array $queryArgs, $queryContext = null): bool
{
return $args['id'] == Auth::id();
return $queryArgs['id'] == Auth::id();
}
}
11 changes: 8 additions & 3 deletions src/Support/Privacy.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ abstract class Privacy
{
public function fire(): bool
{
return $this->validate(func_get_args()[0]);
$queryArgs = func_get_arg(0);
$queryContext = func_get_arg(1);

return $this->validate($queryArgs, $queryContext);
}

/**
* @param array $queryArgs Arguments given with the query/mutation
* @param array $queryArgs Arguments given with the query/mutation
* @param mixed $queryContext Context of the query/mutation
*
* @return bool Return `true` to allow access to the field in question,
* `false otherwise
*/
abstract public function validate(array $queryArgs): bool;
abstract public function validate(array $queryArgs, $queryContext = null): bool;
}
1 change: 1 addition & 0 deletions src/Support/SelectFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ protected static function validateField(FieldDefinition $fieldObject, array $que

// If Privacy class given
case is_string($privacyClass):
/** @var \Rebing\GraphQL\Support\Privacy $instance */
$instance = app($privacyClass);
if (false === call_user_func([$instance, 'fire'], $queryArgs, $ctx)) {
$selectable = null;
Expand Down
18 changes: 18 additions & 0 deletions tests/Database/SelectFields/ValidateFieldTests/PostType.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ public function fields(): array
'type' => Type::string(),
'privacy' => true,
],
'title_privacy_closure_query_context' => [
'alias' => 'title',
'type' => Type::string(),
'privacy' => static function (array $queryArgs, $queryContext): bool {
$expectedQueryContext = [
'arg_from_context_true' => true,
'arg_from_context_false' => false,
];
Assert::assertSame($expectedQueryContext, $queryContext);

return true;
},
],
'title_privacy_class_query_context' => [
'alias' => 'title',
'type' => Type::string(),
'privacy' => PrivacyQueryContext::class,
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
class PrivacyAllowed extends Privacy
{
/**
* @param array $queryArgs Arguments given with the query/mutation
* @return bool Return `true` to allow access to the field in question,
* `false otherwise
* @inheritDoc
*/
public function validate(array $queryArgs): bool
public function validate(array $queryArgs, $queryContext = null): bool
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
class PrivacyArgs extends Privacy
{
/**
* @param array $queryArgs Arguments given with the query/mutation
* @return bool Return `true` to allow access to the field in question,
* `false otherwise
* @inheritDoc
*/
public function validate(array $queryArgs): bool
public function validate(array $queryArgs, $queryContext = null): bool
{
$expectedQueryArgs = [
'arg_from_query' => true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@
class PrivacyDenied extends Privacy
{
/**
* @param array $queryArgs Arguments given with the query/mutation
* @return bool Return `true` to allow access to the field in question,
* `false otherwise
* @inheritDoc
*/
public function validate(array $queryArgs): bool
public function validate(array $queryArgs, $queryContext = null): bool
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Rebing\GraphQL\Tests\Database\SelectFields\ValidateFieldTests;

use PHPUnit\Framework\Assert;
use Rebing\GraphQL\Support\Privacy;

class PrivacyQueryContext extends Privacy
{
/**
* @inheritDoc
*/
public function validate(array $queryArgs, $queryContext = null): bool
{
$expectedQueryContext = [
'arg_from_context_true' => true,
'arg_from_context_false' => false,
];
Assert::assertSame($expectedQueryContext, $queryContext);

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -526,4 +526,103 @@ protected function getEnvironmentSetUp($app)
PostType::class,
]);
}

/**
* Note: actual assertion happens in \Rebing\GraphQL\Tests\Database\SelectFields\ValidateFieldTests\PostType::fields
* within the closure for the field `title_privacy_closure_context`.
*/
public function testPrivacyClosureReceivesContext(): void
{
factory(Post::class)
->create([
'title' => 'post title',
]);

$query = <<<'GRAQPHQL'
{
validateFields {
title_privacy_closure_query_context
}
}
GRAQPHQL;

$this->sqlCounterReset();

$options = [
'opts' => [
'context' => [
'arg_from_context_true' => true,
'arg_from_context_false' => false,
]
]
];

$result = $this->graphql($query, $options);

$this->assertSqlQueries(
<<<'SQL'
select "posts"."title", "posts"."id" from "posts";
SQL
);

$expectedResult = [
'data' => [
'validateFields' => [
[
'title_privacy_closure_query_context' => 'post title',
],
],
],
];
$this->assertEquals($expectedResult, $result);
}

/**
* Note: actual assertion happens in \Rebing\GraphQL\Tests\Database\SelectFields\ValidateFieldTests\PrivacyQueryContext::validate.
*/
public function testPrivacyClassReceivesQueryContext(): void
{
factory(Post::class)
->create([
'title' => 'post title',
]);

$query = <<<'GRAQPHQL'
{
validateFields {
title_privacy_class_query_context
}
}
GRAQPHQL;

$this->sqlCounterReset();

$options = [
'opts' => [
'context' => [
'arg_from_context_true' => true,
'arg_from_context_false' => false,
]
]
];

$result = $this->graphql($query, $options);

$this->assertSqlQueries(
<<<'SQL'
select "posts"."title", "posts"."id" from "posts";
SQL
);

$expectedResult = [
'data' => [
'validateFields' => [
[
'title_privacy_class_query_context' => 'post title',
],
],
],
];
$this->assertEquals($expectedResult, $result);
}
}
5 changes: 4 additions & 1 deletion tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,17 @@ protected function runCommand(Command $command, array $arguments = [], array $in
* Supports the following options:
* - `expectErrors` (default: false): if no errors are expected but present, let's the test fail
* - `variables` (default: null): GraphQL variables for the query
* - `opts` (default: []): GraphQL options for the query (context, schema, operationName, rootValue)
*
* @return array GraphQL result
*/
protected function graphql(string $query, array $options = []): array
{
$expectErrors = $options['expectErrors'] ?? false;
$variables = $options['variables'] ?? null;
$opts = $options['opts'] ?? [];

$result = GraphQL::query($query, $variables);
$result = GraphQL::query($query, $variables, $opts);

$assertMessage = null;

Expand Down

0 comments on commit 468e593

Please sign in to comment.