Skip to content

Commit d3c5619

Browse files
Refactored entire permssion
1 parent c6f6b8d commit d3c5619

File tree

9 files changed

+137
-108
lines changed

9 files changed

+137
-108
lines changed

nxtbn/cart/admin_query.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from nxtbn.cart.models import Cart
55
from nxtbn.cart.admin_types import CartItemType, CartType
6-
from nxtbn.core.admin_permissions import check_user_permissions
6+
from nxtbn.core.admin_permissions import staff_required
77

88

99
class AdminCartQuery(graphene.ObjectType):
@@ -13,19 +13,19 @@ class AdminCartQuery(graphene.ObjectType):
1313

1414
items_in_cart = graphene.List(CartItemType, cart_id=graphene.ID(required=True))
1515

16+
@staff_required
1617
def resolve_carts(self, info, **kwargs):
17-
check_user_permissions(info, any_staff=True)
1818
return Cart.objects.all()
1919

20+
@staff_required
2021
def resolve_cart_by_user(self, info, user_id):
21-
check_user_permissions(info, any_staff=True)
2222
try:
2323
return Cart.objects.get(user_id=user_id)
2424
except Cart.DoesNotExist:
2525
return None
2626

27+
@staff_required
2728
def resolve_items_in_cart(self, info, cart_id):
28-
check_user_permissions(info, any_staff=True)
2929
try:
3030
cart = Cart.objects.get(id=cart_id)
3131
return cart.items.all()

nxtbn/core/admin_mutation.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import graphene
33

44
from nxtbn.core import CurrencyTypes
5-
from nxtbn.core.admin_permissions import check_user_permissions
65
from nxtbn.core.admin_types import CurrencyExchangeType
76
from nxtbn.core.models import CurrencyExchange
87
from nxtbn.users import UserRole
@@ -23,7 +22,6 @@ class Arguments:
2322

2423
@staticmethod
2524
def mutate(root, info, input):
26-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN])
2725
# Validate base_currency
2826
base_currency = input.base_currency
2927
if base_currency != settings.BASE_CURRENCY:
@@ -51,7 +49,6 @@ class Arguments:
5149

5250
@staticmethod
5351
def mutate(root, info, id, input):
54-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN])
5552
try:
5653
currency_exchange = CurrencyExchange.objects.get(pk=id)
5754
except CurrencyExchange.DoesNotExist:
@@ -69,7 +66,6 @@ class Arguments:
6966

7067
@staticmethod
7168
def mutate(root, info, id):
72-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN])
7369
try:
7470
currency_exchange = CurrencyExchange.objects.get(pk=id)
7571
except CurrencyExchange.DoesNotExist:

nxtbn/core/admin_permissions.py

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,23 @@
33

44
from nxtbn.users import UserRole
55

6-
class NxtbnAdminPermission(BasePermission):
7-
def has_permission(self, request, view):
8-
user = request.user
9-
if not user.is_authenticated:
10-
return False
11-
12-
if user.is_superuser:
13-
return True
14-
15-
return False
16-
176

7+
import functools
8+
from graphql import GraphQLError
189
class GranularPermission(BasePermission):
1910
def get_permission_name(self, model_name, action):
2011

2112
return f"{model_name}.{action}"
2213

2314
def has_permission(self, request, view):
15+
if not request.user.is_authenticated:
16+
return False
17+
18+
if request.user.is_superuser:
19+
return True
20+
21+
if request.user.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
22+
return True
2423

2524
model_name = view.queryset.model.__name__.lower() # Get model name dynamically
2625
action = view.action.required_perm
@@ -29,22 +28,84 @@ def has_permission(self, request, view):
2928

3029
# Check if the user has the generated permission
3130
return request.user.has_perm(permission_name)
31+
3232

33+
class ModelPermissions(BasePermission):
3334

34-
def check_user_permissions(info, any_staff=False, allowed_roles=[]):
35-
if not info.context.user.is_authenticated:
36-
raise Exception("You must be logged in to perform this action")
37-
38-
if not info.context.user.is_staff:
39-
raise Exception("You must be a staff to perform this action")
40-
41-
if info.context.user.is_superuser:
42-
return True
43-
44-
if any_staff:
45-
return True
46-
47-
if info.context.user.role not in allowed_roles:
48-
raise Exception("You do not have permission to perform this action")
35+
def has_permission(self, request, view):
36+
if not request.user.is_authenticated:
37+
return False
38+
39+
if request.user.is_superuser:
40+
return True
41+
42+
if request.user.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
43+
return True
44+
45+
46+
47+
model_cls = getattr(view, 'queryset', None)
48+
if model_cls is None:
49+
return False
50+
51+
model_meta = model_cls.model._meta
52+
53+
method_permissions_map = {
54+
'GET': f'{model_meta.app_label}.view_{model_meta.model_name}',
55+
'OPTIONS': f'{model_meta.app_label}.view_{model_meta.model_name}',
56+
'HEAD': f'{model_meta.app_label}.view_{model_meta.model_name}',
57+
'POST': f'{model_meta.app_label}.add_{model_meta.model_name}',
58+
'PUT': f'{model_meta.app_label}.change_{model_meta.model_name}',
59+
'PATCH': f'{model_meta.app_label}.change_{model_meta.model_name}',
60+
'DELETE': f'{model_meta.app_label}.delete_{model_meta.model_name}',
61+
}
62+
63+
required_permission = method_permissions_map.get(request.method)
64+
65+
if required_permission is None:
66+
return False
67+
68+
return request.user.has_perm(required_permission)
69+
70+
71+
72+
73+
def required_perm(code: str): # Used in graphql only
74+
def decorator(func):
75+
@functools.wraps(func)
76+
def wrapper(self, info, *args, **kwargs):
77+
operation = info.operation.operation
78+
user = info.context.user
79+
80+
if user.is_anonymous:
81+
raise GraphQLError("Authentication required")
82+
83+
if operation == "query":
84+
return func(self, info, *args, **kwargs)
85+
86+
87+
88+
if not user.has_perm(code): # Check if user has the required permission
89+
raise GraphQLError("Permission denied") # Block unauthorized access
90+
91+
return func(self, info, *args, **kwargs) # Call the actual resolver
92+
93+
return wrapper
4994

