Просмотр исходного кода

Update ObjectPermission evaluation to support null attrs

Jeremy Stretch 5 лет назад
Родитель
Сommit
814aff78b5
2 измененных файлов с 14 добавлено и 8 удалено
  1. 8 7
      netbox/utilities/api.py
  2. 6 1
      netbox/utilities/auth_backends.py

+ 8 - 7
netbox/utilities/api.py

@@ -6,7 +6,7 @@ from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist, PermissionDenied
 from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist, PermissionDenied
 from django.db import transaction
 from django.db import transaction
-from django.db.models import ManyToManyField, ProtectedError
+from django.db.models import ManyToManyField, ProtectedError, Q
 from django.urls import reverse
 from django.urls import reverse
 from rest_framework.exceptions import APIException
 from rest_framework.exceptions import APIException
 from rest_framework.permissions import BasePermission
 from rest_framework.permissions import BasePermission
@@ -339,12 +339,13 @@ class ModelViewSet(_ModelViewSet):
         }
         }
         permission_required = TokenPermissions.perms_map[request.method][0] % kwargs
         permission_required = TokenPermissions.perms_map[request.method][0] % kwargs
 
 
-        # Enforce object-level permissions
-        attrs = ObjectPermission.objects.get_attr_constraints(request.user, permission_required)
-        if attrs:
-            # Update the view's QuerySet to filter only the permitted objects
-            self.queryset = self.queryset.filter(attrs)
-            return True
+        # Update the view's QuerySet to filter only the permitted objects
+        obj_perm_attrs = request.user._object_perm_cache[permission_required]
+        attrs = Q()
+        for perm_attrs in obj_perm_attrs:
+            if perm_attrs:
+                attrs |= Q(**perm_attrs)
+        self.queryset = self.queryset.filter(attrs)
 
 
     def dispatch(self, request, *args, **kwargs):
     def dispatch(self, request, *args, **kwargs):
         logger = logging.getLogger('netbox.api.views.ModelViewSet')
         logger = logging.getLogger('netbox.api.views.ModelViewSet')

+ 6 - 1
netbox/utilities/auth_backends.py

@@ -80,7 +80,12 @@ class ObjectPermissionBackend(ModelBackend):
         obj_perm_attrs = self.get_object_permissions(user_obj)[perm]
         obj_perm_attrs = self.get_object_permissions(user_obj)[perm]
         attrs = Q()
         attrs = Q()
         for perm_attrs in obj_perm_attrs:
         for perm_attrs in obj_perm_attrs:
-            attrs |= Q(**perm_attrs)
+            if perm_attrs:
+                attrs |= Q(**perm_attrs)
+            else:
+                # Found ObjectPermission with null attrs; allow model-level access
+                attrs = Q()
+                break
 
 
         # Permission to perform the requested action on the object depends on whether the specified object matches
         # Permission to perform the requested action on the object depends on whether the specified object matches
         # the specified attributes. Note that this check is made against the *database* record representing the object,
         # the specified attributes. Note that this check is made against the *database* record representing the object,