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

Fix shared action pre-selection and additional actions leakage on edit

Jason Novinger 21 часов назад
Родитель
Сommit
8a72b3c61c
2 измененных файлов с 44 добавлено и 3 удалено
  1. 5 2
      netbox/users/forms/model_forms.py
  2. 39 1
      netbox/utilities/tests/test_permissions.py

+ 5 - 2
netbox/users/forms/model_forms.py

@@ -430,17 +430,20 @@ class ObjectPermissionForm(forms.ModelForm):
 
             # Pre-select registered actions
             selected_registered = []
+            consumed_actions = set()
             for ct in self.instance.object_types.all():
                 model_key = f'{ct.app_label}.{ct.model}'
                 if model_key in model_actions:
                     for ma in model_actions[model_key]:
                         if ma.name in remaining_actions:
                             selected_registered.append(f'{model_key}.{ma.name}')
-                            remaining_actions.remove(ma.name)
+                            consumed_actions.add(ma.name)
             self.fields['registered_actions'].initial = selected_registered
 
             # Remaining actions go to the additional actions field
-            self.fields['actions'].initial = remaining_actions
+            self.initial['actions'] = [
+                a for a in remaining_actions if a not in consumed_actions
+            ]
 
         # Populate initial data for a new ObjectPermission
         elif self.initial:

+ 39 - 1
netbox/utilities/tests/test_permissions.py

@@ -1,8 +1,12 @@
 from django.test import TestCase
 
-from dcim.models import Site
+from core.models import ObjectType
+from dcim.models import Device, Site
 from netbox.registry import registry
+from users.forms.model_forms import ObjectPermissionForm
+from users.models import ObjectPermission
 from utilities.permissions import ModelAction, register_model_actions
+from virtualization.models import VirtualMachine
 
 
 class ModelActionTest(TestCase):
@@ -75,3 +79,37 @@ class RegisterModelActionsTest(TestCase):
         self.assertEqual(len(actions), 2)
         self.assertEqual(actions[0].name, 'first')
         self.assertEqual(actions[1].name, 'second')
+
+
+class ObjectPermissionFormTest(TestCase):
+
+    def setUp(self):
+        self.original_actions = dict(registry['model_actions'])
+
+    def tearDown(self):
+        registry['model_actions'].clear()
+        registry['model_actions'].update(self.original_actions)
+
+    def test_shared_action_preselection(self):
+        register_model_actions(Device, [ModelAction('render_config')])
+        register_model_actions(VirtualMachine, [ModelAction('render_config')])
+
+        device_ct = ObjectType.objects.get_for_model(Device)
+        vm_ct = ObjectType.objects.get_for_model(VirtualMachine)
+
+        permission = ObjectPermission.objects.create(
+            name='Test Permission',
+            actions=['view', 'render_config'],
+        )
+        permission.object_types.set([device_ct, vm_ct])
+
+        form = ObjectPermissionForm(instance=permission)
+
+        initial = form.fields['registered_actions'].initial
+        self.assertIn('dcim.device.render_config', initial)
+        self.assertIn('virtualization.virtualmachine.render_config', initial)
+
+        # Should not leak into the additional actions field
+        self.assertEqual(form.initial['actions'], [])
+
+        permission.delete()