Skip to content

Commit

Permalink
feat(graphql): Update ScopedDjangoNode
Browse files Browse the repository at this point in the history
Append the verb "read" by default
  • Loading branch information
tOgg1 committed Feb 3, 2021
1 parent af9799f commit 6358faf
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
23 changes: 13 additions & 10 deletions django_scoped_permissions/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ScopedDjangoNodeOptions(DjangoObjectTypeOptions):
allow_anonymous = False # type: bool
node_permissions = None # type: Tuple[str]
field_permissions = None # type: Mapping[str, Union[bool, Tuple[str]]]
verb = "read" # type: str


class ScopedDjangoNode(DjangoObjectType):
Expand All @@ -46,6 +47,7 @@ def __init_subclass_with_meta__(
node_permissions=None,
field_permissions=None,
allow_anonymous=False,
verb="read",
_meta=None,
**options,
):
Expand All @@ -55,6 +57,7 @@ def __init_subclass_with_meta__(
_meta.allow_anonymous = allow_anonymous
_meta.node_permissions = node_permissions
_meta.field_permissions = field_permissions
_meta.verb = verb
interfaces = options.get("interfaces", ()) + (Node,)

# Great, the class is set up. Now let's add permission guards.
Expand Down Expand Up @@ -136,7 +139,7 @@ def get_node(cls, info, id):
if not isinstance(user, ScopedPermissionHolderMixin):
raise GraphQLError("You are not permitted to view this.")

if not obj.can_be_accessed_by(user):
if not obj.can_be_accessed_by(user, cls._meta.verb):
raise GraphQLError("You are not permitted to view this.")

return super().get_node(info, id)
Expand Down Expand Up @@ -196,20 +199,20 @@ class Meta:
abstract = True

@classmethod
def get_permissions(cls, root, info, input, id, obj) -> Iterable[str]:
def get_permissions(
cls, root, info, input, id, obj
) -> Union[Iterable[str], ScopedPermissionGuard]:
super_permissions = super().get_permissions(root, info, input, id, obj) or []

if hasattr(super_permissions, "__len__") and len(super_permissions) > 0:
if (
hasattr(super_permissions, "__len__")
and len(super_permissions) > 0
or isinstance(super_permissions, ScopedPermissionGuard)
):
return super_permissions

# If we don't have explicit permissions we use some defaults here.
if cls._meta.verb == "":
return ["{required_scopes}"]
else:
return [
# Double curly brackets escapes them in an f-string
f"{{required_scopes}}:{cls._meta.verb}"
]
return ScopedPermissionGuard(scope="{required_scopes}", verb=cls._meta.verb)

@classmethod
def check_permissions(cls, root, info, input, id, obj) -> None:
Expand Down
11 changes: 11 additions & 0 deletions django_scoped_permissions/tests/test_graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ class Query(graphene.ObjectType):
)
self.assertIsNotNone(result.errors)

# Can be accessed by someone who has read permissions
user_two.add_or_create_permission("user:read")
result = schema.execute(
query,
variables={"id": to_global_id("UserNode", user.id)},
context=Dict(user=user),
)
self.assertIsNone(result.errors)
data = Dict(result.data)
self.assertEqual("Tormod", data.user.firstName)

def test__node_with_explicit_permissions__has_explicit_permission_handling(
self,
):
Expand Down

0 comments on commit 6358faf

Please sign in to comment.