mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-04-25 19:43:51 +03:00
Add test to permission type
This commit is contained in:
parent
56a4ae9194
commit
106d3e063d
|
@ -164,4 +164,4 @@ class DjangoPermissionField(Field):
|
|||
|
||||
def get_resolver(self, parent_resolver):
|
||||
"""Intercept resolver to analyse permissions"""
|
||||
return partial(auth_resolver, self.resolver or parent_resolver, self.permissions, True)
|
||||
return partial(auth_resolver, self.resolver or parent_resolver, self.permissions, None, None, True)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from mock import patch
|
||||
|
||||
from graphene import Interface, ObjectType, Schema, Connection, String
|
||||
from graphene import Interface, ObjectType, Schema, Connection, String, Field
|
||||
from graphene.relay import Node
|
||||
|
||||
from .. import registry
|
||||
from ..types import DjangoObjectType, DjangoObjectTypeOptions
|
||||
from ..types import DjangoObjectType, DjangoObjectTypeOptions, DjangoPermissionObjectType
|
||||
from .models import Article as ArticleModel
|
||||
from .models import Reporter as ReporterModel
|
||||
|
||||
|
@ -224,3 +224,101 @@ def test_django_objecttype_exclude_fields():
|
|||
|
||||
fields = list(Reporter._meta.fields.keys())
|
||||
assert "email" not in fields
|
||||
|
||||
|
||||
def extra_field_resolver(root, info, **kwargs):
|
||||
return 'extra field'
|
||||
|
||||
|
||||
class PermissionArticle(DjangoPermissionObjectType):
|
||||
"""Basic Type to test"""
|
||||
|
||||
class Meta(object):
|
||||
"""Meta Class"""
|
||||
field_to_permission = {
|
||||
'headline': ('content_type.permission1',),
|
||||
'pub_date': ('content_type.permission2',)
|
||||
}
|
||||
permission_to_field = {
|
||||
'content_type.permission3': ('headline', 'reporter', 'extra_field',)
|
||||
}
|
||||
model = ArticleModel
|
||||
|
||||
extra_field = Field(String, resolver=extra_field_resolver)
|
||||
|
||||
def resolve_headline(self, info, **kwargs):
|
||||
return 'headline'
|
||||
|
||||
|
||||
def test_django_permissions():
|
||||
expected = {
|
||||
'headline': ('content_type.permission1', 'content_type.permission3'),
|
||||
'pub_date': ('content_type.permission2',),
|
||||
'reporter': ('content_type.permission3',),
|
||||
'extra_field': ('content_type.permission3',),
|
||||
}
|
||||
assert PermissionArticle._field_permissions == expected
|
||||
|
||||
|
||||
def test_permission_resolver():
|
||||
MyType = object()
|
||||
|
||||
class Viewer(object):
|
||||
def has_perm(self, perm):
|
||||
return perm == 'content_type.permission3'
|
||||
|
||||
class Info(object):
|
||||
class Context(object):
|
||||
user = Viewer()
|
||||
context = Context()
|
||||
|
||||
resolved = PermissionArticle.resolve_headline(MyType, Info())
|
||||
assert resolved == 'headline'
|
||||
|
||||
|
||||
def test_resolver_without_permission():
|
||||
MyType = object()
|
||||
|
||||
class Viewer(object):
|
||||
def has_perm(self, perm):
|
||||
return False
|
||||
|
||||
class Info(object):
|
||||
class Context(object):
|
||||
user = Viewer()
|
||||
context = Context()
|
||||
|
||||
resolved = PermissionArticle.resolve_headline(MyType, Info())
|
||||
assert resolved is None
|
||||
|
||||
|
||||
def test_permission_resolver_to_field():
|
||||
MyType = object()
|
||||
|
||||
class Viewer(object):
|
||||
def has_perm(self, perm):
|
||||
return perm == 'content_type.permission3'
|
||||
|
||||
class Info(object):
|
||||
class Context(object):
|
||||
user = Viewer()
|
||||
context = Context()
|
||||
|
||||
resolved = PermissionArticle.resolve_extra_field(MyType, Info())
|
||||
assert resolved == 'extra field'
|
||||
|
||||
|
||||
def test_resolver_to_field_without_permission():
|
||||
MyType = object()
|
||||
|
||||
class Viewer(object):
|
||||
def has_perm(self, perm):
|
||||
return perm != 'content_type.permission3'
|
||||
|
||||
class Info(object):
|
||||
class Context(object):
|
||||
user = Viewer()
|
||||
context = Context()
|
||||
|
||||
resolved = PermissionArticle.resolve_extra_field(MyType, Info())
|
||||
assert resolved is None
|
||||
|
|
|
@ -9,7 +9,7 @@ from graphene.types.utils import yank_fields_from_attrs
|
|||
|
||||
from .converter import convert_django_field_with_choices
|
||||
from .registry import Registry, get_global_registry
|
||||
from .utils import DJANGO_FILTER_INSTALLED, get_model_fields, is_valid_django_model
|
||||
from .utils import DJANGO_FILTER_INSTALLED, get_model_fields, is_valid_django_model, auth_resolver
|
||||
|
||||
|
||||
def construct_fields(model, registry, only_fields, exclude_fields):
|
||||
|
@ -170,7 +170,7 @@ class DjangoPermissionObjectType(DjangoObjectType):
|
|||
|
||||
for field_name, field_permissions in cls._field_permissions.items():
|
||||
attr = 'resolve_{}'.format(field_name)
|
||||
resolver = getattr(cls, attr, None)
|
||||
resolver = getattr(cls._meta.fields[field_name], 'resolver', None) or getattr(cls, attr, None)
|
||||
|
||||
if not hasattr(field_permissions, '__iter__'):
|
||||
field_permissions = tuple(field_permissions)
|
||||
|
@ -188,7 +188,7 @@ class DjangoPermissionObjectType(DjangoObjectType):
|
|||
_as=Field,
|
||||
)
|
||||
for name, field in django_fields.items():
|
||||
if isinstance(field._type, NonNull):
|
||||
if hasattr(field, '_type') and isinstance(field._type, NonNull):
|
||||
field._type = field._type._of_type
|
||||
setattr(cls, name, field)
|
||||
|
||||
|
@ -211,7 +211,7 @@ class DjangoPermissionObjectType(DjangoObjectType):
|
|||
cls._field_permissions[field] = cls._field_permissions.get(field, tuple()) + permissions
|
||||
|
||||
@classmethod
|
||||
def set_auth_resolver(cls, name, permissions, field, resolver=None):
|
||||
def set_auth_resolver(cls, name, permissions, resolver=None):
|
||||
"""
|
||||
Set middleware resolver to handle field permissions
|
||||
:param name: Field name
|
||||
|
@ -220,4 +220,4 @@ class DjangoPermissionObjectType(DjangoObjectType):
|
|||
:param resolver: Field resolver
|
||||
:return: Middleware resolver to check permissions
|
||||
"""
|
||||
field.resolver = partial(auth_resolver, field.resolver or resolver, name, permissions, None, False)
|
||||
return partial(auth_resolver, resolver, permissions, name, None, False)
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.db.models.manager import Manager
|
|||
|
||||
|
||||
# from graphene.utils import LazyList
|
||||
from graphene.types.resolver import get_default_resolver
|
||||
from graphene.utils.get_unbound_function import get_unbound_function
|
||||
|
||||
|
||||
|
@ -110,11 +111,27 @@ def resolve_bound_resolver(resolver, root, info, **args):
|
|||
return resolver(root, info, **args)
|
||||
|
||||
|
||||
def auth_resolver(parent_resolver, permissions, raise_exception, root, info, **args):
|
||||
def resolve_default_resolver(attname, default_value, root, info, **args):
|
||||
"""
|
||||
Resolve field with default resolver
|
||||
:param attname: Field name
|
||||
:param default_value: Field default value
|
||||
:param root: Schema root
|
||||
:param info: Schema info
|
||||
:param args: Schema args
|
||||
:return: Resolved field
|
||||
"""
|
||||
resolver = get_default_resolver()
|
||||
return resolver(attname, default_value, root, info, **args)
|
||||
|
||||
|
||||
def auth_resolver(parent_resolver, permissions, attname, default_value, raise_exception, root, info, **args):
|
||||
"""
|
||||
Middleware resolver to check viewer's permissions
|
||||
:param parent_resolver: Field resolver
|
||||
:param permissions: Field permissions
|
||||
:param attname: Field name
|
||||
:param default_value: Default value to field if no resolver is provided
|
||||
:param raise_exception: If True a PermissionDenied is raised
|
||||
:param root: Schema root
|
||||
:param info: Schema info
|
||||
|
@ -127,6 +144,8 @@ def auth_resolver(parent_resolver, permissions, raise_exception, root, info, **a
|
|||
if parent_resolver:
|
||||
# A resolver is provided in the class
|
||||
return resolve_bound_resolver(parent_resolver, root, info, **args)
|
||||
# Get default resolver
|
||||
return resolve_default_resolver(attname, default_value, root, info, **args)
|
||||
elif raise_exception:
|
||||
raise PermissionDenied()
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue
Block a user