diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py index 8d374cc9093d2c501dd74d355e6d21172b51199d..ef615a93f6efac27d363b1b648327e8703e36ee4 100644 --- a/arkindex/documents/api/elements.py +++ b/arkindex/documents/api/elements.py @@ -814,6 +814,10 @@ class MetadataEdit(RetrieveUpdateDestroyAPIView): if Right.Write not in obj.element.corpus.get_acl_rights(request.user): self.permission_denied(request, message='You do not have write access to this corpus.') + def perform_destroy(self, instance): + serializer = self.get_serializer(instance) + serializer.delete(instance) + class AllowedMetaDataPagination(PageNumberPagination): page_size = 200 diff --git a/arkindex/documents/serializers/light.py b/arkindex/documents/serializers/light.py index 4f633870b2c717cb42dc1a0a20d4c61fbe404fa9..dd9f9f48174f35e40f88f6da025807fccf40d4eb 100644 --- a/arkindex/documents/serializers/light.py +++ b/arkindex/documents/serializers/light.py @@ -127,13 +127,18 @@ class MetaDataLightSerializer(serializers.ModelSerializer): revision = RevisionSerializer(read_only=True) dates = InterpretedDateSerializer(many=True, source='get_dates', read_only=True) - def check_allowed(self, corpus=None, type=None, name=None, **kwargs): + def check_allowed(self, corpus=None, type=None, name=None, instance=None, **kwargs): """ Assert metadata type and value are allowed in this corpus """ + message = 'Metadata with this (type, name) are forbidden for this corpus' + if instance: + type = instance.type + name = instance.name + message = 'Edition of metadata with this (type, name) are disallowed for this corpus' if not AllowedMetaData.objects.filter(corpus=corpus, type=type, name=name): raise ValidationError({ - '__all__': ['Metadata with this (type, name) are forbidden for this corpus'] + '__all__': [message] }) def create(self, validated_data): @@ -154,15 +159,9 @@ class MetaDataLightSerializer(serializers.ModelSerializer): user = self.context['request'].user element = instance.element if not (user.is_admin or user.is_internal): - # Assert instance is part of AllowedMetaData table so it can be edited by any user - if not AllowedMetaData.objects.filter( - corpus=element.corpus, - type=instance.type, - name=instance.name - ).exists(): - raise ValidationError({ - '__all__': ['Edition of metadata with this (type, name) are disallowed for this corpus'] - }) + # Assert actual instance is part of AllowedMetaData + self.check_allowed(corpus=element.corpus, instance=instance) + # Assert update is part of AllowedMetaData self.check_allowed(corpus=element.corpus, **validated_data) new_name = validated_data.get('name') or instance.name metadata = element.metadatas \ @@ -172,6 +171,13 @@ class MetaDataLightSerializer(serializers.ModelSerializer): validated_data['index'] = metadata.aggregate(Max('index'))['index__max'] + 1 return super().update(instance, validated_data) + def delete(self, instance): + user = self.context['request'].user + element = instance.element + if not (user.is_admin or user.is_internal): + self.check_allowed(corpus=element.corpus, instance=instance) + instance.delete() + class Meta: model = MetaData read_only_fields = ('id', ) diff --git a/arkindex/documents/tests/test_metadata.py b/arkindex/documents/tests/test_metadata.py index 8d50a0adc9cf42767506cc174148590cc9571692..f145933526bd8829d692e00d3b8da3291f572227 100644 --- a/arkindex/documents/tests/test_metadata.py +++ b/arkindex/documents/tests/test_metadata.py @@ -190,6 +190,25 @@ class TestMetaData(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertEqual(self.vol.metadatas.count(), 0) + def test_delete_non_allowed_metadata(self): + """ + A user may not be able to delete a non allowed metadata + """ + metadata = self.vol.metadatas.create(type=MetaType.Location, name='not editable', value='111,222') + self.client.force_login(self.user) + response = self.client.delete(reverse('api:metadata-edit', kwargs={'pk': str(metadata.id)})) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertDictEqual( + response.json(), + {'__all__': ['Edition of metadata with this (type, name) are disallowed for this corpus']} + ) + + def test_admin_delete_any(self): + metadata = self.vol.metadatas.create(type=MetaType.Location, name='not editable', value='111,222') + self.client.force_login(self.admin) + response = self.client.delete(reverse('api:metadata-edit', kwargs={'pk': str(metadata.id)})) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + def test_delete_metadata_private_corpus(self): self.client.force_login(self.user) response = self.client.delete(reverse('api:metadata-edit', kwargs={'pk': str(self.private_metadata.id)}))