diff --git a/CHANGELOG.md b/CHANGELOG.md index 702e9427f5..ecb69d991d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix some search parameters validation [#1601](https://github.com/opendatateam/udata/pull/1601) - Prevent API tracking errors with unicode [#1602](https://github.com/opendatateam/udata/pull/1602) - Prevent a race condition error when uploading file with concurrent chunking [#1606](https://github.com/opendatateam/udata/pull/1606) +- Disallow resources dict in API [#1603](https://github.com/opendatateam/udata/pull/1603) ## 1.3.6 (2018-04-16) diff --git a/udata/forms/fields.py b/udata/forms/fields.py index a16776d363..3358732ce4 100644 --- a/udata/forms/fields.py +++ b/udata/forms/fields.py @@ -475,9 +475,11 @@ def __init__(self, model_form, *args, **kwargs): def process(self, formdata, data=unset_value): self._formdata = formdata self.initial_data = data - self.has_data = formdata and any( + self.is_list_data = formdata and self.name in formdata + self.is_dict_data = formdata and any( k.startswith(self.prefix) for k in formdata ) + self.has_data = self.is_list_data or self.is_dict_data if self.has_data: super(NestedModelList, self).process(formdata, data) else: @@ -486,9 +488,11 @@ def process(self, formdata, data=unset_value): def validate(self, form, extra_validators=tuple()): '''Perform validation only if data has been submitted''' - # Run normal validation only if there is data for this form if not self.has_data: return True + if self.is_list_data: + if not isinstance(self._formdata[self.name], (list, tuple)): + return False return super(NestedModelList, self).validate(form, extra_validators) def populate_obj(self, obj, name): diff --git a/udata/tests/api/test_datasets_api.py b/udata/tests/api/test_datasets_api.py index 08e1e9c862..3fda2bd470 100644 --- a/udata/tests/api/test_datasets_api.py +++ b/udata/tests/api/test_datasets_api.py @@ -245,6 +245,20 @@ def test_dataset_api_create_with_resources(self): dataset = Dataset.objects.first() self.assertEqual(len(dataset.resources), 3) + def test_dataset_api_create_with_resources_dict(self): + """Create a dataset w/ resources in a dict instead of list, + should fail + """ + data = DatasetFactory.as_dict() + data['resources'] = { + k: v for k, v in enumerate([ + ResourceFactory.as_dict() for _ in range(3) + ]) + } + with self.api_user(): + response = self.post(url_for('api.datasets'), data) + self.assert400(response) + def test_dataset_api_create_with_geom(self): '''It should create a dataset with resources from the API''' data = DatasetFactory.as_dict()