From 91362b0f821bad2a0634eb6e582dbcbbe12d0745 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 21 May 2020 15:53:50 -0400 Subject: [PATCH] Transition BulkCreateView to use ObjectPermissionRequiredMixin --- netbox/ipam/views.py | 2 +- netbox/utilities/views.py | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 706f819cc..476943b13 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -721,7 +721,7 @@ class IPAddressDeleteView(ObjectDeleteView): default_return_url = 'ipam:ipaddress_list' -class IPAddressBulkCreateView(PermissionRequiredMixin, BulkCreateView): +class IPAddressBulkCreateView(BulkCreateView): permission_required = 'ipam.add_ipaddress' form = forms.IPAddressBulkCreateForm model_form = forms.IPAddressBulkAddForm diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index bd612b4df..ba1c18acc 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -468,20 +468,25 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): }) -class BulkCreateView(GetReturnURLMixin, View): +class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): """ Create new objects in bulk. - form: Form class which provides the `pattern` field - model_form: The ModelForm used to create individual objects - pattern_target: Name of the field to be evaluated as a pattern (if any) - template_name: The name of the template + :param queryset: Base queryset for the objects being created + :param form: Form class which provides the `pattern` field + :param model_form: The ModelForm used to create individual objects + :param pattern_target: Name of the field to be evaluated as a pattern (if any) + :param template_name: The name of the template """ + queryset = None form = None model_form = None pattern_target = '' template_name = None + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'add') + def get(self, request): # Set initial values for visible form fields from query args initial = {} @@ -501,7 +506,7 @@ class BulkCreateView(GetReturnURLMixin, View): def post(self, request): logger = logging.getLogger('netbox.views.BulkCreateView') - model = self.model_form._meta.model + model = self.queryset.model form = self.form(request.POST) model_form = self.model_form(request.POST) @@ -534,6 +539,10 @@ class BulkCreateView(GetReturnURLMixin, View): # Raise an IntegrityError to break the for loop and abort the transaction. raise IntegrityError() + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): + raise ObjectDoesNotExist + # If we make it to this point, validation has succeeded on all new objects. msg = "Added {} {}".format(len(new_objs), model._meta.verbose_name_plural) logger.info(msg) @@ -546,6 +555,11 @@ class BulkCreateView(GetReturnURLMixin, View): except IntegrityError: pass + except ObjectDoesNotExist: + msg = "Object creation failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + else: logger.debug("Form validation failed")