diff --git a/src/documents/signals/handlers.py b/src/documents/signals/handlers.py index 30c682cbf..2d6d5c441 100644 --- a/src/documents/signals/handlers.py +++ b/src/documents/signals/handlers.py @@ -794,6 +794,11 @@ def cleanup_user_deletion(sender, instance: User | Group, **kwargs) -> None: def add_to_index(sender, document, **kwargs) -> None: from documents.search import get_backend + # A newly consumed version is not searchable on its own, its content + # becomes the effective_content of the root document + if document.root_document_id: + document = document.root_document + get_backend().add_or_update( document, effective_content=document.get_effective_content(), diff --git a/src/documents/tests/search/test_backend.py b/src/documents/tests/search/test_backend.py index b75b58679..adab7c40f 100644 --- a/src/documents/tests/search/test_backend.py +++ b/src/documents/tests/search/test_backend.py @@ -16,6 +16,7 @@ from documents.search._backend import TantivyBackend from documents.search._backend import WriteBatch from documents.search._backend import get_backend from documents.search._backend import reset_backend +from documents.signals.handlers import add_to_index from documents.tests.factories import CorrespondentFactory from documents.tests.factories import DocumentFactory from documents.tests.factories import DocumentTypeFactory @@ -1030,6 +1031,45 @@ class TestHighlightHits: assert len(hits) == 0 +class TestVersionIndexing: + """ + GIVEN: + - A root document whose new version has just been consumed, e.g. by + the password removal workflow action + WHEN: + - The consumption finished signal is handled + THEN: + - The root document is indexed with the new version's content, since + versions are not searchable on their own + """ + + def test_consumed_version_updates_root_entry( + self, + backend: TantivyBackend, + mocker: MockerFixture, + ) -> None: + root = Document.objects.create( + title="Statement", + content="", + checksum="VER1", + pk=90, + ) + backend.add_or_update(root) + version = Document.objects.create( + title="Statement", + content="unprotected statement text", + checksum="VER2", + pk=91, + root_document=root, + version_index=1, + ) + mocker.patch("documents.search.get_backend", return_value=backend) + + add_to_index(sender=None, document=version) + + assert backend.search_ids("unprotected", user=None) == [root.pk] + + class TestIndexDirectoryGarbageCollection: """Regression tests for Tantivy segment files leaking on disk when multiple long-lived worker processes (Granian/Celery) take turns writing