From 84d82f82a91ba845e3070929c91156c769848d5c Mon Sep 17 00:00:00 2001 From: C Chan Date: Wed, 29 Aug 2018 00:37:27 -0700 Subject: [PATCH 1/3] Update authorization docs to Graphene 2.0 * Re-write some language in "Limiting Field Access" * Added code to "Queryset Filtering On Lists" section to handle queries that return nothing * fix code to Filtering ID-based node access to work based on question [here](https://stackoverflow.com/questions/51057784/django-graphene-with-relay-restricting-queries-access-based-on-id/51958088#51958088) * Rewrote Adding Login Requirements to be Django 2.0 compatible Fixed login requirements --- docs/authorization.rst | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/authorization.rst b/docs/authorization.rst index 0232cc0..bdd1c8e 100644 --- a/docs/authorization.rst +++ b/docs/authorization.rst @@ -20,7 +20,7 @@ Let's use a simple example model. Limiting Field Access --------------------- -This is easy, simply use the ``only_fields`` meta attribute. +To limit fields in a GraphQL query simply use the ``only_fields`` meta attribute. .. code:: python @@ -63,8 +63,12 @@ define a resolve method for that field and return the desired queryset. class Query(ObjectType): all_posts = DjangoFilterConnectionField(PostNode) - def resolve_all_posts(self, args, info): - return Post.objects.filter(published=True) + def resolve_all_posts(self, info): + post = Post.objects.filter(published=True) + if post is not None: + return post + else: + return None User-based Queryset Filtering ----------------------------- @@ -95,7 +99,7 @@ schema is simple. result = schema.execute(query, context_value=request) -Filtering ID-based node access +Filtering ID-based Node Access ------------------------------ In order to add authorization to id-based node access, we need to add a @@ -113,23 +117,24 @@ method to your ``DjangoObjectType``. interfaces = (relay.Node, ) @classmethod - def get_node(cls, id, context, info): + def get_node(cls, id, info): try: - post = cls._meta.model.objects.get(id=id) + post = cls._meta.model.objects.get(id=id, owner__user = info.context.user) except cls._meta.model.DoesNotExist: return None - if post.published or context.user == post.owner: + if post.published or info.context.user == post.owner: return post return None -Adding login required +Adding Login Required --------------------- -If you want to use the standard Django LoginRequiredMixin_ you can create your own view, which includes the ``LoginRequiredMixin`` and subclasses the ``GraphQLView``: +To restrict users from accessing the GraphQL API page the standard Django LoginRequiredMixin_ can be used to create your own standard Django Class Based View, which includes the ``LoginRequiredMixin`` and subclasses the ``GraphQLView``.: .. code:: python - + #views.py + from django.contrib.auth.mixins import LoginRequiredMixin from graphene_django.views import GraphQLView @@ -137,7 +142,9 @@ If you want to use the standard Django LoginRequiredMixin_ you can create your o class PrivateGraphQLView(LoginRequiredMixin, GraphQLView): pass -After this, you can use the new ``PrivateGraphQLView`` in ``urls.py``: +After this, you can use the new ``PrivateGraphQLView`` in the project's URL Configuration file ``url.py``: + +For Django 1.9 and below: .. code:: python @@ -145,5 +152,14 @@ After this, you can use the new ``PrivateGraphQLView`` in ``urls.py``: # some other urls url(r'^graphql', PrivateGraphQLView.as_view(graphiql=True, schema=schema)), ] + +For Django 2.0 and above: + +.. code:: python + + urlpatterns = [ + # some other urls + path('graphql', PrivateGraphQLView.as_view(graphiql=True, schema=schema)), + ] .. _LoginRequiredMixin: https://docs.djangoproject.com/en/1.10/topics/auth/default/#the-loginrequired-mixin From 446013c75232bb4e9aee91d849516f48cb64d6a2 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 5 Sep 2018 13:21:39 +0200 Subject: [PATCH 2/3] Update authorization.rst --- docs/authorization.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/authorization.rst b/docs/authorization.rst index bdd1c8e..aa40656 100644 --- a/docs/authorization.rst +++ b/docs/authorization.rst @@ -64,11 +64,8 @@ define a resolve method for that field and return the desired queryset. all_posts = DjangoFilterConnectionField(PostNode) def resolve_all_posts(self, info): - post = Post.objects.filter(published=True) - if post is not None: - return post - else: - return None + return Post.objects.filter(published=True) + User-based Queryset Filtering ----------------------------- From 2ccd483ffc34c22e3bb6fcf2027656711894a847 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 5 Sep 2018 13:22:54 +0200 Subject: [PATCH 3/3] Update authorization.rst --- docs/authorization.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/authorization.rst b/docs/authorization.rst index aa40656..7a08481 100644 --- a/docs/authorization.rst +++ b/docs/authorization.rst @@ -116,7 +116,7 @@ method to your ``DjangoObjectType``. @classmethod def get_node(cls, id, info): try: - post = cls._meta.model.objects.get(id=id, owner__user = info.context.user) + post = cls._meta.model.objects.get(id=id) except cls._meta.model.DoesNotExist: return None @@ -124,6 +124,7 @@ method to your ``DjangoObjectType``. return post return None + Adding Login Required ---------------------