Skip to content

Commit

Permalink
Exclude fields from certain operations when not authenticated. (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
v16Studios authored Sep 27, 2023
1 parent 42b0a73 commit 6ec8e7e
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 3 deletions.
1 change: 1 addition & 0 deletions config/graphql.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
*/
'execution_middleware' => [
\Rebing\GraphQL\Support\ExecutionMiddleware\ValidateOperationParamsMiddleware::class,
\Enjin\Platform\Middlewares\OperationDefinitionNodeStore::class,
// AutomaticPersistedQueriesMiddleware listed even if APQ is disabled, see the docs for the `'apq'` configuration
\Rebing\GraphQL\Support\ExecutionMiddleware\AutomaticPersistedQueriesMiddleware::class,
\Rebing\GraphQL\Support\ExecutionMiddleware\AddAuthUserContextValueMiddleware::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Enjin\Platform\Enums\Global\TransactionState;
use Enjin\Platform\GraphQL\Middleware\ResolvePage;
use Enjin\Platform\GraphQL\Schemas\Primary\Traits\InPrimarySchema;
use Enjin\Platform\GraphQL\Schemas\Traits\GetsMiddleware;
use Enjin\Platform\GraphQL\Types\Pagination\ConnectionInput;
use Enjin\Platform\Interfaces\PlatformGraphQlMutation;
use Enjin\Platform\Models\Transaction;
Expand All @@ -23,7 +22,6 @@
class MarkAndListPendingTransactionsMutation extends Mutation implements PlatformGraphQlMutation
{
use InPrimarySchema;
use GetsMiddleware;

protected $middleware = [
ResolvePage::class,
Expand Down
5 changes: 5 additions & 0 deletions src/GraphQL/Schemas/Traits/GetsMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ trait GetsMiddleware
{
protected function getMiddleware(): array
{
$parentMiddleware = get_class_vars(get_parent_class());
$this->middleware = array_merge($this->middleware, $parentMiddleware['middleware']);

if ($resolverMiddleware = config('graphql.resolver_middleware')) {
$this->middleware = array_merge($this->middleware, $resolverMiddleware[class_basename(static::class)] ?? []);
$this->middleware = array_merge($this->middleware, $resolverMiddleware[class_basename(get_parent_class(static::class))] ?? []);
}

$this->middleware = array_unique($this->middleware);

return parent::getMiddleware();
}
}
13 changes: 12 additions & 1 deletion src/GraphQL/Schemas/Traits/HasAuthorizableFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@

namespace Enjin\Platform\GraphQL\Schemas\Traits;

use Enjin\Platform\Middlewares\OperationDefinitionNodeStore;

trait HasAuthorizableFields
{
public function getFields(): array
{
$fields = parent::getFields();

return collect($fields)->filter(fn ($field) => !($field['authRequired'] ?? false))->all();
if (!config('enjin-platform.auth')) {
return $fields;
}

return collect($fields)
->filter(
fn ($field) => (auth()->check() || !in_array(OperationDefinitionNodeStore::getOperationName(), $field['excludeFrom'] ?? [])) &&
!(($field['authRequired'] ?? false) && !auth()->check())
)
->all();
}
}
1 change: 1 addition & 0 deletions src/Http/Controllers/GraphQLController.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ protected function isIntrospection(Request $request, RequestParser $parser): boo
if (!$operation->query) {
return false;
}

if ($node = Parser::parse($operation->query)) {
if ('__schema' == $node->definitions->offsetGet(0)?->selectionSet?->selections?->offsetGet(0)?->name?->value) {
return true;
Expand Down
45 changes: 45 additions & 0 deletions src/Middlewares/OperationDefinitionNodeStore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Enjin\Platform\Middlewares;

use Closure;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\Parser;
use GraphQL\Type\Schema;
use Rebing\GraphQL\Support\ExecutionMiddleware\AbstractExecutionMiddleware;
use Rebing\GraphQL\Support\OperationParams;

class OperationDefinitionNodeStore extends AbstractExecutionMiddleware
{
/**
* The current request's Operation Definition Node.
*/
public static OperationDefinitionNode $operationDefinitionNode;

/**
* Handle's middleware logic.
*/
public function handle(string $schemaName, Schema $schema, OperationParams $params, $rootValue, $contextValue, Closure $next): ExecutionResult
{
$documentNode = Parser::parse($params->query);
$operationName = $params->operation;
static::$operationDefinitionNode = collect($documentNode->definitions)
->when($operationName, fn ($collection) => $collection->where('name.value', '=', $operationName))
->first();

return $next($schemaName, $schema, $params, $rootValue, $contextValue);
}

/**
* Get the current request's operation name.
*/
public static function getOperationName()
{
return static::$operationDefinitionNode
->getSelectionSet()
->selections
->offsetGet(0)
->name->value;
}
}

0 comments on commit 6ec8e7e

Please sign in to comment.