Skip to content

Commit

Permalink
Merge pull request #50 from VNG-Realisatie/feature/bio-type-validator
Browse files Browse the repository at this point in the history
Feature/bio type validator
  • Loading branch information
sergei-maertens authored Nov 8, 2019
2 parents f160bad + 2ed02ca commit 56662de
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/brc/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

from .auth import get_drc_auth, get_zrc_auth, get_ztc_auth
from .validators import (
BesluittypeZaaktypeValidator,
ZaaktypeInformatieobjecttypeRelationValidator
BesluittypeInformatieobjecttypeRelationValidator,
BesluittypeZaaktypeValidator
)


Expand Down Expand Up @@ -113,7 +113,7 @@ class Meta:
queryset=BesluitInformatieObject.objects.all(),
fields=['besluit', 'informatieobject']
),
ZaaktypeInformatieobjecttypeRelationValidator("informatieobject"),
BesluittypeInformatieobjecttypeRelationValidator("informatieobject"),
]
extra_kwargs = {
'url': {
Expand Down
19 changes: 13 additions & 6 deletions src/brc/api/tests/test_audittrails.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
DRC_ROOT = 'https://example.com/drc/api/v1'
CATALOGUS = f'{ZTC_ROOT}/catalogus/878a3318-5950-4642-8715-189745f91b04'
INFORMATIE_OBJECT = f'{DRC_ROOT}/enkelvoudiginformatieobjecten/1234'
INFORMATIE_OBJECT_TYPE = f'{ZTC_ROOT}/informatieobjecttypen/1234'

ZAAK = 'https://zrc.com/zaken/1234'
ZAAKTYPE = f'{ZTC_ROOT}/zaaktypen/1234'
Expand All @@ -42,12 +43,17 @@ class AuditTrailTests(MockSyncMixin, JWTAuthMixin, APITestCase):
'productenOfDiensten': [
'https://example.com/product/123',
'https://example.com/dienst/123',
]
],
"informatieobjecttypen": [INFORMATIE_OBJECT_TYPE]
},
ZAAK: {
'url': ZAAK,
'zaaktype': ZAAKTYPE
}
},
INFORMATIE_OBJECT: {
'url': INFORMATIE_OBJECT,
'informatieobjecttype': INFORMATIE_OBJECT_TYPE,
},
}

@patch("vng_api_common.validators.fetcher")
Expand Down Expand Up @@ -135,10 +141,11 @@ def test_create_besluitinformatieobject_audittrail(self, *mocks):

url = reverse(BesluitInformatieObject)

response = self.client.post(url, {
'besluit': besluit_data['url'],
'informatieobject': INFORMATIE_OBJECT,
})
with mock_client(self.responses):
response = self.client.post(url, {
'besluit': besluit_data['url'],
'informatieobject': INFORMATIE_OBJECT,
})

besluitinformatieobject_response = response.data

Expand Down
35 changes: 25 additions & 10 deletions src/brc/api/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from rest_framework import status
from rest_framework.test import APITestCase
from vng_api_common.tests import AuthCheckMixin, JWTAuthMixin, reverse
from zds_client.tests.mocks import mock_client

