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

Introduced ObjectPermissionRequiredMixin

Jeremy Stretch 5 лет назад
Родитель
Сommit
4b5d64939d
2 измененных файлов с 42 добавлено и 1 удалено
  1. 2 1
      netbox/dcim/views.py
  2. 40 0
      netbox/netbox/authentication.py

+ 2 - 1
netbox/dcim/views.py

@@ -21,6 +21,7 @@ from extras.models import Graph
 from extras.views import ObjectConfigContextView
 from ipam.models import Prefix, VLAN
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
+from netbox.authentication import ObjectPermissionRequiredMixin
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator
 from utilities.utils import csv_format
@@ -185,7 +186,7 @@ class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 # Sites
 #
 
-class SiteListView(PermissionRequiredMixin, ObjectListView):
+class SiteListView(ObjectPermissionRequiredMixin, ObjectListView):
     permission_required = 'dcim.view_site'
     queryset = Site.objects.prefetch_related('region', 'tenant')
     filterset = filters.SiteFilterSet

+ 40 - 0
netbox/netbox/authentication.py

@@ -0,0 +1,40 @@
+from django.contrib.auth.mixins import AccessMixin
+from django.contrib.contenttypes.models import ContentType
+from django.db.models import Q
+
+from users.models import ObjectPermission
+
+
+class ObjectPermissionRequiredMixin(AccessMixin):
+    permission_required = None
+
+    def has_permission(self):
+
+        # First, check whether the user has a model-level permission assigned
+        if self.request.user.has_perm(self.permission_required):
+            return True
+
+        # If not, check for an object-level permission
+        app, codename = self.permission_required.split('.')
+        action, model_name = codename.split('_')
+        model = self.queryset.model
+        obj_permissions = ObjectPermission.objects.filter(
+            Q(users=self.request.user) | Q(groups__user=self.request.user),
+            model=ContentType.objects.get_for_model(model),
+            **{f'can_{action}': True}
+        )
+        if obj_permissions:
+
+            # Update the view's QuerySet to filter only the permitted objects
+            # TODO: Do this more efficiently
+            for perm in obj_permissions:
+                self.queryset = self.queryset.filter(**perm.attrs)
+
+            return True
+
+        return False
+
+    def dispatch(self, request, *args, **kwargs):
+        if not self.has_permission():
+            return self.handle_no_permission()
+        return super().dispatch(request, *args, **kwargs)