BulkEditSerializer's hand-parsed validators only caught the exceptions
their happy paths raised, so wrong-typed input produced a 500 or was
passed through to the task:
- owner: a nonexistent or wrong-typed id raised an uncaught error, and a
boolean was accepted (Django coerces True to pk 1). It is now validated
with PrimaryKeyRelatedField and the validated pk is passed on.
- rotate: null raised TypeError, while true, "90" and 45 were accepted and
failed later in QPDF. Degrees are now an IntegerField plus a
multiple-of-90 check, passing an int on. The dedicated rotate endpoint
and edit_pdf operations share the same multiple-of-90 check.
- split: null raised AttributeError, "0" silently became the last page,
"3-1" gave an empty group that crashed the task, and a range like
"1-5000000" was expanded into a list during the request with no upper
bound. Each range is now checked against 1 <= start <= end <= page_count
before it is built.
SetPermissionsSerializer was a bare DictField, and the legacy bulk_edit
set_permissions parameter bypassed even that by hand-calling
validate_set_permissions() on an unchecked dict. A bool or a non-list in
place of users/groups crashed with a raw TypeError instead of a 400.
It is now a nested serializer (view/change, each with users/groups as
lists of integers), used for owned-object create/update, the legacy
bulk_edit set_permissions parameter, and bulk_edit_objects permissions.
Unknown action keys are rejected: previously a typo like "veiw" was
silently dropped, leaving an empty permission set that could clear
existing grants. An explicit set_permissions null (an owner-only change)
remains a no-op, and an empty bulk_edit_objects permissions dict is still
rejected.
operations was a ListField with no child, so both EditPdfDocumentsSerializer
and BulkEditSerializer._validate_parameters_edit_pdf hand-checked each entry
with isinstance(). That accepted booleans (isinstance(True, int) is true) and
passed through any extra keys.
Adds PdfEditOperationSerializer (page >= 1, doc >= 0, rotate a multiple of
90) and uses it as the ListField child on both paths, dropping the manual
type checks and the now-redundant negative/page < 1 bounds checks. Rotations
that are not a multiple of 90 previously passed validation and then failed
inside the task when QPDF refused them.
* Feature: parse advanced search with whoosh-compat and delete the hand-written translator
* Don't cover these, they exist for defensive, but there's no other current diagnostic
* A mix of more no cover and tests
* Route SCHEMA_FIELD_MISSING into an error, not an HTTP 400
* Move permissions-related API tests
* Move bulk-edit-related API tests
* Move bulk-download-related API tests
* Move uisettings-related API tests
* Move remoteversion-related API tests
* Move tasks API tests
* Move object-related API tests
* Move consumption-template-related API tests
* Rename pared-down documents API test file
Co-Authored-By: Trenton H <797416+stumpylog@users.noreply.github.com>