Skip to content

Commit 0f12997

Browse files
Merge pull request #377 from MySecondLanguage/permission-mutation-toggle
Permission mutation toggle
2 parents cf693e6 + 9367895 commit 0f12997

File tree

8 files changed

+84
-65
lines changed

8 files changed

+84
-65
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 staff_required
6+
from nxtbn.core.admin_permissions import gql_staff_required
77

88

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

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

16-
@staff_required
16+
@gql_staff_required
1717
def resolve_carts(self, info, **kwargs):
1818
return Cart.objects.all()
1919

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

27-
@staff_required
27+
@gql_staff_required
2828
def resolve_items_in_cart(self, info, cart_id):
2929
try:
3030
cart = Cart.objects.get(id=cart_id)

nxtbn/core/admin_permissions.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import functools
88
from graphql import GraphQLError
9+
910
class GranularPermission(BasePermission):
1011
def get_permission_name(self, model_name, action):
1112

@@ -18,19 +19,23 @@ def has_permission(self, request, view):
1819
if request.user.is_superuser:
1920
return True
2021

21-
if request.user.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
22+
if request.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
2223
return True
2324

24-
model_name = view.queryset.model.__name__.lower() # Get model name dynamically
25-
action = view.action.required_perm
25+
model_cls = getattr(view, 'queryset', None) or getattr(view, 'model', None)
26+
if model_cls is None:
27+
return False
28+
29+
model_name = model_cls.__name__.lower()
30+
action = view.required_perm
2631

2732
permission_name = self.get_permission_name(model_name, action)
2833

2934
# Check if the user has the generated permission
3035
return request.user.has_perm(permission_name)
3136

3237

33-
class ModelPermissions(BasePermission):
38+
class CommonPermissions(BasePermission):
3439

3540
def has_permission(self, request, view):
3641
if not request.user.is_authenticated:
@@ -39,12 +44,12 @@ def has_permission(self, request, view):
3944
if request.user.is_superuser:
4045
return True
4146

42-
if request.user.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
47+
if request.method in SAFE_METHODS and request.user.is_staff: # Every staff can view
4348
return True
4449

4550

4651

47-
model_cls = getattr(view, 'queryset', None)
52+
model_cls = getattr(view, 'queryset', None) or getattr(view, 'model', None)
4853
if model_cls is None:
4954
return False
5055

@@ -70,7 +75,7 @@ def has_permission(self, request, view):
7075

7176

7277

73-
def required_perm(code: str): # Used in graphql only
78+
def gql_required_perm(code: str): # Used in graphql only
7479
def decorator(func):
7580
@functools.wraps(func)
7681
def wrapper(self, info, *args, **kwargs):
@@ -95,7 +100,7 @@ def wrapper(self, info, *args, **kwargs):
95100
return decorator
96101

97102

98-
def staff_required(func):
103+
def gql_staff_required(func): # Used in graphql only
99104
@functools.wraps(func)
100105
def wrapper(self, info, *args, **kwargs):
101106
user = info.context.user

nxtbn/core/admin_queries.py

Lines changed: 3 additions & 3 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 staff_required
6+
from nxtbn.core.admin_permissions import gql_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,7 +14,7 @@ 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
17+
@gql_staff_required
1818
def resolve_currency_exchanges(self, info, **kwargs):
1919
return CurrencyExchange.objects.all()
2020

@@ -24,7 +24,7 @@ def resolve_currency_exchange(self, info, id):
2424
except CurrencyExchange.DoesNotExist:
2525
return None
2626

27-
@staff_required
27+
@gql_staff_required
2828
def resolve_allowed_currency_list(self, info):
2929
allowed_currency_list = settings.ALLOWED_CURRENCIES
3030

nxtbn/order/admin_queries.py

Lines changed: 3 additions & 3 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 staff_required
4+
from nxtbn.core.admin_permissions import gql_staff_required
55
from nxtbn.order.admin_types import OrderType
66
from nxtbn.order.models import Address, Order
77
from nxtbn.users import UserRole
@@ -13,11 +13,11 @@ class AdminOrderQuery(graphene.ObjectType):
1313

1414

1515

16-
@staff_required
16+
@gql_staff_required
1717
def resolve_orders(self, info, **kwargs):
1818
return Order.objects.all()
1919

