Ver Fonte

Introduced ObjectPermissionRequiredMixin

Jeremy Stretch há 6 anos atrás
pai
commit
4b5d64939d
2 ficheiros alterados com 42 adições e 1 exclusões
  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 extras.views import ObjectConfigContextView
 from ipam.models import Prefix, VLAN
 from ipam.models import Prefix, VLAN
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
+from netbox.authentication import ObjectPermissionRequiredMixin
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator
 from utilities.paginator import EnhancedPaginator
 from utilities.utils import csv_format
 from utilities.utils import csv_format
@@ -185,7 +186,7 @@ class RegionBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 # Sites
 # Sites
 #
 #
 
 
-class SiteListView(PermissionRequiredMixin, ObjectListView):
+class SiteListView(ObjectPermissionRequiredMixin, ObjectListView):
     permission_required = 'dcim.view_site'
     permission_required = 'dcim.view_site'
     queryset = Site.objects.prefetch_related('region', 'tenant')
     queryset = Site.objects.prefetch_related('region', 'tenant')
     filterset = filters.SiteFilterSet
     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)