from brc.datamodel.models import BesluitInformatieObject
from brc.datamodel.tests.factories import (
Expand All @@ -17,6 +18,21 @@
from ..scopes import SCOPE_BESLUITEN_AANMAKEN, SCOPE_BESLUITEN_ALLES_LEZEN
from .mixins import MockSyncMixin

INFORMATIEOBJECT = f'http://drc.com/api/v1/enkelvoudiginformatieobjecten/1234'
INFORMATIEOBJECTTYPE = 'https://ztc.com/informatieobjecttypen/1234'
BESLUITTYPE = 'https://ztc.com/besluittypen/1234'

RESPONSES = {
BESLUITTYPE: {
'url': BESLUITTYPE,
'informatieobjecttypen': [INFORMATIEOBJECTTYPE]
},
INFORMATIEOBJECT: {
'url': INFORMATIEOBJECT,
'informatieobjecttype': INFORMATIEOBJECTTYPE
}
}


@override_settings(ZDS_CLIENT_CLASS='vng_api_common.mocks.MockClient')
class BesluitScopeForbiddenTests(MockSyncMixin, AuthCheckMixin, APITestCase):
Expand Down Expand Up @@ -102,10 +118,10 @@ def test_read_superuser(self):
class BioReadTests(MockSyncMixin, JWTAuthMixin, APITestCase):

scopes = [SCOPE_BESLUITEN_ALLES_LEZEN, SCOPE_BESLUITEN_AANMAKEN]
besluittype = 'https://besluittype.nl/ok'
besluittype = BESLUITTYPE

def test_list_bio_limited_to_authorized_zaken(self):
besluit1 = BesluitFactory.create(besluittype='https://besluittype.nl/ok')
besluit1 = BesluitFactory.create(besluittype=BESLUITTYPE)
besluit2 = BesluitFactory.create(besluittype='https://besluittype.nl/not_ok')

url = reverse(BesluitInformatieObject)
Expand All @@ -126,12 +142,10 @@ def test_list_bio_limited_to_authorized_zaken(self):
besluit_url = reverse(bio1.besluit)
self.assertEqual(response_data[0]['besluit'], f'http://testserver{besluit_url}')

@patch("vng_api_common.validators.fetcher")
# @patch("vng_api_common.validators.fetcher")
@patch("vng_api_common.validators.obj_has_shape", return_value=True)
def test_create_bio_limited_to_authorized_besluiten(self, *mocks):
informatieobject = 'https://drc.com/api/v1/enkelvoudigeinformatieobjecten/1234'

besluit1 = BesluitFactory.create(besluittype='https://besluittype.nl/ok')
besluit1 = BesluitFactory.create(besluittype=BESLUITTYPE)
besluit2 = BesluitFactory.create(besluittype='https://besluittype.nl/not_ok')

besluit_uri1 = reverse(besluit1)
Expand All @@ -144,16 +158,17 @@ def test_create_bio_limited_to_authorized_besluiten(self, *mocks):
url2 = reverse('besluitinformatieobject-list')

data1 = {
'informatieobject': informatieobject,
'informatieobject': INFORMATIEOBJECT,
'besluit': besluit_url1
}
data2 = {
'informatieobject': informatieobject,
'informatieobject': INFORMATIEOBJECT,
'besluit': besluit_url2
}

response1 = self.client.post(url1, data1)
response2 = self.client.post(url2, data2)
with mock_client(RESPONSES):
response1 = self.client.post(url1, data1)
response2 = self.client.post(url2, data2)

self.assertEqual(response1.status_code, status.HTTP_201_CREATED, response1.data)
self.assertEqual(response2.status_code, status.HTTP_403_FORBIDDEN, response2.data)
44 changes: 25 additions & 19 deletions src/brc/api/tests/test_besluitinformatieobjecten.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
from unittest.mock import patch

from django.test import override_settings
from django.urls import reverse, reverse_lazy

from freezegun import freeze_time
from rest_framework import status
from rest_framework.test import APITestCase
from vng_api_common.tests import (
JWTAuthMixin, get_operation_url, get_validation_errors
JWTAuthMixin, get_operation_url, get_validation_errors, reverse,
reverse_lazy
)
from vng_api_common.validators import IsImmutableValidator
from zds_client.tests.mocks import mock_client

from brc.datamodel.models import Besluit, BesluitInformatieObject
from brc.datamodel.tests.factories import (
Expand All @@ -22,6 +22,19 @@
from .mixins import MockSyncMixin

INFORMATIEOBJECT = f'http://drc.com/api/v1/enkelvoudiginformatieobjecten/{uuid.uuid4().hex}'
INFORMATIEOBJECTTYPE = 'https://ztc.com/informatieobjecttypen/1234'
BESLUITTYPE = 'https://ztc.com/besluittypen/1234'

RESPONSES = {
BESLUITTYPE: {
'url': BESLUITTYPE,
'informatieobjecttypen': [INFORMATIEOBJECTTYPE]
},
INFORMATIEOBJECT: {
'url': INFORMATIEOBJECT,
'informatieobjecttype': INFORMATIEOBJECTTYPE
}
}


def dt_to_api(dt: datetime):
Expand All @@ -42,22 +55,18 @@ class BesluitInformatieObjectAPITests(MockSyncMixin, JWTAuthMixin, APITestCase):
heeft_alle_autorisaties = True

@freeze_time('2018-09-19T12:25:19+0200')
@patch("vng_api_common.validators.fetcher")
@patch("vng_api_common.validators.obj_has_shape", return_value=True)
def test_create(self, *mocks):
besluit = BesluitFactory.create()
besluit_url = reverse('besluit-detail', kwargs={
'version': '1',
'uuid': besluit.uuid,
})

besluit = BesluitFactory.create(besluittype=BESLUITTYPE)
besluit_url = reverse(besluit)
content = {
'informatieobject': INFORMATIEOBJECT,
'besluit': 'http://testserver' + besluit_url,
}

# Send to the API
response = self.client.post(self.list_url, content)
with mock_client(RESPONSES):
response = self.client.post(self.list_url, content)

# Test response
self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)
Expand All @@ -78,27 +87,24 @@ def test_create(self, *mocks):
})
self.assertEqual(response.json(), expected_response)

