diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b940ccbc2..29dd54c6bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,10 @@ ctrl/command/middle-mouse click #2170 - 🐛(y-provider) destroy Y.Doc instances after each convert request #2129 - 🐛(backend) remove deleted sub documents in favorite_list endpoint #2083 +### Fixed + +- 🐛(backend) create_for_owner: add accesses before saving doc content #2124 + ## [v4.8.3] - 2026-03-23 ### Changed diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index 83bffc8383..0daf1218ca 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -516,7 +516,6 @@ def create(self, validated_data): document = models.Document.add_root( title=validated_data["title"], - content=document_content, creator=user, ) @@ -535,6 +534,9 @@ def create(self, validated_data): role=models.RoleChoices.OWNER, ) + document.content = document_content + document.save() + self._send_email_notification(document, validated_data, email, language) return document diff --git a/src/backend/core/tests/documents/test_api_documents_create_for_owner.py b/src/backend/core/tests/documents/test_api_documents_create_for_owner.py index f294403891..53aaf11423 100644 --- a/src/backend/core/tests/documents/test_api_documents_create_for_owner.py +++ b/src/backend/core/tests/documents/test_api_documents_create_for_owner.py @@ -594,6 +594,44 @@ def test_api_documents_create_for_owner_with_converter_exception( assert response.json() == {"content": ["Could not convert content"]} +@override_settings(SERVER_TO_SERVER_API_TOKENS=["DummyToken"]) +@pytest.mark.usefixtures("mock_convert_md") +def test_api_documents_create_for_owner_access_before_content(): + """ + Accesses must exist before content is saved to object storage so the owner + has access to the very first version of the document. + """ + user = factories.UserFactory() + accesses_at_save_time = [] + + original_save_content = Document.save_content + + def capturing_save_content(self, content): + accesses_at_save_time.extend( + list(self.accesses.values_list("user__sub", "role")) + ) + return original_save_content(self, content) + + data = { + "title": "My Document", + "content": "Document content", + "sub": str(user.sub), + "email": user.email, + } + + with patch.object(Document, "save_content", capturing_save_content): + response = APIClient().post( + "/api/v1.0/documents/create-for-owner/", + data, + format="json", + HTTP_AUTHORIZATION="Bearer DummyToken", + ) + + assert response.status_code == 201 + # The owner access must already exist when save_content is called + assert (str(user.sub), "owner") in accesses_at_save_time + + @override_settings(SERVER_TO_SERVER_API_TOKENS=["DummyToken"]) def test_api_documents_create_for_owner_with_empty_content(): """The content should not be empty or a 400 error should be raised."""