50-
return True
95+
return decorator
96+
97+
98+
def staff_required(func):
99+
@functools.wraps(func)
100+
def wrapper(self, info, *args, **kwargs):
101+
user = info.context.user
102+
103+
if user.is_anonymous:
104+
raise GraphQLError("Authentication required")
105+
106+
if not user.is_staff: # Check if the user is a staff member
107+
raise GraphQLError("Permission denied") # Block access if the user is not staff
108+
109+
return func(self, info, *args, **kwargs) # Call the actual resolver
110+
111+
return wrapper

nxtbn/core/admin_queries.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from graphql import GraphQLError
44

55
from nxtbn.core import CurrencyTypes
6-
from nxtbn.core.admin_permissions import check_user_permissions
6+
from nxtbn.core.admin_permissions import staff_required
77
from nxtbn.core.admin_types import AdminCurrencyTypesEnum, CurrencyExchangeType
88
from nxtbn.core.models import CurrencyExchange
99
from graphene_django.filter import DjangoFilterConnectionField
@@ -14,19 +14,18 @@ class AdminCoreQuery(graphene.ObjectType):
1414
currency_exchange = graphene.Field(CurrencyExchangeType, id=graphene.ID(required=True))
1515
allowed_currency_list = graphene.List(AdminCurrencyTypesEnum)
1616

17+
@staff_required
1718
def resolve_currency_exchanges(self, info, **kwargs):
18-
check_user_permissions(info, any_staff=True)
1919
return CurrencyExchange.objects.all()
2020

2121
def resolve_currency_exchange(self, info, id):
22-
check_user_permissions(info, any_staff=True)
2322
try:
2423
return CurrencyExchange.objects.get(id=id)
2524
except CurrencyExchange.DoesNotExist:
2625
return None
2726

27+
@staff_required
2828
def resolve_allowed_currency_list(self, info):
29-
check_user_permissions(info, any_staff=True)
3029
allowed_currency_list = settings.ALLOWED_CURRENCIES
3130

3231
if not allowed_currency_list:

nxtbn/filemanager/api/dashboard/views.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
DocumentSerializer,
1111
ImageSerializer,
1212
)
13-
from nxtbn.core.admin_permissions import NxtbnAdminPermission
1413
from nxtbn.core.paginator import NxtbnPagination
1514

1615
class ImageFilter(django_filters.FilterSet):
@@ -25,7 +24,6 @@ class ImageListView(generics.ListCreateAPIView):
2524
serializer_class = ImageSerializer
2625
queryset = Image.objects.all().order_by('-created_at')
2726
pagination_class = NxtbnPagination
28-
permission_classes = (NxtbnAdminPermission,)
2927
filter_backends = [ DjangoFilterBackend,]
3028
filterset_class = ImageFilter
3129

@@ -34,20 +32,17 @@ class ImageDetailView(generics.RetrieveUpdateDestroyAPIView):
3432
queryset = Image.objects.all()
3533
serializer_class = ImageSerializer
3634
pagination_class = NxtbnPagination
37-
permission_classes = (NxtbnAdminPermission,)
3835
lookup_field = "id"
3936

4037

4138
class DocumentListView(generics.ListCreateAPIView):
4239
serializer_class = DocumentSerializer
4340
queryset = Document.objects.all()
44-
permission_classes = (NxtbnAdminPermission,)
4541
pagination_class = NxtbnPagination
4642

4743

4844
class DocumentDetailView(generics.RetrieveUpdateDestroyAPIView):
4945
queryset = Document.objects.all()
5046
serializer_class = DocumentSerializer
5147
pagination_class = NxtbnPagination
52-
permission_classes = (NxtbnAdminPermission,)
5348
lookup_field = "id"

nxtbn/order/admin_queries.py

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import graphene
22
from graphene_django.filter import DjangoFilterConnectionField
33

