mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-07 00:27:12 +00:00
Performance: unify permission-filtering backends, fixes Correspondent/Tag list slowness (#13601)
* feat: add unified PermittedObjectsFilter backed by permitted_object_ids * refactor: migrate all ViewSets to unified PermittedObjectsFilter Replace the deprecated ObjectOwnedOrGrantedPermissionsFilter, DocumentPermissionsFilter, and ObjectOwnedPermissionsFilter aliases with PermittedObjectsFilter directly across documents/views.py (8 sites, including TrashView's include_granted=False subclass) and paperless_mail/views.py (3 sites), then delete the now-unreferenced alias classes from documents/filters.py. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UFyrt7FWbRRdTUAcdqBcsc * docs: document legacy status of get_objects_for_user_owner_aware/has_perms_owner_aware Stage 4's PermittedObjectsFilter/permitted_object_ids() covers the queryset-filtering use case, but both functions still have production callers outside this plan's scope (documents/views.py, documents/serialisers.py, documents/signals/handlers.py, paperless_ai/matching.py, paperless_ai/ai_classifier.py). Per Task 20 Step 2, they are kept in place rather than partially deleted, with docstrings updated to note their legacy status and remaining callers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UFyrt7FWbRRdTUAcdqBcsc * Fix: address final review findings for permission-filter unification - Add a permanent regression test pinning TrashView's include_granted=False wiring: an explicit view_document grant on a trashed document must not leak it into /api/trash/ for a non-owner, non-superuser requester. - Drop the now-dead direct dependency djangorestframework-guardian; the last rest_framework_guardian import was removed by this branch's migration onto PermittedObjectsFilter. django-guardian is untouched. - Replace the hand-maintained, already-stale caller lists in get_objects_for_user_owner_aware/has_perms_owner_aware docstrings with a pointer to grep for remaining callers instead. - In PermittedObjectsFilter.filter_queryset, compute `model` only on the include_granted=True path that actually uses it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UFyrt7FWbRRdTUAcdqBcsc * perf: check bulk-edit-objects apply_to_all permissions via DB-side exclude/exists Materialized the full permitted_object_ids() set into a Python set() just to check membership for the request's objs queryset -- the same pattern already fixed at four other sites for Document. This one is used by apply_to_all, where objs can be an unbounded filtered selection (e.g. all tags matching a filter) rather than a small request-supplied ID list, making the wasted materialization worse here than at the sites already fixed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Cleans up the comment about why this is still here for now --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b192a419fd
commit
fc242bb570
8 files changed
+681
-606
No files matched your search
@@ -23,7 +23,7 @@ from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||
|
||||
from documents.filters import ObjectOwnedOrGrantedPermissionsFilter
|
||||
from documents.filters import PermittedObjectsFilter
|
||||
from documents.models import PaperlessTask
|
||||
from documents.permissions import PaperlessObjectPermissions
|
||||
from documents.permissions import has_perms_owner_aware
|
||||
@@ -75,7 +75,7 @@ class MailAccountViewSet(PassUserMixin, ModelViewSet[MailAccount]):
|
||||
serializer_class = MailAccountSerializer
|
||||
pagination_class = StandardPagination
|
||||
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
|
||||
filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,)
|
||||
filter_backends = (PermittedObjectsFilter,)
|
||||
|
||||
def get_permissions(self):
|
||||
if self.action == "test":
|
||||
@@ -197,7 +197,7 @@ class ProcessedMailViewSet(PassUserMixin, ReadOnlyModelViewSet[ProcessedMail]):
|
||||
filter_backends = (
|
||||
DjangoFilterBackend,
|
||||
OrderingFilter,
|
||||
ObjectOwnedOrGrantedPermissionsFilter,
|
||||
PermittedObjectsFilter,
|
||||
)
|
||||
filterset_class = ProcessedMailFilterSet
|
||||
|
||||
@@ -225,7 +225,7 @@ class MailRuleViewSet(PassUserMixin, ModelViewSet[MailRule]):
|
||||
serializer_class = MailRuleSerializer
|
||||
pagination_class = StandardPagination
|
||||
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
|
||||
filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,)
|
||||
filter_backends = (PermittedObjectsFilter,)
|
||||
|
||||
|
||||
@extend_schema_view(
|
||||
|
||||
Reference in new issue
Block a user