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

inject_user() and graphql views. #161

Open
DownGoat opened this issue May 15, 2019 · 3 comments
Open

inject_user() and graphql views. #161

DownGoat opened this issue May 15, 2019 · 3 comments

Comments

@DownGoat
Copy link

Hello, I'm looking for a way to use inject_user() on a class based GraphQL view, or some other way to access the user_id. I have the following PoC for GraphQL, and I can inject a user object into the **args parameter, but there does not seem to be any easily exposed functions in the library that allows me to quickly pull out a claim without parsing stuff myself.

class AuthorizationMiddleware(object):
    def resolve(next, root, info, **args):
        return next(root, info, **{'user': True})


class SanixGraphql(GraphQLView):
    schema = schema
    graphiql = True
    decorators = [protected(), inject_user()]
    middleware = [AuthorizationMiddleware]

Is there anything I can use to easily extract the user_id from the token inside the AuthorizationMiddleware.resolve`method.

@ahopkins
Copy link
Owner

You are right, you could get it by decoding the token yourself.

But, you also should be able to get it with inject_user, which calls:

f(request, user=user, *args, **kwargs)

Where, f is the view handler.

I am not 100% sure about sanic-graphql since it has been a while since I used it. I am not sure (1) what the view handler being wrapped it, and (2) how the middleware work.

I can try and dig in and take a look.

@ahopkins
Copy link
Owner

So the place that inject_user is sending the user is the dispatch_request method.

from sanic import Sanic
from sanic_jwt import Initialize
from sanic_graphql import GraphQLView
import graphene


user = {"user_id": 1, "username": "foobar"}
app = Sanic(__name__)
sanicjwt = Initialize(
    app, authenticate=lambda x: user, retrieve_user=lambda x, y: user
)


class Query(graphene.ObjectType):
    hello = graphene.String(argument=graphene.String(default_value="stranger"))

    def resolve_hello(self, info, argument):
        return "Hello " + argument


schema = graphene.Schema(query=Query)


class AuthorizationMiddleware:
    def resolve(next, root, info, **args):
        print("AuthorizationMiddleware.resolve:\n=============")
        print(f"\troot: {root}")
        print(f"\tinfo: {info}")
        print(f"\targs: {args}")
        return next(root, info, **args)


class SanixGraphql(GraphQLView):
    schema = schema
    graphiql = True
    decorators = [sanicjwt.protected(), sanicjwt.inject_user()]
    middleware = [AuthorizationMiddleware]

    async def dispatch_request(self, *args, **kwargs):
        print("SanixGraphql.dispatch_request:\n=============")
        print(f"\targs: {args}")
        print(f"\tkwargs: {kwargs}")
        return await super().dispatch_request(*args, **kwargs)


app.add_route(SanixGraphql.as_view(), "/graphql")

if __name__ == "__main__":
    app.run(debug=True)

This is the barebones test that I was running just to see what is going on.

[2019-05-16 00:17:22 +0300] [16634] [INFO] Starting worker [16634]
SanixGraphql.dispatch_request:
=============
	args: (<Request: POST /graphql>,)
	kwargs: {'user': {'user_id': 1, 'username': 'foobar'}}
AuthorizationMiddleware.resolve:
=============
	root: None
	info: <graphql.execution.base.ResolveInfo object at 0x7fa3491d20c8>
	args: {'argument': 'stranger'}
[2019-05-16 00:18:30 +0300] - (sanic.access)[INFO][127.0.0.1:53444]: POST http://localhost:8000/graphql  200 35

As you can see, dispatch_request gets called before the middleware. The problem that I see is that the middleware seemed to be getting called DEEP inside the graphql and graphene APIs. I am not exactly sure where or how to modify them to pass additional args or kwargs.

What is is you are trying to achieve so I can help understand what the goal is.

@DownGoat
Copy link
Author

Basically I want to have easy access to the user_id which is in the token, inside GraphQL resolvers without having to call some function myself in every resolver.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants