Skip to content

Commit bb8f5ee

Browse files
committed
Fix hard related objects not list error
The related object fields are not covered by the form, so don't pass any validation before trying to iterate over them and accessing their elements. Instead of allowing a hard technical error to be raised, explicitly check that it is indeed a list, and raise a normal validation error if not.
1 parent 6b3b4b3 commit bb8f5ee

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

netbox/dcim/tests/test_views.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,42 @@ def test_import_objects(self):
982982
ii1 = InventoryItemTemplate.objects.first()
983983
self.assertEqual(ii1.name, 'Inventory Item 1')
984984

985+
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
986+
def test_import_nolist(self):
987+
# Add all required permissions to the test user
988+
self.add_permissions(
989+
'dcim.view_devicetype',
990+
'dcim.add_devicetype',
991+
'dcim.add_consoleporttemplate',
992+
'dcim.add_consoleserverporttemplate',
993+
'dcim.add_powerporttemplate',
994+
'dcim.add_poweroutlettemplate',
995+
'dcim.add_interfacetemplate',
996+
'dcim.add_frontporttemplate',
997+
'dcim.add_rearporttemplate',
998+
'dcim.add_modulebaytemplate',
999+
'dcim.add_devicebaytemplate',
1000+
'dcim.add_inventoryitemtemplate',
1001+
)
1002+
1003+
for value in ('', 'null', '3', '"My console port"', '{name: "My other console port"}'):
1004+
with self.subTest(value=value):
1005+
import_data = f'''
1006+
manufacturer: Manufacturer 1
1007+
model: TEST-2000
1008+
slug: test-2000
1009+
u_height: 1
1010+
console-ports: {value}
1011+
'''
1012+
form_data = {
1013+
'data': import_data,
1014+
'format': 'yaml'
1015+
}
1016+
1017+
response = self.client.post(reverse('dcim:devicetype_bulk_import'), data=form_data, follow=True)
1018+
self.assertHttpStatus(response, 200)
1019+
self.assertContains(response, "console-ports: Must be a list.")
1020+
9851021
def test_export_objects(self):
9861022
url = reverse('dcim:devicetype_list')
9871023
self.add_permissions('dcim.view_devicetype')

netbox/netbox/views/generic/bulk_views.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,14 @@ def _save_object(self, import_form, model_form, request):
363363
# Iterate through the related object forms (if any), validating and saving each instance.
364364
for field_name, related_object_form in self.related_object_forms.items():
365365

366+
related_objects = model_form.data.get(field_name, list())
367+
if not isinstance(related_objects, list): # TODO isinstance(Sequence)?
368+
import_form.add_error(None, f"{field_name}: {_('Must be a list.')}")
369+
raise AbortTransaction()
370+
related_objects = list(enumerate(related_objects))
371+
366372
related_obj_pks = []
367-
for i, rel_obj_data in enumerate(model_form.data.get(field_name, list())):
373+
for i, rel_obj_data in related_objects:
368374
rel_obj_data = self.prep_related_object_data(obj, rel_obj_data)
369375
f = related_object_form(rel_obj_data)
370376

0 commit comments

Comments
 (0)