diff --git a/arkindex/training/api.py b/arkindex/training/api.py index b0b38db5f8c8d10002832fc61ffcf7eefe238984..cdecc15cd2fc4b67cd74a1429b51c2bdddd23b50 100644 --- a/arkindex/training/api.py +++ b/arkindex/training/api.py @@ -561,7 +561,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView): put=extend_schema( description=dedent( """ - Update a dataset. + Update a dataset. The dataset must not be in `complete` state. The sets array can only be updated following those cases: * Adding or removing sets, nothing specific is done. @@ -575,7 +575,7 @@ class CorpusDataset(CorpusACLMixin, ListCreateAPIView): patch=extend_schema( description=dedent( """ - Partially update a dataset. + Partially update a dataset. The dataset must not be in `complete` state. The sets array can only be updated following those cases: * Adding or removing sets, nothing specific is done. @@ -618,6 +618,10 @@ class DatasetUpdate(ACLMixin, RetrieveUpdateDestroyAPIView): if not self.has_access(obj.corpus, role.value): raise PermissionDenied(detail=f'You do not have {str(role).lower()} access to corpus {obj.corpus.name}.') + # Prevent editing anything on a complete dataset + if obj.state == DatasetState.Complete: + raise ValidationError(detail='This dataset is in complete state and cannot be modified anymore.') + def perform_destroy(self, dataset): dataset.dataset_elements.all().delete() super().perform_destroy(dataset) diff --git a/arkindex/training/tests/test_datasets_api.py b/arkindex/training/tests/test_datasets_api.py index 2733436554f2239b5735fa2125a2d700815ec89a..5216495af92fe13ae5ecf16cb9d85aba5afeb291 100644 --- a/arkindex/training/tests/test_datasets_api.py +++ b/arkindex/training/tests/test_datasets_api.py @@ -711,10 +711,6 @@ class TestDatasetsAPI(FixtureAPITestCase): (build, build) : True, (build, complete) : True, (build, error): True, - (complete, op): False, - (complete, build) : False, - (complete, complete) : True, - (complete, error): False, (error, op): False, (error, build) : True, (error, complete) : False, @@ -745,6 +741,29 @@ class TestDatasetsAPI(FixtureAPITestCase): {'state': [f'Transition from {state_from} to {state_to} is not allowed.']} ) + def test_update_complete_forbidden(self): + self.dataset.state = DatasetState.Complete + self.dataset.save() + self.client.force_login(self.user) + for new_state in DatasetState: + with self.subTest(new_state=new_state): + with self.assertNumQueries(6): + response = self.client.put( + reverse('api:dataset-update', kwargs={'pk': self.dataset.pk}), + data={ + 'name': 'AA', + 'description': 'BB', + 'sets': self.dataset.sets + ['CC'], + 'state': new_state.value, + }, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertListEqual( + response.json(), + ['This dataset is in complete state and cannot be modified anymore.'], + ) + def test_update_ponos_task_state_requires_dataset_in_process(self): self.process.process_datasets.all().delete() with self.assertNumQueries(7): @@ -962,10 +981,6 @@ class TestDatasetsAPI(FixtureAPITestCase): (build, build) : True, (build, complete) : True, (build, error): True, - (complete, op): False, - (complete, build) : False, - (complete, complete) : True, - (complete, error): False, (error, op): False, (error, build) : True, (error, complete) : False, @@ -996,6 +1011,29 @@ class TestDatasetsAPI(FixtureAPITestCase): {'state': [f'Transition from {state_from} to {state_to} is not allowed.']} ) + def test_partial_update_complete_forbidden(self): + self.dataset.state = DatasetState.Complete + self.dataset.save() + self.client.force_login(self.user) + for new_state in DatasetState: + with self.subTest(new_state=new_state): + with self.assertNumQueries(6): + response = self.client.patch( + reverse('api:dataset-update', kwargs={'pk': self.dataset.pk}), + data={ + 'name': 'AA', + 'description': 'BB', + 'sets': self.dataset.sets + ['CC'], + 'state': new_state.value, + }, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertListEqual( + response.json(), + ['This dataset is in complete state and cannot be modified anymore.'], + ) + # RetrieveDataset def test_retrieve_requires_login(self):