diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index e96400eff..75e73d878 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -40,6 +40,7 @@ from guardian.utils import get_group_obj_perms_model from guardian.utils import get_user_obj_perms_model from rest_framework import fields from rest_framework import serializers +from rest_framework.exceptions import PermissionDenied from rest_framework.fields import SerializerMethodField from rest_framework.filters import OrderingFilter @@ -436,6 +437,19 @@ class OwnedObjectSerializer( return instance def update(self, instance, validated_data): + user = getattr(self, "user", None) + is_superuser = user.is_superuser if user is not None else False + is_owner = instance.owner == user if user is not None else False + is_unowned = instance.owner is None + + if ( + ("owner" in validated_data and validated_data["owner"] != instance.owner) + or "set_permissions" in validated_data + ) and not (is_superuser or is_owner or is_unowned): + raise PermissionDenied( + _("Insufficient permissions."), + ) + if "set_permissions" in validated_data: self._set_permissions(validated_data["set_permissions"], instance) self.validate_unique_together(validated_data, instance) diff --git a/src/documents/tests/test_api_permissions.py b/src/documents/tests/test_api_permissions.py index bc81dabe9..31b860745 100644 --- a/src/documents/tests/test_api_permissions.py +++ b/src/documents/tests/test_api_permissions.py @@ -441,6 +441,59 @@ class TestApiAuth(DirectoriesMixin, APITestCase): self.assertTrue(checker.has_perm("change_document", doc)) self.assertIn("change_document", get_perms(group1, doc)) + def test_document_permissions_change_requires_owner(self): + owner = User.objects.create_user(username="owner") + editor = User.objects.create_user(username="editor") + editor.user_permissions.add( + *Permission.objects.all(), + ) + + doc = Document.objects.create( + title="Ownered doc", + content="sensitive", + checksum="abc123", + mime_type="application/pdf", + owner=owner, + ) + + assign_perm("view_document", editor, doc) + assign_perm("change_document", editor, doc) + + self.client.force_authenticate(editor) + response = self.client.patch( + f"/api/documents/{doc.pk}/", + json.dumps( + { + "set_permissions": { + "view": { + "users": [editor.id], + "groups": [], + }, + "change": { + "users": None, + "groups": None, + }, + }, + }, + ), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + self.client.force_authenticate(editor) + response = self.client.patch( + f"/api/documents/{doc.pk}/", + json.dumps( + { + "owner": editor.id, + }, + ), + content_type="application/json", + ) + + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + def test_dynamic_permissions_fields(self): user1 = User.objects.create_user(username="user1") user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))