@patch("vng_api_common.validators.fetcher")
@patch("vng_api_common.validators.obj_has_shape", return_value=True)
def test_duplicate_object(self, *mocks):
"""
Test the (informatieobject, object) unique together validation.
"""
bio = BesluitInformatieObjectFactory.create(
informatieobject=INFORMATIEOBJECT
informatieobject=INFORMATIEOBJECT,
besluit__besluittype=BESLUITTYPE
)
besluit_url = reverse('besluit-detail', kwargs={
'version': '1',
'uuid': bio.besluit.uuid,
})

besluit_url = reverse(bio.besluit)
content = {
'informatieobject': bio.informatieobject,
'besluit': f'http://testserver{besluit_url}',
}

# Send to the API
response = self.client.post(self.list_url, content)
with mock_client(RESPONSES):
response = self.client.post(self.list_url, content)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.data)
error = get_validation_errors(response, 'nonFieldErrors')
Expand Down
12 changes: 5 additions & 7 deletions src/brc/api/tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ def test_zaak_invalid_resource(self, *mocks):
error = get_validation_errors(response, 'zaak')
self.assertEqual(error['code'], 'invalid-resource')


class BesluitInformatieObjectTests(BesluitSyncMixin, JWTAuthMixin, APITestCase):

heeft_alle_autorisaties = True
Expand Down Expand Up @@ -359,7 +360,7 @@ def test_validate_informatieobject_invalid_resource(self):
@override_settings(LINK_FETCHER='vng_api_common.mocks.link_fetcher_200')
@patch("vng_api_common.validators.fetcher")
@patch("vng_api_common.validators.obj_has_shape", return_value=True)
def test_validate_no_informatieobjecttype_zaaktype_relation(self, *mocks):
def test_validate_no_informatieobjecttype_besluittype_relation(self, *mocks):
besluit = BesluitFactory.create(besluittype=BESLUITTYPE, zaak=ZAAK)
besluit_url = reverse('besluit-detail', kwargs={'uuid': besluit.uuid})
url = reverse('besluitinformatieobject-list')
Expand All @@ -371,16 +372,13 @@ def test_validate_no_informatieobjecttype_zaaktype_relation(self, *mocks):
},
BESLUITTYPE: {
'url': BESLUITTYPE,
'zaaktypes': []
'zaaktypes': [],
'informatieobjecttypen': [],
},
INFORMATIEOBJECT: {
'url': INFORMATIEOBJECT,
'informatieobjecttype': INFORMATIEOBJECT_TYPE
},
ZAAKTYPE: {
'url': ZAAKTYPE,
'informatieobjecttypen': []
}
}

with mock_client(responses):
Expand All @@ -392,4 +390,4 @@ def test_validate_no_informatieobjecttype_zaaktype_relation(self, *mocks):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

error = get_validation_errors(response, 'nonFieldErrors')
self.assertEqual(error['code'], 'missing-zaaktype-informatieobjecttype-relation')
self.assertEqual(error['code'], 'missing-besluittype-informatieobjecttype-relation')
17 changes: 7 additions & 10 deletions src/brc/api/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def __call__(self, attrs):
raise serializers.ValidationError(self.message, code=self.code)


class ZaaktypeInformatieobjecttypeRelationValidator:
code = "missing-zaaktype-informatieobjecttype-relation"
message = _("Het informatieobjecttype hoort niet bij het zaaktype van de zaak.")
class BesluittypeInformatieobjecttypeRelationValidator:
code = "missing-besluittype-informatieobjecttype-relation"
message = _("Het informatieobjecttype hoort niet bij het besluitype van de besluit.")

def __init__(self, url_field: str, besluit_field: str = "besluit", resource: str = None):
self.url_field = url_field
Expand All @@ -64,10 +64,7 @@ def __call__(self, attrs):
if not informatieobject_url or not besluit:
return

# Only apply validation if the Besluit is linked to a Zaak
if besluit.zaak:
zaak = fetch_object('zaak', besluit.zaak)
zaaktype = fetch_object('zaaktype', zaak['zaaktype'])
informatieobject = fetch_object(self.resource, informatieobject_url)
if informatieobject['informatieobjecttype'] not in zaaktype['informatieobjecttypen']:
raise serializers.ValidationError(self.message, code=self.code)
besluittype = fetch_object('besluittype', besluit.besluittype)
informatieobject = fetch_object(self.resource, informatieobject_url)
if informatieobject['informatieobjecttype'] not in besluittype['informatieobjecttypen']:
raise serializers.ValidationError(self.message, code=self.code)
3 changes: 3 additions & 0 deletions src/brc/tests/test_create_besluit.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
'url': BESLUITTYPE,
'zaaktypes': [
ZAAKTYPE
],
'informatieobjecttypen': [
INFORMATIEOBJECTTYPE
]
},
ZAAK: {
Expand Down

0 comments on commit 56662de

Please sign in to comment.