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

Clean up permissions utility functions

Jeremy Stretch 5 лет назад
Родитель
Сommit
85e932bfc1

+ 3 - 4
netbox/netbox/authentication.py

@@ -6,7 +6,7 @@ from django.contrib.auth.models import Group
 from django.db.models import Q
 from django.db.models import Q
 
 
 from users.models import ObjectPermission
 from users.models import ObjectPermission
-from utilities.permissions import permission_is_exempt, resolve_permission
+from utilities.permissions import permission_is_exempt, resolve_permission, resolve_permission_ct
 
 
 
 
 class ObjectPermissionBackend(ModelBackend):
 class ObjectPermissionBackend(ModelBackend):
@@ -42,8 +42,7 @@ class ObjectPermissionBackend(ModelBackend):
         return perms
         return perms
 
 
     def has_perm(self, user_obj, perm, obj=None):
     def has_perm(self, user_obj, perm, obj=None):
-        app_label, codename = perm.split('.')
-        action, model_name = codename.split('_')
+        app_label, action, model_name = resolve_permission(perm)
 
 
         # Superusers implicitly have all permissions
         # Superusers implicitly have all permissions
         if user_obj.is_active and user_obj.is_superuser:
         if user_obj.is_active and user_obj.is_superuser:
@@ -114,7 +113,7 @@ class RemoteUserBackend(_RemoteUserBackend):
         permissions_list = []
         permissions_list = []
         for permission_name, attrs in settings.REMOTE_AUTH_DEFAULT_PERMISSIONS.items():
         for permission_name, attrs in settings.REMOTE_AUTH_DEFAULT_PERMISSIONS.items():
             try:
             try:
-                content_type, action = resolve_permission(permission_name)
+                content_type, action = resolve_permission_ct(permission_name)
                 # TODO: Merge multiple actions into a single ObjectPermission per content type
                 # TODO: Merge multiple actions into a single ObjectPermission per content type
                 obj_perm = ObjectPermission(actions=[action], attrs=attrs)
                 obj_perm = ObjectPermission(actions=[action], attrs=attrs)
                 obj_perm.save()
                 obj_perm.save()

+ 11 - 9
netbox/utilities/permissions.py

@@ -19,33 +19,36 @@ def get_permission_for_model(model, action):
     )
     )
 
 
 
 
-def get_permission_action(name):
+def resolve_permission(name):
     """
     """
-    Return the action component (e.g. view or add) from a permission name.
+    Given a permission name, return the app_label, action, and model_name components. For example, "dcim.view_site"
+    returns ("dcim", "view", "site").
 
 
     :param name: Permission name in the format <app_label>.<action>_<model>
     :param name: Permission name in the format <app_label>.<action>_<model>
     """
     """
     try:
     try:
-        return name.split('.')[1].split('_')[0]
+        app_label, codename = name.split('.')
+        action, model_name = codename.rsplit('_', 1)
     except ValueError:
     except ValueError:
         raise ValueError(
         raise ValueError(
             f"Invalid permission name: {name}. Must be in the format <app_label>.<action>_<model>"
             f"Invalid permission name: {name}. Must be in the format <app_label>.<action>_<model>"
         )
         )
 
 
+    return app_label, action, model_name
 
 
-def resolve_permission(name):
+
+def resolve_permission_ct(name):
     """
     """
     Given a permission name, return the relevant ContentType and action. For example, "dcim.view_site" returns
     Given a permission name, return the relevant ContentType and action. For example, "dcim.view_site" returns
     (Site, "view").
     (Site, "view").
 
 
     :param name: Permission name in the format <app_label>.<action>_<model>
     :param name: Permission name in the format <app_label>.<action>_<model>
     """
     """
-    app_label, codename = name.split('.')
-    action, model_name = codename.split('_')
+    app_label, action, model_name = resolve_permission(name)
     try:
     try:
         content_type = ContentType.objects.get(app_label=app_label, model=model_name)
         content_type = ContentType.objects.get(app_label=app_label, model=model_name)
     except ContentType.DoesNotExist:
     except ContentType.DoesNotExist:
