diff --git a/src/documents/matching.py b/src/documents/matching.py index af0d2d831..65f52d567 100644 --- a/src/documents/matching.py +++ b/src/documents/matching.py @@ -19,7 +19,7 @@ from documents.models import StoragePath from documents.models import Tag from documents.models import Workflow from documents.models import WorkflowTrigger -from documents.permissions import get_objects_for_user_owner_aware +from documents.permissions import permitted_object_ids from documents.regex import safe_regex_search if TYPE_CHECKING: @@ -55,10 +55,8 @@ def match_correspondents(document: Document, classifier: DocumentClassifier, use user = document.owner if user is not None: - correspondents = get_objects_for_user_owner_aware( - user, - "documents.view_correspondent", - Correspondent, + correspondents = Correspondent.objects.filter( + id__in=permitted_object_ids(user, Correspondent, "view_correspondent"), ) else: correspondents = Correspondent.objects.all() @@ -86,10 +84,8 @@ def match_document_types(document: Document, classifier: DocumentClassifier, use user = document.owner if user is not None: - document_types = get_objects_for_user_owner_aware( - user, - "documents.view_documenttype", - DocumentType, + document_types = DocumentType.objects.filter( + id__in=permitted_object_ids(user, DocumentType, "view_documenttype"), ) else: document_types = DocumentType.objects.all() @@ -116,7 +112,9 @@ def match_tags(document: Document, classifier: DocumentClassifier, user=None): user = document.owner if user is not None: - tags = get_objects_for_user_owner_aware(user, "documents.view_tag", Tag) + tags = Tag.objects.filter( + id__in=permitted_object_ids(user, Tag, "view_tag"), + ) else: tags = Tag.objects.all() @@ -145,10 +143,8 @@ def match_storage_paths(document: Document, classifier: DocumentClassifier, user user = document.owner if user is not None: - storage_paths = get_objects_for_user_owner_aware( - user, - "documents.view_storagepath", - StoragePath, + storage_paths = StoragePath.objects.filter( + id__in=permitted_object_ids(user, StoragePath, "view_storagepath"), ) else: storage_paths = StoragePath.objects.all() diff --git a/src/documents/tests/test_permission_filtering_security.py b/src/documents/tests/test_permission_filtering_security.py index a27a7e2b9..be72b6e8f 100644 --- a/src/documents/tests/test_permission_filtering_security.py +++ b/src/documents/tests/test_permission_filtering_security.py @@ -13,6 +13,7 @@ from django.test import override_settings from guardian.shortcuts import assign_perm from rest_framework.test import APIClient +from documents.matching import match_tags from documents.models import Correspondent from documents.models import DocumentType from documents.models import StoragePath @@ -554,3 +555,27 @@ class TestPermittedObjectIdsGenericModels: expected_visible=[obj.pk], expected_hidden=[], ) + + +@pytest.mark.django_db +class TestMatchingRespectsObjectPermissions: + def test_match_tags_only_considers_tags_visible_to_user(self): + owner = User.objects.create_user(username="tag_owner") + classifying_user = User.objects.create_user(username="classifier_user") + visible_tag = TagFactory( + owner=owner, + match="invoice", + matching_algorithm=Tag.MATCH_LITERAL, + ) + hidden_tag = TagFactory( + owner=owner, + match="invoice", + matching_algorithm=Tag.MATCH_LITERAL, + ) + assign_perm("view_tag", classifying_user, visible_tag) + doc = DocumentFactory(owner=classifying_user, content="an invoice document") + + matched = match_tags(doc, classifier=None, user=classifying_user) + matched_ids = {t.pk for t in matched} + assert visible_tag.pk in matched_ids + assert hidden_tag.pk not in matched_ids