Skip to content

Commit

Permalink
fix: update ownership decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
vncsna committed Apr 11, 2024
1 parent 235f1af commit 45cd919
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 22 deletions.
6 changes: 3 additions & 3 deletions bd_api/apps/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from django.db.models.query import QuerySet
from django.utils import timezone

from bd_api.custom.graphql_jwt import ownership_required
from bd_api.custom.graphql_jwt import owner_required
from bd_api.custom.model import BaseModel
from bd_api.custom.storage import OverwriteStorage, upload_to, validate_image

Expand Down Expand Up @@ -279,8 +279,8 @@ class Account(BaseModel, AbstractBaseUser, PermissionsMixin):
]
graphql_filter_fields_blacklist = ["internal_subscription"]
graphql_nested_filter_fields_whitelist = ["email", "username"]
graphql_query_decorator = ownership_required
graphql_mutation_decorator = ownership_required
graphql_query_decorator = owner_required(allow_anonymous=False)
graphql_mutation_decorator = owner_required(allow_anonymous=True)

USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "first_name", "last_name"]
Expand Down
41 changes: 22 additions & 19 deletions bd_api/custom/graphql_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def wrapper(*args, **kwargs):
return wrapper


def ownership_required(f, exc=exceptions.PermissionDenied):
def owner_required(allow_anonymous=False, exc=exceptions.PermissionDenied):
"""Decorator to limit graphql queries and mutations
- Super users are allowed to edit all resources
Expand All @@ -58,23 +58,26 @@ def get_uid(context, exp=r"id:\s[\"]?(\d+)[\"]?"):
query = context.body.decode("utf-8").replace('\\"', "").lower()
except Exception:
query = str(context._post).replace('\\"', "").lower()

return [int(uid) for uid in findall(exp, query)]

@wraps(f)
@context(f)
def wrapper(context, *args, **kwargs):
if context.user.is_staff:
return f(*args, **kwargs)
if context.user.is_superuser:
return f(*args, **kwargs)
uid = get_uid(context)
if context.user.is_anonymous:
if not uid:
uid = [int(uid) for uid in findall(exp, query)]
return uid[0] if uid else None

def decorator(f):
@wraps(f)
@context(f)
def wrapper(context, *args, **kwargs):
if context.user.is_staff:
return f(*args, **kwargs)
if context.user.is_authenticated:
if context.user.id == uid[0]:
if context.user.is_superuser:
return f(*args, **kwargs)
raise exc

return wrapper
uid = get_uid(context)
if context.user.is_authenticated:
if context.user.id == uid:
return f(*args, **kwargs)
if context.user.is_anonymous:
if allow_anonymous and not uid:
return f(*args, **kwargs)
raise exc

return wrapper

return decorator

0 comments on commit 45cd919

Please sign in to comment.