Skip to content

Commit

Permalink
Merge pull request #164 from open-zaak/feature/resource-validation-fo…
Browse files Browse the repository at this point in the history
…r-fk

Feature/resource validation for internal fk
  • Loading branch information
sergei-maertens committed Nov 7, 2019
2 parents 4f80f46 + 9ef1bf6 commit 2a73e22
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 16 deletions.
11 changes: 11 additions & 0 deletions src/openzaak/components/documenten/tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ def test_validate_informatieobjecttype_invalid(self):
error = get_validation_errors(response, "informatieobjecttype")
self.assertEqual(error["code"], "bad-url")

def test_validate_informatieobjecttype_invalid_resource(self):
url = reverse("enkelvoudiginformatieobject-list")

response = self.client.post(
url, {"informatieobjecttype": "https://example.com"}
)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
error = get_validation_errors(response, "informatieobjecttype")
self.assertEqual(error["code"], "invalid-resource")

def test_validate_informatieobjecttype_unpublished(self):
informatieobjecttype = InformatieObjectTypeFactory.create()
informatieobjecttype_url = reverse(informatieobjecttype)
Expand Down
2 changes: 1 addition & 1 deletion src/openzaak/components/zaken/api/serializers/zaken.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class Meta:
"Resultaat",
settings.REFERENTIELIJSTEN_API_SPEC,
get_auth=get_auth,
),
)
]
},
"hoofdzaak": {
Expand Down
82 changes: 78 additions & 4 deletions src/openzaak/components/zaken/tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from django.test import override_settings

import requests_mock
from freezegun import freeze_time
from rest_framework import status
from rest_framework.test import APITestCase
Expand Down Expand Up @@ -60,13 +61,16 @@ def setUpTestData(cls):
cls.zaaktype = ZaakTypeFactory.create(concept=False)
cls.zaaktype_url = reverse(cls.zaaktype)

def test_validate_zaaktype_invalid(self):
def test_validate_zaaktype_bad_url(self):
url = reverse("zaak-list")

with requests_mock.Mocker() as m:
m.get("https://example.com/zrc/zaken/1234", status_code=404)

response = self.client.post(
url,
{
"zaaktype": "https://example.com/foo/bar",
"zaaktype": "https://example.com/zrc/zaken/1234",
"bronorganisatie": "517439943",
"verantwoordelijkeOrganisatie": "517439943",
"registratiedatum": "2018-06-11",
Expand All @@ -81,6 +85,27 @@ def test_validate_zaaktype_invalid(self):
self.assertEqual(validation_error["code"], "bad-url")
self.assertEqual(validation_error["name"], "zaaktype")

def test_validate_zaaktype_invalid_resource(self):
url = reverse("zaak-list")

response = self.client.post(
url,
{
"zaaktype": "https://example.com",
"bronorganisatie": "517439943",
"verantwoordelijkeOrganisatie": "517439943",
"registratiedatum": "2018-06-11",
"startdatum": "2018-06-11",
},
**ZAAK_WRITE_KWARGS,
)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

validation_error = get_validation_errors(response, "zaaktype")
self.assertEqual(validation_error["code"], "invalid-resource")
self.assertEqual(validation_error["name"], "zaaktype")

def test_validate_zaaktype_valid(self, *mocks):
url = reverse("zaak-list")

Expand Down Expand Up @@ -687,7 +712,7 @@ def test_statustype_valid_resource(self):

self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)

def test_statustype_invalid_resource(self):
def test_statustype_bad_url(self):
zaak = ZaakFactory.create(zaaktype=self.zaaktype)
zaak_url = reverse(zaak)
list_url = reverse("status-list")
Expand All @@ -706,6 +731,25 @@ def test_statustype_invalid_resource(self):
error = get_validation_errors(response, "statustype")
self.assertEqual(error["code"], "bad-url")

def test_statustype_invalid_resource(self):
zaak = ZaakFactory.create(zaaktype=self.zaaktype)
zaak_url = reverse(zaak)
list_url = reverse("status-list")

response = self.client.post(
list_url,
{
"zaak": zaak_url,
"statustype": "https://example.com",
"datumStatusGezet": isodatetime(2018, 10, 1, 10, 00, 00),
},
)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

error = get_validation_errors(response, "statustype")
self.assertEqual(error["code"], "invalid-resource")

def test_statustype_zaaktype_mismatch(self):
zaak = ZaakFactory.create()
zaak_url = reverse(zaak)
Expand Down Expand Up @@ -819,7 +863,7 @@ def test_not_allowed_to_change_resultaattype(self):
validation_error = get_validation_errors(response, "resultaattype")
self.assertEqual(validation_error["code"], IsImmutableValidator.code)

def test_resultaattype_invalid_resource(self):
def test_resultaattype_bad_url(self):
zaak = ZaakFactory.create()
zaak_url = reverse("zaak-detail", kwargs={"uuid": zaak.uuid})
list_url = reverse("resultaat-list")
Expand All @@ -834,6 +878,20 @@ def test_resultaattype_invalid_resource(self):
validation_error = get_validation_errors(response, "resultaattype")
self.assertEqual(validation_error["code"], "bad-url")

def test_resultaattype_invalid_resource(self):
zaak = ZaakFactory.create()
zaak_url = reverse("zaak-detail", kwargs={"uuid": zaak.uuid})
list_url = reverse("resultaat-list")

response = self.client.post(
list_url, {"zaak": zaak_url, "resultaattype": "https://example.com"}
)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

validation_error = get_validation_errors(response, "resultaattype")
self.assertEqual(validation_error["code"], "invalid-resource")

def test_resultaattype_incorrect_zaaktype(self):
zaak = ZaakFactory.create()
zaak_url = reverse("zaak-detail", kwargs={"uuid": zaak.uuid})
Expand Down Expand Up @@ -921,6 +979,22 @@ def test_eigenschap_invalid_url(self):
validation_error = get_validation_errors(response, "eigenschap")
self.assertEqual(validation_error["code"], "bad-url")

def test_eigenschap_invalid_resource(self):
zaak = ZaakFactory.create()
zaak_url = reverse(zaak)

list_url = reverse("zaakeigenschap-list", kwargs={"zaak_uuid": zaak.uuid})

response = self.client.post(
list_url,
{"zaak": zaak_url, "eigenschap": "http://example.com", "waarde": "test"},
)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

validation_error = get_validation_errors(response, "eigenschap")
self.assertEqual(validation_error["code"], "invalid-resource")


class ZaakObjectValidationTests(JWTAuthMixin, APITestCase):
heeft_alle_autorisaties = True
Expand Down
29 changes: 18 additions & 11 deletions src/openzaak/utils/serializer_fields.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from django.utils.translation import ugettext_lazy as _

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from vng_api_common.validators import URLValidator


class LengthValidationMixin:
default_error_messages = {
"max_length": _("Ensure this field has no more than {max_length} characters."),
"min_length": _("Ensure this field has at least {min_length} characters."),
"bad-url": "Please provide a valid URL.",
"bad-url": "The URL {url} could not be fetched. Exception: {exc}",
"invalid-resource": "Please provide a valid URL. Exception: {exc}",
}

def __init__(self, **kwargs):
Expand All @@ -16,23 +19,27 @@ def __init__(self, **kwargs):

super().__init__(**kwargs)

def fail(self, key, **kwargs):
"""
Replace build-in 'no_match' error code with `bad-url` to make it consistent with
reference implementation
"""
if key == "no_match":
key = "bad-url"
super().fail(key, **kwargs)

def to_internal_value(self, data):
if self.max_length and len(data) > self.max_length:
self.fail("max_length", max_length=self.max_length, length=len(data))

if self.min_length and len(data) < self.min_length:
self.fail("min_length", max_length=self.min_length, length=len(data))

return super().to_internal_value(data)
# check if url is valid
try:
value = super().to_internal_value(data)
except ValidationError as field_exc:
# rewrite validation code to make it fit reference implementation
# if url is not valid
try:
URLValidator()(data)
except ValidationError as exc:
self.fail("bad-url", url=data, exc=exc)

# if the url is not bad -> then the problem is that it doesn't fit resource
self.fail("invalid-resource", exc=field_exc)
return value


class LengthHyperlinkedRelatedField(
Expand Down

0 comments on commit 2a73e22

Please sign in to comment.