From 501cdd92d276451384cec4f944a878d1289aa4ea Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:34:13 -0700 Subject: [PATCH] Fix: limit share link viewset actions (#12461) --- src/documents/tests/test_api_documents.py | 52 +++++++++++++++++++++++ src/documents/views.py | 10 ++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/documents/tests/test_api_documents.py b/src/documents/tests/test_api_documents.py index d38091347..352ce7810 100644 --- a/src/documents/tests/test_api_documents.py +++ b/src/documents/tests/test_api_documents.py @@ -2990,6 +2990,58 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase): self.assertEqual(create_resp.status_code, status.HTTP_201_CREATED) self.assertEqual(create_resp.data["document"], doc.pk) + def test_share_link_update_methods_not_allowed(self): + """ + GIVEN: + - An existing share link + WHEN: + - PUT and PATCH requests are made to its detail endpoint + THEN: + - The API rejects them with 405 and the link is unchanged + """ + doc = Document.objects.create( + title="test", + mime_type="application/pdf", + content="share link content", + ) + expiration = timezone.now() + timedelta(days=7) + create_resp = self.client.post( + "/api/share_links/", + data={ + "document": doc.pk, + "expiration": expiration.isoformat(), + "file_version": ShareLink.FileVersion.ORIGINAL, + }, + format="json", + ) + self.assertEqual(create_resp.status_code, status.HTTP_201_CREATED) + share_link_id = create_resp.data["id"] + + patch_resp = self.client.patch( + f"/api/share_links/{share_link_id}/", + data={ + "expiration": None, + "file_version": ShareLink.FileVersion.ARCHIVE, + }, + format="json", + ) + self.assertEqual(patch_resp.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) + + put_resp = self.client.put( + f"/api/share_links/{share_link_id}/", + data={ + "document": doc.pk, + "expiration": None, + "file_version": ShareLink.FileVersion.ARCHIVE, + }, + format="json", + ) + self.assertEqual(put_resp.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) + + share_link = ShareLink.objects.get(pk=share_link_id) + self.assertEqual(share_link.file_version, ShareLink.FileVersion.ORIGINAL) + self.assertIsNotNone(share_link.expiration) + def test_next_asn(self): """ GIVEN: diff --git a/src/documents/views.py b/src/documents/views.py index b7600bb6e..732fe2232 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -76,6 +76,7 @@ from rest_framework.exceptions import ValidationError from rest_framework.filters import OrderingFilter from rest_framework.filters import SearchFilter from rest_framework.generics import GenericAPIView +from rest_framework.mixins import CreateModelMixin from rest_framework.mixins import DestroyModelMixin from rest_framework.mixins import ListModelMixin from rest_framework.mixins import RetrieveModelMixin @@ -2702,7 +2703,14 @@ class TasksViewSet(ReadOnlyModelViewSet): ) -class ShareLinkViewSet(ModelViewSet, PassUserMixin): +class ShareLinkViewSet( + PassUserMixin, + CreateModelMixin, + RetrieveModelMixin, + DestroyModelMixin, + ListModelMixin, + GenericViewSet, +): model = ShareLink queryset = ShareLink.objects.all()