Update ObjectPermission evaluation to support null attrs

This commit is contained in:
Jeremy Stretch 2020-05-28 09:39:27 -04:00
parent a261d10bfd
commit 814aff78b5
2 changed files with 14 additions and 8 deletions

View File

@ -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 # Update the view's QuerySet to filter only the permitted objects
attrs = ObjectPermission.objects.get_attr_constraints(request.user, permission_required) obj_perm_attrs = request.user._object_perm_cache[permission_required]
if attrs: attrs = Q()
# Update the view's QuerySet to filter only the permitted objects for perm_attrs in obj_perm_attrs:
self.queryset = self.queryset.filter(attrs) if perm_attrs:
return True 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')

View File

@ -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,