laravel-graphql icon indicating copy to clipboard operation
laravel-graphql copied to clipboard

middleware_schema doesn't work

Open monsterdream opened this issue 7 years ago • 7 comments

Hi, I think that middleware_schema parameter in config doesn't work. I created another schema "secret", to this point everything is working fine but code below doesn't. It seems that even if I will query secret schema, "default" middleware is take charge here instead of "secret" middlewares.

    'middleware_schema' => [
        'default' => ['auth'],
	'secret' => ['api', 'auth:users_api']
    ],

Basically middleware will be used defined here:

'schema' => 'default',

Instead from 'middleware_schema'.

monsterdream avatar Mar 01 '18 15:03 monsterdream

Tried to reproduce your issue, but it looks fine on my end.

Can you create an example project where this happens?

kevinvdburgt avatar Mar 04 '18 20:03 kevinvdburgt

On Laravel 5.6, you need to add graphql to your middleware groups.

App\Http\Kernel.php Add the following to your $middlewareGroups array:

'graphql' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, ],

Then in your graphql.php config file, update your middleware to look like the following:

'middleware' => [ 'graphql', 'auth' ],

Change any of the middleware_schema to whatever you would like.

Bowens20832 avatar Mar 15 '18 22:03 Bowens20832

middleware_schema not works on Lumen 5.6

obihuang avatar Apr 25 '18 09:04 obihuang

@Bowens20832 Lumen does not have middlewareGroups

obihuang avatar Apr 25 '18 09:04 obihuang

middleware defined in routeMiddleware can't be used in middleware_schema

obihuang avatar May 02 '18 09:05 obihuang

@kevinvdburgt Could you take a look at this problem?

obihuang avatar May 09 '18 06:05 obihuang

I think i got the middleware_schema implementaion to work in Lumen. For everyone who is interested; I copied the GraphQLController into my Http/Controllers folder and tweaked it a bit. Now it looks like this:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class GraphQLController extends Controller
{
    protected $schema;

    public function __construct(Request $request)
    {
        $route = $request->route();

        // Prevent schema middlewares to be applied to graphiql routes
        $routeName = is_object($route) ? $route->getName() : null;
        if (!is_null($routeName) && preg_match('/^graphql\.graphiql/', $routeName)) {
            return;
        }

        $defaultSchema = config('graphql.schema');
        if (is_array($route)) {
            $this->schema = array_get($route, '2.graphql_schema', $defaultSchema);
        } elseif (is_object($route)) {
            $this->schema = $route->parameter('graphql_schema', $defaultSchema);
        } else {
            $this->schema = $defaultSchema;
        }

        $middleware = config('graphql.middleware_schema.' . $this->schema, null);

        if ($middleware) {
            if (is_array($middleware)) {
                foreach ($middleware as $entry) {
                    $this->middleware($entry);
                }
            } else {
                $this->middleware($middleware);
            }
        }
    }

    public function query(Request $request, $schema = null)
    {
        $isBatch = !$request->has('query');
        $inputs = $request->all();

        if (!$schema) {
            $schema = $this->schema;
        }

        if (!$isBatch) {
            $data = $this->executeQuery($schema, $inputs);
        } else {
            $data = [];
            foreach ($inputs as $input) {
                $data[] = $this->executeQuery($schema, $input);
            }
        }

        $headers = config('graphql.headers', []);
        $options = config('graphql.json_encoding_options', 0);

        $errors = !$isBatch ? array_get($data, 'errors', []) : [];
        $authorized = array_reduce($errors, function ($authorized, $error) {
            return !$authorized || array_get($error, 'message') === 'Unauthorized' ? false : true;
        }, true);
        if (!$authorized) {
            return response()->json($data, 403, $headers, $options);
        }

        return response()->json($data, 200, $headers, $options);
    }

    public function graphiql(Request $request, $schema = null)
    {
        $view = config('graphql.graphiql.view', 'graphql::graphiql');
        return view($view, [
            'schema' => $schema,
        ]);
    }

    protected function executeQuery($schema, $input)
    {
        $variablesInputName = config('graphql.variables_input_name', 'variables');
        $query = array_get($input, 'query');
        $variables = array_get($input, $variablesInputName);
        if (is_string($variables)) {
            $variables = json_decode($variables, true);
        }
        $operationName = array_get($input, 'operationName');
        $context = $this->queryContext($query, $variables, $schema);
        return app('graphql')->query($query, $variables, [
            'context' => $context,
            'schema' => $schema,
            'operationName' => $operationName
        ]);
    }

    protected function queryContext($query, $variables, $schema)
    {
        try {
            return app('auth')->user();
        } catch (\Exception $e) {
            return null;
        }
    }
}

The crucial parts are:

  1. GraphQLController extends Controller or BaseController
  2. determine current schema in __construct
  3. go through all middleware entries if it es an array in end of __construct
  4. use the right schema in the query method
if (!$schema) {
    $schema = $this->schema;
}

Also you need the following config:

'controllers' => \App\Http\Controllers\GraphQLController::class.'@query',

It's really sad that this package is kind of dead. If that would not be the case, I would be happy to create a pull request.

Artem-Schander avatar Nov 06 '18 18:11 Artem-Schander