Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix updating ID for resource #3239

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions udata/core/dataset/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,10 @@ def post(self, dataset):
ResourceEditPermission(dataset).test()
form = api.validate(ResourceForm)
resource = Resource()

if form._fields.get("id").data in [r.id for r in dataset.resources]:
abort(400, "A resource with the same ID already exists.")
ThibaudDauce marked this conversation as resolved.
Show resolved Hide resolved

if form._fields.get("filetype").data != "remote":
api.abort(400, "This endpoint only supports remote resources")
form.populate_obj(resource)
Expand Down Expand Up @@ -547,6 +551,10 @@ def put(self, dataset, rid):
# ensure API client does not override url on self-hosted resources
if resource.filetype == "file":
form._fields.get("url").data = resource.url

if form._fields.get("id").data != resource.id:
abort(400, "Cannot update resource ID after creation")

# populate_obj populates existing resource object with the content of the form.
# update_resource saves the updated resource dict to the database
# the additional dataset.save is required as we update the last_modified date.
Expand Down
39 changes: 39 additions & 0 deletions udata/tests/api/test_datasets_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,18 @@ def test_dataset_api_update(self):
self.assertEqual(Dataset.objects.count(), 1)
self.assertEqual(Dataset.objects.first().description, "new description")

def test_cannot_modify_dataset_id(self):
user = self.login()
dataset = DatasetFactory(owner=user)

data = dataset.to_dict()
data["id"] = "7776aa373aa050e302b5714d"

response = self.put(url_for("api.dataset", dataset=dataset.id), data)

self.assert200(response)
ThibaudDauce marked this conversation as resolved.
Show resolved Hide resolved
self.assertEqual(response.json["id"], str(dataset.id))

def test_dataset_api_update_with_resources(self):
"""It should update a dataset from the API with resources parameters"""
user = self.login()
Expand Down Expand Up @@ -1082,6 +1094,33 @@ def test_unallowed_create_filetype_file(self):
# should fail because the POST endpoint only supports URL setting for remote resources
self.assert400(response)

def test_creating_and_updating_resource_uuid(self):
uuid_a = "c312cfb0-60f7-417c-9cf9-3d985196b22a"
uuid_b = "e8262134-5ff0-4bd8-98bc-5db76bb27856"

data = ResourceFactory.as_dict()
data["filetype"] = "remote"
data["id"] = uuid_a
response = self.post(url_for("api.resources", dataset=self.dataset), data)
self.assert201(response)
self.assertEqual(response.json["id"], uuid_a)

# Cannot create a second resource with the same UUID
data = ResourceFactory.as_dict()
data["filetype"] = "remote"
data["id"] = uuid_a
response = self.post(url_for("api.resources", dataset=self.dataset), data)
self.assert400(response)

# Cannot modify the ID of an existing resource
data = response.json
data["id"] = uuid_b
response = self.put(
url_for("api.resource", dataset=self.dataset, rid=uuid_a),
data,
)
self.assert400(response)

def test_create_normalize_format(self):
_format = " FORMAT "
data = ResourceFactory.as_dict()
Expand Down