20-
@staff_required
20+
@gql_staff_required
2121
def resolve_order(self, info, id):
2222
try:
2323
order = Order.objects.get(id=id)

nxtbn/order/api/dashboard/views.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import django_filters
2222
from django_filters import rest_framework as filters
2323

24-
from nxtbn.core.admin_permissions import GranularPermission
24+
from nxtbn.core.admin_permissions import GranularPermission, CommonPermissions
25+
from nxtbn.core.enum_perms import PermissionsEnum
2526
from nxtbn.core.utils import to_currency_unit
2627
from nxtbn.order.proccesor.views import OrderProccessorAPIView
2728
from nxtbn.order import OrderAuthorizationStatus, OrderChargeStatus, OrderStatus, ReturnStatus
@@ -90,6 +91,7 @@ def filter_max_order_value(self, queryset, name, value):
9091

9192

9293
class OrderListView(generics.ListAPIView):
94+
permission_classes = (CommonPermissions, )
9395
queryset = Order.objects.all()
9496
serializer_class = OrderListSerializer
9597
pagination_class = NxtbnPagination
@@ -103,10 +105,9 @@ class OrderListView(generics.ListAPIView):
103105
search_fields = ['alias', 'id', 'user__username', 'supplier__name']
104106
ordering_fields = ['created_at']
105107

106-
role_action = 'list'
107-
108108

109109
class OrderDetailView(generics.RetrieveAPIView):
110+
permission_classes = (CommonPermissions, )
110111
queryset = Order.objects.all()
111112
serializer_class = OrderDetailsSerializer
112113
lookup_field = 'alias'
@@ -130,7 +131,7 @@ class OrderDetailView(generics.RetrieveAPIView):
130131

131132

132133
class BasicStatsView(APIView):
133-
134+
permission_classes = (CommonPermissions, )
134135
def get(self, request):
135136
# Get start and end dates from query parameters
136137
start_date_str = request.query_params.get('start_date')
@@ -217,6 +218,7 @@ def get(self, request):
217218

218219

