Clean up permissions utility functions

This commit is contained in:
Jeremy Stretch 2020-06-02 09:26:45 -04:00
parent 7b01ba9776
commit 85e932bfc1
4 changed files with 19 additions and 18 deletions

View File

@ -6,7 +6,7 @@ from django.contrib.auth.models import Group
from django.db.models import Q
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):
@ -42,8 +42,7 @@ class ObjectPermissionBackend(ModelBackend):
return perms
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
if user_obj.is_active and user_obj.is_superuser:
@ -114,7 +113,7 @@ class RemoteUserBackend(_RemoteUserBackend):
permissions_list = []
for permission_name, attrs in settings.REMOTE_AUTH_DEFAULT_PERMISSIONS.items():
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
obj_perm = ObjectPermission(actions=[action], attrs=attrs)
obj_perm.save()

View File

@ -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>
"""
try:
return name.split('.')[1].split('_')[0]
app_label, codename = name.split('.')
action, model_name = codename.rsplit('_', 1)
except ValueError:
raise ValueError(
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
(Site, "view").
: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:
content_type = ContentType.objects.get(app_label=app_label, model=model_name)
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
@ -56,8 +59,7 @@ def permission_is_exempt(name):
: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 (

View File

@ -7,7 +7,7 @@ from django.urls import reverse, NoReverseMatch
from rest_framework.test import APIClient
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
@ -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>.
"""
for name in names:
ct, action = resolve_permission(name)
ct, action = resolve_permission_ct(name)
obj_perm = ObjectPermission(actions=[action])
obj_perm.save()
obj_perm.users.add(self.user)

View File

@ -28,7 +28,7 @@ from extras.models import CustomField, CustomFieldValue, ExportTemplate
from extras.querysets import CustomFieldQueryset
from utilities.exceptions import AbortTransaction
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 .error_handlers import handle_protectederror
from .forms import ConfirmationForm, ImportForm
@ -64,7 +64,7 @@ class ObjectPermissionRequiredMixin(AccessMixin):
if user.has_perms((permission_required, *self.additional_permissions)):
# 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)
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
permissions = {}
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)
# Construct the table based on the user's permissions