Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions docs/authorization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,98 @@ After this, you can use the new ``PrivateGraphQLView`` in ``urls.py``:
]

.. _LoginRequiredMixin: https://docs.djangoproject.com/en/1.10/topics/auth/default/#the-loginrequired-mixin

Adding permissions to Nodes
---------------------------
If you want to user the auth django permissions to access a node, we need to inheritance
from ``AuthNodeMixin`` and define a required permissions in the node. This will return
a ``PermissionDenied`` is the user does not have the required permissions.

.. code:: python

from graphene_django.types import DjangoObjectType
from graphene_django.auth.mixins import AuthNodeMixin
from .models import Post

class PostNode(AuthNodeMixin, DjangoObjectType):
_permission = 'app.add_post'

class Meta:
model = Post
only_fields = ('title', 'content')
interfaces = (relay.Node, )

We can set multiple required permissions like this:

.. code:: python

from graphene_django.types import DjangoObjectType
from graphene_django.auth.mixins import AuthNodeMixin
from .models import Post

class PostNode(AuthNodeMixin, DjangoObjectType):
_permission = ('app.add_post', 'app.delete_post',)

class Meta:
model = Post
only_fields = ('title', 'content')
interfaces = (relay.Node, )

Adding permissions to Mutations
---------------------------
If you want to user the auth django permissions to execute a mutation, we need to inheritance
from ``AuthMutationMixin`` and define a required permissions in the node. This will return
a ``PermissionDenied`` is the user does not have the required permissions.

.. code:: python

class CreatePet(AuthMutationMixin, graphene.Mutation):
_permission = 'app.create_pet'
pet = graphene.Field(PetNode)

class Input:
name = graphene.String(required=True)

@classmethod
def mutate(cls, root, input, context, info):
# Auth Required Virification
if cls.has_permision(context) is not True:
return cls.has_permision(context)
# End Auth
pet_name = input.get('name')
pet = Pet.objects.create(name=pet_name)
return CreatePet(pet=pet)

We can set multiple required permissions like this:

.. code:: python

class CreatePet(AuthMutationMixin, graphene.Mutation):
_permission = ('app.add_pet', 'app.delete_pet')
pet = graphene.Field(PetNode)

class Input:
name = graphene.String(required=True)

@classmethod
def mutate(cls, root, input, context, info):
# Auth Required Virification
if cls.has_permision(context) is not True:
return cls.has_permision(context)
# End Auth
pet_name = input.get('name')
pet = Pet.objects.create(name=pet_name)
return CreatePet(pet=pet)

Adding permissions to filters
-----------------------------
We use DjangoFilterConnectionField to create filters to our nodes. Graphene-django has a field with
permission required ``AuthDjangoFilterConnectionField``. This field requires permissions to access
to it's nodes and is simple to create your filters.

.. code:: python

class MyCustomFilter(AuthDjangoFilterConnectionField):
_permission = ('app.add_pet', 'app.delete_pet')

With this example code we can implement filters with required permissions.
Empty file.
38 changes: 38 additions & 0 deletions graphene_django/auth/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.core.exceptions import PermissionDenied
from graphene_django.filter.fields import DjangoFilterConnectionField
from graphene_django.fields import DjangoConnectionField


class AuthDjangoFilterConnectionField(DjangoFilterConnectionField):
_permission = ''

@classmethod
def has_perm(cls, context):
if context is None:
return False
if type(context) is dict:
user = context.get('user', None)
if user is None:
return False
else:
user = context.user
if user.is_authenticated() is False:
return False

if type(cls._permission) is tuple:
for permission in cls._permission:
if not user.has_perm(permission):
return False
if type(cls._permission) is str:
if not user.has_perm(cls._permission):
return False
return True

def connection_resolver(self, resolver, connection, default_manager, filterset_class, filtering_args,
root, args, context, info):
if self.has_perm(context) is not True:
return DjangoConnectionField.connection_resolver(
resolver, connection, [PermissionDenied('Permission Denied'), ], root, args, context, info)
return super(AuthDjangoFilterConnectionField, self).connection_resolver(
resolver, connection, default_manager, filterset_class, filtering_args,
root, args, context, info)
65 changes: 65 additions & 0 deletions graphene_django/auth/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from django.core.exceptions import PermissionDenied


class AuthNodeMixin():
_permission = ''

@classmethod
def get_node(cls, id, context, info):

def has_perm(object_instance):
if context is None:
return False
if type(context) is dict:
user = context.get('user', None)
if user is None:
return False
else:
user = context.user
if user.is_authenticated() is False:
return False

if type(cls._permission) is tuple:
for permission in cls._permission:
if not user.has_perm(permission):
return False
if type(cls._permission) is str:
if not user.has_perm(cls._permission):
return False
return True

try:
object_instance = cls._meta.model.objects.get(id=id)
except cls._meta.model.DoesNotExist:
return None

if has_perm(object_instance):
return object_instance
return PermissionDenied('Permission Denied')


class AuthMutationMixin():
_permission = ''

@classmethod
def has_permision(cls, context):
if context is None:
return PermissionDenied('Permission Denied')
if type(context) is dict:
user = context.get('user', None)
if user is None:
return PermissionDenied('Permission Denied')
else:
user = context.user
if user.is_authenticated() is False:
return PermissionDenied('Permission Denied')

if type(cls._permission) is tuple:
for permission in cls._permission:
if not user.has_perm(permission):
return PermissionDenied('Permission Denied')
return True
if type(cls._permission) is str:
if user.has_perm(cls._permission):
return True
return PermissionDenied('Permission Denied')
Loading