4-
from nxtbn.core.admin_permissions import check_user_permissions
4+
from nxtbn.core.admin_permissions import staff_required
55
from nxtbn.order.admin_types import OrderType
66
from nxtbn.order.models import Address, Order
77
from nxtbn.users import UserRole
@@ -11,31 +11,17 @@ class AdminOrderQuery(graphene.ObjectType):
1111
orders = DjangoFilterConnectionField(OrderType)
1212
order = graphene.Field(OrderType, id=graphene.Int(required=True))
1313

14-
# all_addresses = graphene.List(AddressGraphType)
15-
# address = graphene.Field(AddressGraphType, id=graphene.Int(required=True))
14+
1615

16+
@staff_required
1717
def resolve_orders(self, info, **kwargs):
18-
check_user_permissions(info, any_staff=True)
1918
return Order.objects.all()
2019

20+
@staff_required
2121
def resolve_order(self, info, id):
22-
check_user_permissions(info, any_staff=True)
2322
try:
2423
order = Order.objects.get(id=id)
2524
except Order.DoesNotExist:
2625
raise Exception("Order not found")
2726

28-
return order
29-
30-
def resolve_addresses(self, info):
31-
check_user_permissions(info, any_staff=True)
32-
return Address.objects.all()
33-
34-
def resolve_address(self, info, id):
35-
check_user_permissions(info, any_staff=True)
36-
try:
37-
address = Address.objects.get(id=id)
38-
except Address.DoesNotExist:
39-
raise Exception("Address not found")
40-
41-
return address
27+
return order

nxtbn/product/admin_mutations.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import graphene
2-
from nxtbn.core.admin_permissions import check_user_permissions
32
from nxtbn.product.admin_types import CategoryTranslationType, CategoryType, CollectionTranslationType, ProductTagTranslationType, ProductTranslationType, ProductVariantTranslationType, SupplierTranslationType
43
from nxtbn.product.models import Category, CategoryTranslation, CollectionTranslation, ProductTagTranslation, ProductTranslation, ProductVariantTranslation, SupplierTranslation
54
from nxtbn.users import UserRole
@@ -20,7 +19,6 @@ class Arguments:
2019
category = graphene.Field(CategoryType)
2120

2221
def mutate(self, info, id, input):
23-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER])
2422
category = Category.objects.get(id=id)
2523
category.name = input.name
2624
category.description = input.description
@@ -48,7 +46,6 @@ class Arguments:
4846
product_translation = graphene.Field(ProductTranslationType)
4947

5048
def mutate(self, info, base_product_id, lang_code, name, summary, description, meta_title, meta_description):
51-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
5249
try:
5350
product_translation = ProductTranslation.objects.get(product_id=base_product_id, language_code=lang_code)
5451
except ProductTranslation.DoesNotExist:
@@ -76,7 +73,6 @@ class Arguments:
7673
category_translation = graphene.Field(CategoryTranslationType)
7774

7875
def mutate(self, info, base_category_id, lang_code, name, description, meta_title, meta_description):
79-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
8076
try:
8177
category_translation = CategoryTranslation.objects.get(category_id=base_category_id, language_code=lang_code)
8278
except CategoryTranslation.DoesNotExist:
@@ -103,7 +99,6 @@ class Arguments:
10399
supplier_translation = graphene.Field(SupplierTranslationType)
104100

105101
def mutate(self, info, base_supplier_id, lang_code, name, description, meta_title, meta_description):
106-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
107102
try:
108103
supplier_translation = SupplierTranslation.objects.get(supplier_id=base_supplier_id, language_code=lang_code)
109104
except SupplierTranslation.DoesNotExist:
@@ -127,7 +122,6 @@ class Arguments:
127122
product_variant_translation = graphene.Field(ProductVariantTranslationType)
128123

129124
def mutate(self, info, base_product_variant_id, lang_code, name, description, meta_title, meta_description):
130-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
131125
try:
132126
product_variant_translation = ProductVariantTranslation.objects.get(product_variant_id=base_product_variant_id, language_code=lang_code)
133127
except ProductVariantTranslation.DoesNotExist:
@@ -147,7 +141,6 @@ class Arguments:
147141
product_tag_translation = graphene.Field(ProductTagTranslationType)
148142

149143
def mutate(self, info, base_product_tag_id, lang_code, name, description, meta_title, meta_description):
150-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
151144
try:
152145
product_tag_translation = ProductTagTranslation.objects.get(product_tag_id=base_product_tag_id, language_code=lang_code)
153146
except ProductTagTranslation.DoesNotExist:
@@ -170,7 +163,6 @@ class Arguments:
170163
collection_translation = graphene.Field(CollectionTranslationType)
171164

172165
def mutate(self, info, base_collection_id, lang_code, name, description, meta_title, meta_description):
173-
check_user_permissions(info, allowed_roles=[UserRole.STORE_MANAGER, UserRole.ADMIN, UserRole.PRODUCT_MANAGER, UserRole.TRANSLATOR])
174166
try:
175167
collection_translation = CollectionTranslation.objects.get(collection_id=base_collection_id, language_code=lang_code)
176168
except CollectionTranslation.DoesNotExist:

0 commit comments

Comments
 (0)