mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-09-14 13:47:58 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ac8dd7a04 | ||
|
|
f1b21628a9 |
@@ -2037,10 +2037,10 @@ class BulkEditSerializer(
|
||||
raise serializers.ValidationError("remove_custom_fields not specified")
|
||||
|
||||
def _validate_owner(self, owner):
|
||||
ownerUser = User.objects.get(pk=owner)
|
||||
if ownerUser is None:
|
||||
try:
|
||||
return User.objects.get(pk=owner)
|
||||
except (User.DoesNotExist, TypeError, ValueError):
|
||||
raise serializers.ValidationError("Specified owner cannot be found")
|
||||
return ownerUser
|
||||
|
||||
def _validate_parameters_set_permissions(self, parameters) -> None:
|
||||
if "set_permissions" not in parameters:
|
||||
@@ -2060,7 +2060,7 @@ class BulkEditSerializer(
|
||||
or not float(parameters["degrees"]).is_integer()
|
||||
):
|
||||
raise serializers.ValidationError("invalid rotation degrees")
|
||||
except ValueError:
|
||||
except (TypeError, ValueError):
|
||||
raise serializers.ValidationError("invalid rotation degrees")
|
||||
|
||||
def _validate_source_mode(self, parameters) -> None:
|
||||
@@ -2073,6 +2073,8 @@ class BulkEditSerializer(
|
||||
def _validate_parameters_split(self, parameters) -> None:
|
||||
if "pages" not in parameters:
|
||||
raise serializers.ValidationError("pages not specified")
|
||||
if not isinstance(parameters["pages"], str):
|
||||
raise serializers.ValidationError("invalid pages specified")
|
||||
try:
|
||||
pages = []
|
||||
docs = parameters["pages"].split(",")
|
||||
|
||||
@@ -1165,6 +1165,65 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.assertIn(b"set_permissions not specified", response.content)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.serialisers.bulk_edit.set_permissions")
|
||||
def test_set_permissions_rejects_nonexistent_owner(self, m) -> None:
|
||||
"""
|
||||
BulkEditSerializer._validate_owner called User.objects.get(pk=owner)
|
||||
with no try/except, so a syntactically valid but nonexistent user
|
||||
id raised an uncaught User.DoesNotExist instead of a clean 400.
|
||||
"""
|
||||
self.setup_mock(m, "set_permissions")
|
||||
|
||||
response = self.client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
json.dumps(
|
||||
{
|
||||
"documents": [self.doc2.id],
|
||||
"method": "set_permissions",
|
||||
"parameters": {
|
||||
"set_permissions": {"view": {"users": [self.user.id]}},
|
||||
"owner": 999999,
|
||||
},
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.serialisers.bulk_edit.set_permissions")
|
||||
def test_set_permissions_rejects_wrong_typed_owner(self, m) -> None:
|
||||
"""
|
||||
_validate_owner only caught User.DoesNotExist -- a wrong-typed
|
||||
owner (list/dict/non-numeric string) reaches
|
||||
User.objects.get(pk=owner) and raises an uncaught TypeError or
|
||||
ValueError instead, since `parameters` is a bare DictField with
|
||||
no type checking on "owner" at that level.
|
||||
"""
|
||||
self.setup_mock(m, "set_permissions")
|
||||
|
||||
for bad_owner in (["not", "an", "id"], {"nested": "dict"}, "not-a-number"):
|
||||
with self.subTest(owner=bad_owner):
|
||||
response = self.client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
json.dumps(
|
||||
{
|
||||
"documents": [self.doc2.id],
|
||||
"method": "set_permissions",
|
||||
"parameters": {
|
||||
"set_permissions": {
|
||||
"view": {"users": [self.user.id]},
|
||||
},
|
||||
"owner": bad_owner,
|
||||
},
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.serialisers.bulk_edit.set_permissions")
|
||||
def test_set_permissions_merge(self, m) -> None:
|
||||
self.setup_mock(m, "set_permissions")
|
||||
@@ -1438,6 +1497,53 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.serialisers.bulk_edit.rotate")
|
||||
def test_bulk_edit_rotate_rejects_null_degrees(self, m) -> None:
|
||||
"""
|
||||
BulkEditSerializer._validate_parameters_rotate's
|
||||
`float(parameters["degrees"])` raised an uncaught TypeError for
|
||||
None (only ValueError was caught), reachable via the legacy
|
||||
generic /api/documents/bulk_edit/ method="rotate" path (the
|
||||
dedicated /api/documents/rotate/ endpoint isn't affected, its
|
||||
`degrees` field is a typed IntegerField).
|
||||
"""
|
||||
self.setup_mock(m, "rotate")
|
||||
response = self.client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
json.dumps(
|
||||
{
|
||||
"documents": [self.doc2.id],
|
||||
"method": "rotate",
|
||||
"parameters": {"degrees": None},
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.serialisers.bulk_edit.split")
|
||||
def test_bulk_edit_split_rejects_null_pages(self, m) -> None:
|
||||
"""
|
||||
BulkEditSerializer._validate_parameters_split called
|
||||
parameters["pages"].split(",") with no type check, so a null
|
||||
value raised an uncaught AttributeError instead of a clean 400.
|
||||
"""
|
||||
self.setup_mock(m, "split")
|
||||
response = self.client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
json.dumps(
|
||||
{
|
||||
"documents": [self.doc2.id],
|
||||
"method": "split",
|
||||
"parameters": {"pages": None},
|
||||
},
|
||||
),
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
m.assert_not_called()
|
||||
|
||||
@mock.patch("documents.views.bulk_edit.rotate")
|
||||
def test_rotate_insufficient_permissions(self, m) -> None:
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
|
||||
Reference in New Issue
Block a user