Improve validation for import session (#12492)

- Ensure that validated data is a dict shape
This commit is contained in:
Oliver
2026-07-28 23:50:44 +10:00
committed by GitHub
parent e918d84f60
commit 73c0bb9603
3 changed files with 59 additions and 7 deletions
+12 -3
View File
@@ -98,7 +98,10 @@ class DataImportSessionSerializer(InvenTreeModelSerializer):
if type(defaults) is not dict: if type(defaults) is not dict:
try: try:
defaults = json.loads(str(defaults)) defaults = json.loads(str(defaults))
except: except json.JSONDecodeError:
raise ValidationError(_('Invalid field defaults'))
if type(defaults) is not dict:
raise ValidationError(_('Invalid field defaults')) raise ValidationError(_('Invalid field defaults'))
return defaults return defaults
@@ -111,7 +114,10 @@ class DataImportSessionSerializer(InvenTreeModelSerializer):
if type(overrides) is not dict: if type(overrides) is not dict:
try: try:
overrides = json.loads(str(overrides)) overrides = json.loads(str(overrides))
except: except json.JSONDecodeError:
raise ValidationError(_('Invalid field overrides'))
if type(overrides) is not dict:
raise ValidationError(_('Invalid field overrides')) raise ValidationError(_('Invalid field overrides'))
return overrides return overrides
@@ -124,7 +130,10 @@ class DataImportSessionSerializer(InvenTreeModelSerializer):
if type(filters) is not dict: if type(filters) is not dict:
try: try:
filters = json.loads(str(filters)) filters = json.loads(str(filters))
except: except json.JSONDecodeError:
raise ValidationError(_('Invalid field filters'))
if type(filters) is not dict:
raise ValidationError(_('Invalid field filters')) raise ValidationError(_('Invalid field filters'))
return filters return filters
+41 -1
View File
@@ -152,7 +152,47 @@ class ImporterTest(ImporterMixin, InvenTreeTestCase):
self.assertEqual(n + 12, Company.objects.count()) self.assertEqual(n + 12, Company.objects.count())
def test_field_defaults(self): def test_field_defaults(self):
"""Test default field values.""" """Test default field values.
Regression test for bug #30 (dev/todo/bugs.md): validate_field_defaults
must reject any parsed JSON value that isn't actually a dict, not just
values which fail to parse as JSON at all.
"""
from django.core.exceptions import ValidationError as DjangoValidationError
def data_file():
# full_clean() reads the file eagerly, so each session needs its own
# freshly-opened (binary) copy
content = self.helper_file('companies.csv').read()
return ContentFile(content.encode(), 'companies.csv')
# A dict value is accepted as-is
session = DataImportSession(
data_file=data_file(), model_type='company', field_defaults={'name': 'Test'}
)
session.full_clean()
# A JSON-encoded dict string is also accepted (de-stringified)
session = DataImportSession(
data_file=data_file(),
model_type='company',
field_defaults='{"name": "Test"}',
)
session.full_clean()
# A JSON-encoded list is valid JSON, but not a dict - must be rejected
session = DataImportSession(
data_file=data_file(), model_type='company', field_defaults='[1, 2, 3]'
)
with self.assertRaises(DjangoValidationError):
session.full_clean()
# Garbage which does not even parse as JSON must also be rejected
session = DataImportSession(
data_file=data_file(), model_type='company', field_defaults='not valid json'
)
with self.assertRaises(DjangoValidationError):
session.full_clean()
def test_lookup_field_ambiguous_match(self): def test_lookup_field_ambiguous_match(self):
"""Test the behavior of lookup_related_field for ambiguous and pinned matches.""" """Test the behavior of lookup_related_field for ambiguous and pinned matches."""
+6 -3
View File
@@ -6,7 +6,7 @@ from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
# Define maximum limits for imported file data # Define maximum limits for imported file data
IMPORTER_MAX_FILE_SIZE = 32 * 1024 * 1042 IMPORTER_MAX_FILE_SIZE = 32 * 1024 * 1024
IMPORTER_MAX_ROWS = 5000 IMPORTER_MAX_ROWS = 5000
IMPORTER_MAX_COLS = 1000 IMPORTER_MAX_COLS = 1000
@@ -46,8 +46,11 @@ def validate_field_defaults(value):
return return
if type(value) is not dict: if type(value) is not dict:
# OK if we can parse it as JSON # OK if we can parse it as JSON - but the result must be a dict
try: try:
value = json.loads(value) value = json.loads(value)
except json.JSONDecodeError: except (TypeError, json.JSONDecodeError):
raise ValidationError(_('Value must be a valid dictionary object'))
if type(value) is not dict:
raise ValidationError(_('Value must be a valid dictionary object')) raise ValidationError(_('Value must be a valid dictionary object'))