-        raise ValueError(f"Unknown app/model for {name}")
+        raise ValueError(f"Unknown app_label/model_name for {name}")
 
 
     return content_type, action
     return content_type, action
 
 
@@ -56,8 +59,7 @@ def permission_is_exempt(name):
 
 
     :param name: Permission name in the format <app_label>.<action>_<model>
     :param name: Permission name in the format <app_label>.<action>_<model>
     """
     """
-    app_label, codename = name.split('.')
-    action, model_name = codename.split('_')
+    app_label, action, model_name = resolve_permission(name)
 
 
     if action == 'view':
     if action == 'view':
         if (
         if (

+ 2 - 2
netbox/utilities/testing/testcases.py

@@ -7,7 +7,7 @@ from django.urls import reverse, NoReverseMatch
 from rest_framework.test import APIClient
 from rest_framework.test import APIClient
 
 
 from users.models import ObjectPermission, Token
 from users.models import ObjectPermission, Token
-from utilities.permissions import resolve_permission
+from utilities.permissions import resolve_permission_ct
 from .utils import disable_warnings, post_data
 from .utils import disable_warnings, post_data
 
 
 
 
@@ -33,7 +33,7 @@ class TestCase(_TestCase):
         Assign a set of permissions to the test user. Accepts permission names in the form <app>.<action>_<model>.
         Assign a set of permissions to the test user. Accepts permission names in the form <app>.<action>_<model>.
         """
         """
         for name in names:
         for name in names:
-            ct, action = resolve_permission(name)
+            ct, action = resolve_permission_ct(name)
             obj_perm = ObjectPermission(actions=[action])
             obj_perm = ObjectPermission(actions=[action])
             obj_perm.save()
             obj_perm.save()
             obj_perm.users.add(self.user)
             obj_perm.users.add(self.user)

+ 3 - 3
netbox/utilities/views.py

@@ -28,7 +28,7 @@ from extras.models import CustomField, CustomFieldValue, ExportTemplate
 from extras.querysets import CustomFieldQueryset
 from extras.querysets import CustomFieldQueryset
 from utilities.exceptions import AbortTransaction
 from utilities.exceptions import AbortTransaction
 from utilities.forms import BootstrapMixin, CSVDataField, TableConfigForm
 from utilities.forms import BootstrapMixin, CSVDataField, TableConfigForm
-from utilities.permissions import get_permission_action, get_permission_for_model
+from utilities.permissions import get_permission_for_model, resolve_permission
 from utilities.utils import csv_format, prepare_cloned_fields
 from utilities.utils import csv_format, prepare_cloned_fields
 from .error_handlers import handle_protectederror
 from .error_handlers import handle_protectederror
 from .forms import ConfirmationForm, ImportForm
 from .forms import ConfirmationForm, ImportForm
@@ -64,7 +64,7 @@ class ObjectPermissionRequiredMixin(AccessMixin):
         if user.has_perms((permission_required, *self.additional_permissions)):
         if user.has_perms((permission_required, *self.additional_permissions)):
 
 
             # Update the view's QuerySet to filter only the permitted objects
             # Update the view's QuerySet to filter only the permitted objects
-            action = get_permission_action(permission_required)
+            action = resolve_permission(permission_required)[1]
             self.queryset = self.queryset.restrict(user, action)
             self.queryset = self.queryset.restrict(user, action)
 
 
             return True
             return True
@@ -233,7 +233,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
         # Compile a dictionary indicating which permissions are available to the current user for this model
         # Compile a dictionary indicating which permissions are available to the current user for this model
         permissions = {}
         permissions = {}
         for action in ('add', 'change', 'delete', 'view'):
         for action in ('add', 'change', 'delete', 'view'):
-            perm_name = '{}.{}_{}'.format(model._meta.app_label, action, model._meta.model_name)
+            perm_name = get_permission_for_model(model, action)
             permissions[action] = request.user.has_perm(perm_name)
             permissions[action] = request.user.has_perm(perm_name)
 
 
         # Construct the table based on the user's permissions
         # Construct the table based on the user's permissions