diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index c7391e2f1..3c1a93703 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -2039,7 +2039,7 @@ class BulkEditSerializer( def _validate_owner(self, owner): try: return User.objects.get(pk=owner) - except User.DoesNotExist: + except (User.DoesNotExist, TypeError, ValueError): raise serializers.ValidationError("Specified owner cannot be found") def _validate_parameters_set_permissions(self, parameters) -> None: diff --git a/src/documents/tests/test_api_bulk_edit.py b/src/documents/tests/test_api_bulk_edit.py index 2009694e3..b91988b98 100644 --- a/src/documents/tests/test_api_bulk_edit.py +++ b/src/documents/tests/test_api_bulk_edit.py @@ -1192,6 +1192,38 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase): 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")