perf: migrate bulk-edit-objects dispatch to permitted_object_ids (#13576)

* perf: migrate bulk-edit-objects apply_to_all dispatch to permitted_object_ids

Replaces get_objects_for_user_owner_aware/has_perms_owner_aware in the
BulkEditObjectsView apply_to_all dispatch (Tag/Correspondent/DocumentType/
StoragePath) with permitted_object_ids and the resolve-once,
check-membership pattern used elsewhere in this stage. Tag-descendant
expansion logic left untouched. Adds a security test pinning that
apply_to_all excludes objects the requester lacks object-level permission
on.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmMBGW9FKyDgmKRJ5H9rif

* test: add tag-descendant partial-permission coverage, verify pre-migration characterization

Adds TestBulkEditObjectsTagDescendantPartialPermission, exercising the
tag-descendant-expansion block in BulkEditObjectsView.post as a
non-superuser with object-level change_tag granted on a parent tag and
one of two children but not the other, confirming the expansion only
pulls in descendants the requester actually has permission on.

Verified both this test and the existing apply_to_all boundary test
pass unchanged against the pre-migration
get_objects_for_user_owner_aware/has_perms_owner_aware code (reverted
via a scratch patch of the prior commit's views.py hunk, then
restored), confirming they characterize genuine pre-existing behavior
rather than something the permitted_object_ids migration made
necessary.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UmMBGW9FKyDgmKRJ5H9rif

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Trenton H
2026-08-08 07:27:17 -07:00
committed by GitHub
co-authored by Claude Sonnet 5
parent 3986150f95
commit b192a419fd
2 changed files with 119 additions and 5 deletions
+5 -5
View File
@@ -178,6 +178,7 @@ from documents.permissions import has_global_statistics_permission
from documents.permissions import has_perms_owner_aware
from documents.permissions import has_system_status_permission
from documents.permissions import permitted_document_ids
from documents.permissions import permitted_object_ids
from documents.permissions import set_permissions_for_object
from documents.plugins.date_parsing import get_date_parser
from documents.schema import generate_object_with_permissions_schema
@@ -4764,10 +4765,8 @@ class BulkEditObjectsView(PassUserMixin):
"document_types": DocumentTypeFilterSet,
"storage_paths": StoragePathFilterSet,
}[object_type]
user_permitted_objects = get_objects_for_user_owner_aware(
user,
perm_codename,
object_class,
user_permitted_objects = object_class.objects.filter(
id__in=permitted_object_ids(user, object_class, perm_codename),
)
objs = filterset_class(
data=filters,
@@ -4792,8 +4791,9 @@ class BulkEditObjectsView(PassUserMixin):
if not user.is_superuser:
perm = f"documents.{perm_codename}"
permitted_ids = set(permitted_object_ids(user, object_class, perm_codename))
has_perms = user.has_perm(perm) and all(
has_perms_owner_aware(user, perm_codename, obj) for obj in objs
obj.pk in permitted_ids for obj in objs
)
if not has_perms: