Răsfoiți Sursa

Enforce constrained permissions when bulk renaming objects

Jeremy Stretch 5 ani în urmă
părinte
comite
4458ce69df
1 a modificat fișierele cu 36 adăugiri și 21 ștergeri
  1. 36 21
      netbox/utilities/views.py

+ 36 - 21
netbox/utilities/views.py

@@ -1054,33 +1054,48 @@ class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
         return get_permission_for_model(self.queryset.model, 'change')
 
     def post(self, request):
+        logger = logging.getLogger('netbox.views.BulkRenameView')
 
         if '_preview' in request.POST or '_apply' in request.POST:
             form = self.form(request.POST, initial={'pk': request.POST.getlist('pk')})
             selected_objects = self.queryset.filter(pk__in=form.initial['pk'])
 
             if form.is_valid():
-                for obj in selected_objects:
-                    find = form.cleaned_data['find']
-                    replace = form.cleaned_data['replace']
-                    if form.cleaned_data['use_regex']:
-                        try:
-                            obj.new_name = re.sub(find, replace, obj.name)
-                        # Catch regex group reference errors
-                        except re.error:
-                            obj.new_name = obj.name
-                    else:
-                        obj.new_name = obj.name.replace(find, replace)
-
-                if '_apply' in request.POST:
-                    for obj in selected_objects:
-                        obj.name = obj.new_name
-                        obj.save()
-                    messages.success(request, "Renamed {} {}".format(
-                        len(selected_objects),
-                        self.queryset.model._meta.verbose_name_plural
-                    ))
-                    return redirect(self.get_return_url(request))
+                try:
+                    with transaction.atomic():
+                        renamed_pks = []
+                        for obj in selected_objects:
+                            find = form.cleaned_data['find']
+                            replace = form.cleaned_data['replace']
+                            if form.cleaned_data['use_regex']:
+                                try:
+                                    obj.new_name = re.sub(find, replace, obj.name)
+                                # Catch regex group reference errors
+                                except re.error:
+                                    obj.new_name = obj.name
+                            else:
+                                obj.new_name = obj.name.replace(find, replace)
+                            renamed_pks.append(obj.pk)
+
+                        if '_apply' in request.POST:
+                            for obj in selected_objects:
+                                obj.name = obj.new_name
+                                obj.save()
+
+                            # Enforce constrained permissions
+                            if self.queryset.filter(pk__in=renamed_pks).count() != len(selected_objects):
+                                raise ObjectDoesNotExist
+
+                            messages.success(request, "Renamed {} {}".format(
+                                len(selected_objects),
+                                self.queryset.model._meta.verbose_name_plural
+                            ))
+                            return redirect(self.get_return_url(request))
+
+                except ObjectDoesNotExist:
+                    msg = "Object update failed due to object-level permissions violation"
+                    logger.debug(msg)
+                    form.add_error(None, msg)
 
         else:
             form = self.form(initial={'pk': request.POST.getlist('pk')})