* Chore: drop get_groups_with_only_permission
It worked around get_groups_with_perms lacking only_with_perms_in, which
django-guardian added in 3.1.0. The pinned version is newer.
* Chore: consolidate direct grant lookups into get_permission_grantees
Six places listed who holds a permission on an object, each with its own
query and result shape, and one had already drifted into expanding group
members.
* Chore: drop the unreachable empty viewer grant default
get_permission_grantees returns an entry for every requested document.
* Chore: drop set_permissions_for_object in favor of the bulk helper
The same grant rules were implemented twice, and only the bulk version
validated every action before writing, so the single-object one could leave
a partial change behind.
* Chore: type the set-permissions dict
Callers passed whatever they had, including querysets of User and Group
objects that only worked because id__in accepts a subquery.
* Refactor: add pure pdf_ops module with real-PDF tests
* Drops tests we don't relly need + adds the typing annotation
* Now that I'm sure it works, re-work these tests to mock pdf_ops, rather than pikepdf
* Validates pages ahead of time in build_pdfs rather than during the building
* Adds the given/when/then and some additional cleanups of pytest style
* This is redundant now
Drops get_objects_for_user_owner_aware. Callers now use restrict_queryset_to_visible.
The same question was answered two ways, and the guardian path did not deny
deactivated users the way permitted_object_ids does.
* Chore: share one base class for the method-mapped permission classes
ViewDocumentsPermissions, TrashPermissions, PaperlessNotePermissions and
AcknowledgeTasksPermissions each repeated the same has_permission body and
disagreed on HTTP methods missing from their perms_map.
GlobalPermissionsByMethod now holds that logic once. HEAD is checked
against the GET entry and a method missing from the map is denied. The
task acknowledge map gains OPTIONS, now requiring change_paperlesstask
like POST instead of being open to any authenticated user. The global
statistics and system status checks also share their active and
authenticated preamble.
* Chore: type GlobalPermissionsByMethod.perms_map keys as HTTP methods
perms_map accepted any string key, so a misspelled method or a HEAD entry
would never match. Keys are now a Literal of the mappable methods, without
HEAD, and the map is typed read-only.