From cdcb77dea8b143c93369d5a34ded0fe128c01ea1 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 29 Jun 2022 14:06:01 -0400 Subject: [PATCH] Move actions determination to a mixin --- netbox/netbox/views/generic/bulk_views.py | 24 +++++--------------- netbox/netbox/views/generic/mixins.py | 25 +++++++++++++++++++++ netbox/netbox/views/generic/object_views.py | 20 +++++------------ 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index 7267e73ed..bb1c2b8e3 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -24,7 +24,7 @@ from utilities.htmx import is_htmx from utilities.permissions import get_permission_for_model from utilities.views import GetReturnURLMixin from .base import BaseMultiObjectView -from .mixins import TableMixin +from .mixins import ActionsMixin, TableMixin __all__ = ( 'BulkComponentCreateView', @@ -37,7 +37,7 @@ __all__ = ( ) -class ObjectListView(BaseMultiObjectView, TableMixin): +class ObjectListView(BaseMultiObjectView, ActionsMixin, TableMixin): """ Display multiple objects, all the same type, as a table. @@ -51,13 +51,6 @@ class ObjectListView(BaseMultiObjectView, TableMixin): template_name = 'generic/object_list.html' filterset = None filterset_form = None - actions = ('add', 'import', 'export', 'bulk_edit', 'bulk_delete') - action_perms = defaultdict(set, **{ - 'add': {'add'}, - 'import': {'add'}, - 'bulk_edit': {'change'}, - 'bulk_delete': {'delete'}, - }) def get_required_permission(self): return get_permission_for_model(self.queryset.model, 'view') @@ -134,12 +127,7 @@ class ObjectListView(BaseMultiObjectView, TableMixin): self.queryset = self.filterset(request.GET, self.queryset).qs # Determine the available actions - actions = [] - for action in self.actions: - if request.user.has_perms([ - get_permission_for_model(model, name) for name in self.action_perms[action] - ]): - actions.append(action) + actions = self.get_permitted_actions(request.user) has_bulk_actions = any([a.startswith('bulk_') for a in actions]) if 'export' in request.GET: @@ -176,15 +164,13 @@ class ObjectListView(BaseMultiObjectView, TableMixin): 'table': table, }) - context = { + return render(request, self.template_name, { 'model': model, 'table': table, 'actions': actions, 'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None, **self.get_extra_context(request), - } - - return render(request, self.template_name, context) + }) class BulkCreateView(GetReturnURLMixin, BaseMultiObjectView): diff --git a/netbox/netbox/views/generic/mixins.py b/netbox/netbox/views/generic/mixins.py index 0adf3a4c4..4b3fa0740 100644 --- a/netbox/netbox/views/generic/mixins.py +++ b/netbox/netbox/views/generic/mixins.py @@ -1,8 +1,33 @@ +from collections import defaultdict + +from utilities.permissions import get_permission_for_model + __all__ = ( 'TableMixin', ) +class ActionsMixin: + actions = ('add', 'import', 'export', 'bulk_edit', 'bulk_delete') + action_perms = defaultdict(set, **{ + 'add': {'add'}, + 'import': {'add'}, + 'bulk_edit': {'change'}, + 'bulk_delete': {'delete'}, + }) + + def get_permitted_actions(self, user, model=None): + """ + Return a tuple of actions for which the given user is permitted to do. + """ + model = model or self.queryset.model + return [ + action for action in self.actions if user.has_perms([ + get_permission_for_model(model, name) for name in self.action_perms[action] + ]) + ] + + class TableMixin: def get_table(self, data, request, bulk_actions=True): diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index f9d8b6ac9..82867b429 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -1,5 +1,4 @@ import logging -from collections import defaultdict from copy import deepcopy from django.contrib import messages @@ -21,7 +20,7 @@ from utilities.permissions import get_permission_for_model from utilities.utils import get_viewname, normalize_querydict, prepare_cloned_fields from utilities.views import GetReturnURLMixin from .base import BaseObjectView -from .mixins import TableMixin +from .mixins import ActionsMixin, TableMixin __all__ = ( 'ComponentCreateView', @@ -71,7 +70,7 @@ class ObjectView(BaseObjectView): }) -class ObjectChildrenView(ObjectView, TableMixin): +class ObjectChildrenView(ObjectView, ActionsMixin, TableMixin): """ Display a table of child objects associated with the parent object. @@ -79,15 +78,13 @@ class ObjectChildrenView(ObjectView, TableMixin): child_model: The model class which represents the child objects table: The django-tables2 Table class used to render the child objects list filterset: A django-filter FilterSet that is applied to the queryset + actions: Supported actions for the model. When adding custom actions, bulk action names must + be prefixed with `bulk_`. Default actions: add, import, export, bulk_edit, bulk_delete + action_perms: A dictionary mapping supported actions to a set of permissions required for each """ child_model = None table = None filterset = None - actions = ('bulk_edit', 'bulk_delete') - action_perms = defaultdict(set, **{ - 'bulk_edit': {'change'}, - 'bulk_delete': {'delete'}, - }) def get_children(self, request, parent): """ @@ -125,12 +122,7 @@ class ObjectChildrenView(ObjectView, TableMixin): child_objects = self.filterset(request.GET, child_objects).qs # Determine the available actions - actions = [] - for action in self.actions: - if request.user.has_perms([ - get_permission_for_model(self.child_model, name) for name in self.action_perms[action] - ]): - actions.append(action) + actions = self.get_permitted_actions(request.user, model=self.child_model) table_data = self.prep_table_data(request, child_objects, instance) table = self.get_table(table_data, request, bool(actions))