219220
class OrderOverviewStatsView(APIView):
221+
permission_classes = (CommonPermissions, )
220222
"""
221223
View to provide an overview of order statistics within a specified date range.
222224
Methods:
@@ -310,7 +312,7 @@ def get(self, request):
310312

311313

312314
class OrderSummaryAPIView(APIView):
313-
315+
permission_classes = (CommonPermissions, )
314316
def get(self, request, *args, **kwargs):
315317
time_period = request.query_params.get('time_period') # 'year', 'month', 'week', 'day'
316318
current_date = datetime.now()
@@ -392,12 +394,20 @@ def get(self, request, *args, **kwargs):
392394

393395
return Response(formatted_data)
394396
class OrderEastimateView(OrderProccessorAPIView):
395-
permission_classes = (GranularPermission, )
396-
required_perm = 'order.eastimate_order'
397-
398397
create_order = False # Eastimate order
399398

399+
def check_permissions(self, request):
400+
if not request.user.is_staff:
401+
self.permission_denied(
402+
request,
403+
message=_("You do not have permission to perform this action."),
404+
code='permission_denied'
405+
)
406+
400407
class OrderCreateView(OrderProccessorAPIView):
408+
model = Order
409+
permission_classes = (GranularPermission, )
410+
required_perm = 'add_order'
401411
create_order = True # Eastimate and create order
402412

403413
class CreateCustomAPIView(generics.CreateAPIView):

nxtbn/product/admin_queries.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import graphene
44

55
from graphene_django.filter import DjangoFilterConnectionField
6-
from nxtbn.core.admin_permissions import staff_required
6+
from nxtbn.core.admin_permissions import gql_staff_required
77
from nxtbn.product.admin_types import CategoryTranslationType, CategoryType, CollectionTranslationType, CollectionType, ProductGraphType, ProductTagTranslationType, ProductTagType, ProductTranslationType, ProductVariantAdminType, SupplierType
88
from nxtbn.product.models import Category, CategoryTranslation, Collection, CollectionTranslation, Product, ProductTag, ProductTagTranslation, ProductTranslation, Supplier
99
from nxtbn.users import UserRole
@@ -42,114 +42,114 @@ class ProductQuery(graphene.ObjectType):
4242
tags_translations = DjangoFilterConnectionField(ProductTagTranslationType)
4343

4444

45-
@staff_required
45+
@gql_staff_required
4646
def resolve_product(root, info, id):
4747

4848
try:
4949
return Product.objects.get(pk=id)
5050
except Product.DoesNotExist:
5151
return None
5252

53-
@staff_required
53+
@gql_staff_required
5454
def resolve_products(root, info, **kwargs):
5555
return Product.objects.all()
5656

5757

58-
@staff_required
58+
@gql_staff_required
5959
def resolve_collection(root, info, id):
6060

6161
try:
6262
return Collection.objects.get(pk=id)
6363
except Collection.DoesNotExist:
6464
return None
6565

66-
@staff_required
66+
@gql_staff_required
6767
def resolve_collections(root, info, **kwargs):
6868
return Collection.objects.all()
6969

70-
@staff_required
70+
@gql_staff_required
7171
def resolve_producttag(root, info, id):
7272

7373
try:
7474
return ProductTag.objects.get(pk=id)
7575
except ProductTag.DoesNotExist:
7676
return None
7777

78-
@staff_required
78+
@gql_staff_required
7979
def resolve_producttags(root, info, **kwargs):
8080
return ProductTag.objects.all()
8181

8282

83-
@staff_required
83+
@gql_staff_required
8484
def resolve_supplier(root, info, id):
8585

8686
try:
8787
return Supplier.objects.get(pk=id)
8888
except Supplier.DoesNotExist:
8989
return None
9090

91-
@staff_required
91+
@gql_staff_required
9292
def resolve_suppliers(root, info, **kwargs):
9393
return Product.objects.all()
9494

95-
@staff_required
95+
@gql_staff_required
9696
def resolve_product_variants(root, info, **kwargs):
9797
return Product.objects.all()
9898

99-
@staff_required
99+
@gql_staff_required
100100
def resolve_category(root, info, id):
101101

102102
try:
103103
return Category.objects.get(pk=id)
104104
except Category.DoesNotExist:
105105
return None
106106

107-
@staff_required
107+
@gql_staff_required
108108
def resolve_categories(root, info, **kwargs):
109109
return Category.objects.all()
110110

111111
# All translations
112-
@staff_required
112+
@gql_staff_required
113113
def resolve_category_translation(root, info, base_category_id, lang_code):
114114
try:
115115
return CategoryTranslation.objects.get(category_id=base_category_id, language_code=lang_code)
116116
except CategoryTranslation.DoesNotExist:
117117
return None
118-
@staff_required
118+
@gql_staff_required
119119
def resolve_category_translations(root, info, **kwargs):
120120
return CategoryTranslation.objects.all()
121121

122-
@staff_required
122+
@gql_staff_required
123123
def resolve_collection_translation(root, info, base_collection_id, lang_code):
124124
try:
125125
return CollectionTranslation.objects.get(collection_id=base_collection_id, language_code=lang_code)
126126
except CollectionTranslation.DoesNotExist:
127127
return None
128128

129-
@staff_required
129+
@gql_staff_required
130130
def resolve_collection_translations(root, info, **kwargs):
131131
return CollectionTranslation.objects.all()
132132

133-
@staff_required
133+
@gql_staff_required
134134
def resolve_tags_translation(root, info, base_tag_id, lang_code):
135135
try:
136136
return ProductTagTranslation.objects.get(tag_id=base_tag_id, language_code=lang_code)
137137
except ProductTagTranslation.DoesNotExist:
138138
return None
139139

140-
@staff_required
140+
@gql_staff_required
141141
def resolve_tags_translations(root, info, **kwargs):
142142
return ProductTagTranslation.objects.all()
143143

144144

145-
@staff_required
145+
@gql_staff_required
146146
def resolve_product_translation(root, info, base_product_id, lang_code):
147147
try:
148148
return ProductTranslation.objects.get(product_id=base_product_id, language_code=lang_code)
149149
except ProductTranslation.DoesNotExist:
150150
return None
151151

152-
@staff_required
152+
@gql_staff_required
153153
def resolve_product_translations(root, info, **kwargs):
154154
return ProductTranslation.objects.all()
155155

0 commit comments

Comments
 (0)