From 3a0255a1cdcfd199e3797888091463258e268afd Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Fri, 22 Nov 2024 14:42:24 +0100 Subject: [PATCH] :sparkles: [#256] added Value error exception to return qs.none() when url filter doesn't end in valid uuid --- .../api/tests/test_filters.py | 282 ++++++++++++++++-- src/openklant/components/utils/filters.py | 5 +- src/openklant/utils/query.py | 9 +- 3 files changed, 271 insertions(+), 25 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/tests/test_filters.py b/src/openklant/components/klantinteracties/api/tests/test_filters.py index 8cf811a1..958aa702 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_filters.py +++ b/src/openklant/components/klantinteracties/api/tests/test_filters.py @@ -68,10 +68,22 @@ def test_filter_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"hadBetrokkene__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_party_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"hadBetrokkene__wasPartij__url": fake_party_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_partij_uuid(self): klantcontact = KlantcontactFactory.create() klantcontact2 = KlantcontactFactory.create() @@ -126,10 +138,24 @@ def test_filter_betrokkene_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"hadBetrokkene__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + betrokkene_list_url = reverse("klantinteracties:betrokkene-list") + fake_betrokkene_url = ( + "https://testserver.com" + betrokkene_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"hadBetrokkene__url": fake_betrokkene_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_onderwerpobject__url(self): klantcontact = KlantcontactFactory.create() klantcontact2 = KlantcontactFactory.create() @@ -171,10 +197,24 @@ def test_filter_onderwerpobject__url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"onderwerpobject__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + onderwerpobject_list_url = reverse("klantinteracties:onderwerpobject-list") + fake_onderwerpobject_url = ( + "https://testserver.com" + onderwerpobject_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"onderwerpobject__url": fake_onderwerpobject_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_was_onderwerpobject__url(self): klantcontact = KlantcontactFactory.create() klantcontact2 = KlantcontactFactory.create() @@ -216,12 +256,28 @@ def test_filter_was_onderwerpobject__url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"wasOnderwerpobject__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + was_onderwerpobject_list_url = reverse( + "klantinteracties:onderwerpobject-list" + ) + fake_was_onderwerpobject_url = ( + "https://testserver.com" + was_onderwerpobject_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"wasOnderwerpobject__url": fake_was_onderwerpobject_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + class BetrokkeneFilterSetTests(APITestCase): url = reverse("klantinteracties:betrokkene-list") @@ -265,10 +321,24 @@ def test_filter_had_klantcontact_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"hadKlantcontact__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + klantcontact_list_url = reverse("klantinteracties:klantcontact-list") + fake_klantcontact_url = ( + "https://testserver.com" + klantcontact_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"hadKlantcontact__url": fake_klantcontact_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_had_klantcontact_uuid(self): klantcontact = KlantcontactFactory.create() klantcontact2 = KlantcontactFactory.create() @@ -296,7 +366,7 @@ def test_filter_had_klantcontact_uuid(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"hadKlantcontact__uuid": "ValueError"} ) @@ -372,12 +442,26 @@ def test_filter_verstrektedigitaal_adres_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"verstrektedigitaalAdres__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + digitaaladres_list_url = reverse("klantinteracties:digitaaladres-list") + fake_digitaaladres_url = ( + "https://testserver.com" + digitaaladres_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"verstrektedigitaalAdres__url": fake_digitaaladres_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_verstrektedigitaal_adres_uuid(self): betrokkene = BetrokkeneFactory.create() betrokkene2 = BetrokkeneFactory.create() @@ -405,7 +489,7 @@ def test_filter_verstrektedigitaal_adres_uuid(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"verstrektedigitaalAdres__uuid": "ValueError"} ) @@ -472,10 +556,22 @@ def test_filter_was_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"wasPartij__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"wasPartij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_was_partij_uuid(self): partij = PartijFactory.create() partij2 = PartijFactory.create() @@ -503,7 +599,7 @@ def test_filter_was_partij_uuid(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"wasPartij__uuid": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -577,12 +673,24 @@ def test_filter_vertegenwoordigde_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"vertegenwoordigdePartij__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"vertegenwoordigdePartij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_partij_identificator_code_objecttype(self): partij, partij2 = PartijFactory.create_batch(2) PartijIdentificatorFactory.create( @@ -783,10 +891,22 @@ def test_filter_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"partij__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"partij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_partij_uuid(self): partij, partij2 = PartijFactory.create_batch(2) categorie_relatie = CategorieRelatieFactory.create(partij=partij) @@ -813,7 +933,7 @@ def test_filter_partij_uuid(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"partij__uuid": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -881,10 +1001,24 @@ def test_filter_categorie_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"categorie__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + categorie_list_url = reverse("klantinteracties:categorie-list") + fake_categorie_url = ( + "https://testserver.com" + categorie_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"categorie__url": fake_categorie_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_categorie_uuid(self): categorie = CategorieFactory.create() categorie2 = CategorieFactory.create() @@ -912,7 +1046,7 @@ def test_filter_categorie_uuid(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"categorie__uuid": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -990,10 +1124,24 @@ def test_filter_klantcontact_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"klantcontact__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + klantcontact_list_url = reverse("klantinteracties:klantcontact-list") + fake_klantcontact_url = ( + "https://testserver.com" + klantcontact_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"klantcontact__url": fake_klantcontact_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_actor_url(self): actor = ActorFactory.create() actor2 = ActorFactory.create() @@ -1032,10 +1180,22 @@ def test_filter_actor_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get(self.url, {"actor__url": "ValueError"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + actor_list_url = reverse("klantinteracties:actor-list") + fake_actor_url = "https://testserver.com" + actor_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"actor__url": fake_actor_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + class VertegenwoordigdenFiltersetTests(APITestCase): url = reverse("klantinteracties:vertegenwoordigden-list") @@ -1078,12 +1238,24 @@ def test_filter_vertegenwoordigende_partij_url(self): ) self.assertEqual(response.status_code, status.HTTP_200_OK) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"vertegenwoordigendePartij__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"vertegenwoordigendePartij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_vertegenwoordigde_partij_url(self): partij, partij2, partij3, partij4 = PartijFactory.create_batch(4) vertegenwoordigden = VertegenwoordigdenFactory.create( @@ -1123,12 +1295,24 @@ def test_filter_vertegenwoordigde_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"vertegenwoordigdePartij__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"vertegenwoordigdePartij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + class InterneTaakFilterSetTests(APITestCase): url = reverse("klantinteracties:internetaak-list") @@ -1167,12 +1351,24 @@ def test_filter_toegewezen_aan_actor_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"toegewezenAanActor__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + actor_list_url = reverse("klantinteracties:actor-list") + fake_actor_url = "https://testserver.com" + actor_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"toegewezenAanActor__url": fake_actor_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_aanleidinggevend_klantcontact_url(self): klantcontact, klantcontact2 = KlantcontactFactory.create_batch(2) internetaak = InterneTaakFactory.create(klantcontact=klantcontact) @@ -1210,12 +1406,26 @@ def test_filter_aanleidinggevend_klantcontact_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"aanleidinggevendKlantcontact__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + klantcontact_list_url = reverse("klantinteracties:klantcontact-list") + fake_klantcontact_url = ( + "https://testserver.com" + klantcontact_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"aanleidinggevendKlantcontact__url": fake_klantcontact_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + class DigitaalAdresFilterSetTests(APITestCase): url = reverse("klantinteracties:digitaaladres-list") @@ -1257,12 +1467,26 @@ def test_filter_verstrekt_door_betrokkene_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"verstrektDoorBetrokkene__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + with self.subTest("invalid_uuid_results_nothing"): + betrokkene_list_url = reverse("klantinteracties:betrokkene-list") + fake_betrokkene_url = ( + "https://testserver.com" + betrokkene_list_url + "/not-a-uuid" + ) + + response = self.client.get( + self.url, + {"verstrektDoorBetrokkene__url": fake_betrokkene_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) + def test_filter_verstrekt_door_partij_url(self): partij, partij2 = PartijFactory.create_batch(2) @@ -1299,8 +1523,20 @@ def test_filter_verstrekt_door_partij_url(self): self.assertEqual(response.json()["count"], 0) - with self.subTest("invalid_url_results_in_400"): + with self.subTest("no url as value restults in 400"): response = self.client.get( self.url, {"verstrektDoorPartij__url": "ValueError"} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + with self.subTest("invalid_uuid_results_nothing"): + partij_list_url = reverse("klantinteracties:partij-list") + fake_partij_url = "https://testserver.com" + partij_list_url + "/not-a-uuid" + + response = self.client.get( + self.url, + {"verstrektDoorPartij__url": fake_partij_url}, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assertEqual(response.json()["count"], 0) diff --git a/src/openklant/components/utils/filters.py b/src/openklant/components/utils/filters.py index 380bfa89..1b278dbc 100644 --- a/src/openklant/components/utils/filters.py +++ b/src/openklant/components/utils/filters.py @@ -36,6 +36,9 @@ def __init__(self, *args, **kwargs): def filter(self, qs, value: OpenApiTypes.URI) -> QuerySet: if value: - value = uuid.UUID(value.rstrip("/").split("/")[-1]) + try: + value = uuid.UUID(value.rstrip("/").split("/")[-1]) + except ValueError: + return qs.none() return super().filter(qs, value) diff --git a/src/openklant/utils/query.py b/src/openklant/utils/query.py index 31b15412..51d2eecf 100644 --- a/src/openklant/utils/query.py +++ b/src/openklant/utils/query.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: EUPL-1.2 # Copyright (C) 2024 Dimpact from drf_spectacular.contrib.django_filters import DjangoFilterExtension +from drf_spectacular.utils import OpenApiParameter from vng_api_common.utils import underscore_to_camel @@ -17,7 +18,13 @@ def get_schema_operation_parameters(self, auto_schema, *args, **kwargs): for parameter in parameters: parameter["name"] = underscore_to_camel(parameter["name"]) - if parameter["name"].endswith("__url"): + + # reshape url fields which has incorrect field format + is_query = parameter["in"] == OpenApiParameter.QUERY + is_string = parameter["schema"]["type"] == "string" + is_url_field = parameter["name"].endswith("__url") + + if all((is_query, is_string, is_url_field)): parameter["schema"] = {"type": "string", "format": "uri"} return parameters