From 22e47923c8fee69b1a227c35f6eca70b030d3fd9 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Fri, 24 Jan 2025 16:41:30 +0100 Subject: [PATCH 1/5] :sparkles: [#5016] Add Referentielijsten service select to builder and modify the services API endpoint to retrieve referentielijsten services based on a query parameter --- src/openapi.yaml | 14 +++++++++++ .../formio_builder/WebformBuilder.js | 2 ++ .../formio_builder/referentielijsten.js | 6 +++++ src/openforms/services/api/serializers.py | 1 + src/openforms/services/api/viewsets.py | 23 +++++++++++++++++-- src/openforms/services/tests/test_api_list.py | 19 +++++++++++++++ 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/openforms/js/components/formio_builder/referentielijsten.js diff --git a/src/openapi.yaml b/src/openapi.yaml index 709ecb96bd..733e98b40a 100644 --- a/src/openapi.yaml +++ b/src/openapi.yaml @@ -4167,6 +4167,12 @@ paths: Note that this endpoint is **EXPERIMENTAL**. summary: List available services + parameters: + - in: query + name: type + schema: + type: string + description: 'The type of Services to return, possible values: `referentielijsten`' tags: - services security: @@ -9723,6 +9729,13 @@ components: type: string format: uri readOnly: true + slug: + type: string + title: Service slug + description: A unique, human-friendly slug to identify this service. Primarily + useful for cross-instance import/export. + maxLength: 255 + pattern: ^[-a-zA-Z0-9_]+$ label: type: string maxLength: 100 @@ -9740,6 +9753,7 @@ components: - apiRoot - apiType - label + - slug - url x-experimental: true ServiceFetchConfiguration: diff --git a/src/openforms/js/components/formio_builder/WebformBuilder.js b/src/openforms/js/components/formio_builder/WebformBuilder.js index c48b1e2811..0c290c1dbf 100644 --- a/src/openforms/js/components/formio_builder/WebformBuilder.js +++ b/src/openforms/js/components/formio_builder/WebformBuilder.js @@ -24,6 +24,7 @@ import { getRegistrationAttributes, getValidatorPlugins, } from './plugins'; +import {getServices} from './referentielijsten'; let _supportedLanguages = undefined; const getSupportedLanguages = () => { @@ -167,6 +168,7 @@ class WebformBuilder extends WebformBuilderFormio { getFormComponents={() => this.webform.form.components} getValidatorPlugins={getValidatorPlugins} getRegistrationAttributes={getRegistrationAttributes} + getServices={getServices} getPrefillPlugins={getPrefillPlugins} getPrefillAttributes={getPrefillAttributes} getFileTypes={async () => FILE_TYPES} diff --git a/src/openforms/js/components/formio_builder/referentielijsten.js b/src/openforms/js/components/formio_builder/referentielijsten.js new file mode 100644 index 0000000000..fecb76c251 --- /dev/null +++ b/src/openforms/js/components/formio_builder/referentielijsten.js @@ -0,0 +1,6 @@ +import {get} from 'utils/fetch'; + +export const getServices = async type => { + const resp = await get(`/api/v2/services?type=${encodeURIComponent(type)}`); + return resp.data; +}; diff --git a/src/openforms/services/api/serializers.py b/src/openforms/services/api/serializers.py index ec49008bfe..71e55892aa 100644 --- a/src/openforms/services/api/serializers.py +++ b/src/openforms/services/api/serializers.py @@ -10,6 +10,7 @@ class Meta: model = Service fields = ( "url", + "slug", "label", "api_root", "api_type", diff --git a/src/openforms/services/api/viewsets.py b/src/openforms/services/api/viewsets.py index 2550955c08..2492378842 100644 --- a/src/openforms/services/api/viewsets.py +++ b/src/openforms/services/api/viewsets.py @@ -1,10 +1,11 @@ from django.utils.translation import gettext_lazy as _ -from drf_spectacular.utils import extend_schema, extend_schema_view +from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view from rest_framework import authentication, permissions, viewsets from zgw_consumers.models import Service from openforms.api.utils import mark_experimental +from openforms.config.models import GlobalConfiguration from . import serializers @@ -17,7 +18,18 @@ "in the backend.\n\n" "Note that this endpoint is **EXPERIMENTAL**." ), - ) + parameters=[ + OpenApiParameter( + name="type", + type=str, + location=OpenApiParameter.QUERY, + description=_( + "The type of Services to return, possible values: `referentielijsten`" + ), + required=False, + ) + ], + ), ) @mark_experimental class ServiceViewSet(viewsets.ReadOnlyModelViewSet): @@ -30,3 +42,10 @@ class ServiceViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.ServiceSerializer queryset = Service.objects.all() + + def get_queryset(self): + qs = super().get_queryset() + if self.request.query_params.get("type") == "referentielijsten": + config = GlobalConfiguration.get_solo() + return config.referentielijsten_services + return qs diff --git a/src/openforms/services/tests/test_api_list.py b/src/openforms/services/tests/test_api_list.py index 7ec386c2dd..7d729f58be 100644 --- a/src/openforms/services/tests/test_api_list.py +++ b/src/openforms/services/tests/test_api_list.py @@ -4,6 +4,7 @@ from zgw_consumers.test.factories import ServiceFactory from openforms.accounts.tests.factories import StaffUserFactory, UserFactory +from openforms.config.models import GlobalConfiguration class AccessControlTests(APITestCase): @@ -31,6 +32,24 @@ def test_service_list_returns_a_list_to_admin_users(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.json(), []) + def test_service_list_filter_by_referentielijsten(self): + config = GlobalConfiguration.get_solo() + config.referentielijsten_services.set( + [ServiceFactory.create(label="Referentielijsten", slug="referentielijsten")] + ) + config.save() + endpoint = reverse("api:service-list") + self.client.force_authenticate(user=self.admin_user) + + response = self.client.get(endpoint, {"type": "referentielijsten"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + services = response.json() + + self.assertEqual(len(services), 1) + self.assertEqual(services[0]["slug"], "referentielijsten") + def test_returned_services_have_the_right_properties(self): expected_service = ServiceFactory.create() endpoint = reverse("api:service-list") From 40da627462b4d90e8bc4d0c3b2a391eb0da76ed4 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Mon, 3 Feb 2025 09:24:40 +0100 Subject: [PATCH 2/5] :sparkles: [#5016] Add endpoint for referentielijst tabellen this endpoint is used by the formio builder to populate the select widget with tabellen to populate select/selectboxes/radio component options from --- src/openapi.yaml | 62 +++++++++++++++++++ src/openforms/api/urls.py | 10 +++ .../contrib/referentielijsten/api/__init__.py | 0 .../referentielijsten/api/serializers.py | 29 +++++++++ .../contrib/referentielijsten/api/viewsets.py | 55 ++++++++++++++++ .../contrib/referentielijsten/client.py | 21 +++++++ .../formio_builder/WebformBuilder.js | 3 +- .../formio_builder/referentielijsten.js | 5 ++ 8 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 src/openforms/contrib/referentielijsten/api/__init__.py create mode 100644 src/openforms/contrib/referentielijsten/api/serializers.py create mode 100644 src/openforms/contrib/referentielijsten/api/viewsets.py diff --git a/src/openapi.yaml b/src/openapi.yaml index 733e98b40a..0df897a580 100644 --- a/src/openapi.yaml +++ b/src/openapi.yaml @@ -3715,6 +3715,44 @@ paths: $ref: '#/components/headers/X-Is-Form-Designer' Content-Language: $ref: '#/components/headers/Content-Language' + /api/v2/referentielijst-tabellen/{service_slug}: + get: + operationId: referentielijst_tabellen_list + description: |- + Return a list of available (JSON) tabellen in a given Referentielijsten service configured in the backend. + + Note that this endpoint is **EXPERIMENTAL**. + summary: List tabellen for a Referentielijsten service + parameters: + - in: path + name: service_slug + schema: + type: string + pattern: ^[-a-zA-Z0-9_]+$ + required: true + tags: + - referentielijst-tabellen + security: + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ReferentielijstTabellen' + description: '' + headers: + X-Session-Expires-In: + $ref: '#/components/headers/X-Session-Expires-In' + X-CSRFToken: + $ref: '#/components/headers/X-CSRFToken' + X-Is-Form-Designer: + $ref: '#/components/headers/X-Is-Form-Designer' + Content-Language: + $ref: '#/components/headers/Content-Language' + x-experimental: true /api/v2/registration/attributes: get: operationId: registration_attributes_list @@ -9657,6 +9695,30 @@ components: required: - name - slug + ReferentielijstTabellen: + type: object + properties: + code: + type: string + description: The unique code that identifies the table. + naam: + type: string + description: The name of the table. + einddatumGeldigheid: + type: string + format: date-time + writeOnly: true + description: The timestamp on which the tabel expires. + isGeldig: + type: boolean + readOnly: true + description: Indicates whether or not the table is expired. + required: + - code + - einddatumGeldigheid + - isGeldig + - naam + x-experimental: true RegistrationAttribute: type: object properties: diff --git a/src/openforms/api/urls.py b/src/openforms/api/urls.py index 286d637ea8..9ba9b8337e 100644 --- a/src/openforms/api/urls.py +++ b/src/openforms/api/urls.py @@ -10,6 +10,9 @@ from rest_framework_nested.routers import NestedSimpleRouter from openforms.config.api.viewsets import ThemeViewSet +from openforms.contrib.referentielijsten.api.viewsets import ( + ReferentielijstenTabellenViewSet, +) from openforms.forms.api.public_api.viewsets import CategoryViewSet from openforms.forms.api.viewsets import ( FormDefinitionViewSet, @@ -60,6 +63,13 @@ # services router.register("services", ServiceViewSet) +# referentielijsten +router.register( + "referentielijst-tabellen", + ReferentielijstenTabellenViewSet, + basename="referentielijst-tabellen", +) + # service fetch configurations router.register("service-fetch-configurations", ServiceFetchConfigurationViewSet) diff --git a/src/openforms/contrib/referentielijsten/api/__init__.py b/src/openforms/contrib/referentielijsten/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/openforms/contrib/referentielijsten/api/serializers.py b/src/openforms/contrib/referentielijsten/api/serializers.py new file mode 100644 index 0000000000..208518d9a1 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/api/serializers.py @@ -0,0 +1,29 @@ +from datetime import datetime + +from django.utils.translation import gettext_lazy as _ + +from rest_framework import serializers + +from openforms.api.utils import mark_experimental + + +@mark_experimental +class ReferentielijstTabellenSerializer(serializers.Serializer): + code = serializers.CharField( + help_text=_("The unique code that identifies the table.") + ) + naam = serializers.CharField(help_text=_("The name of the table.")) + einddatumGeldigheid = serializers.DateTimeField( + help_text=_("The timestamp on which the tabel expires."), write_only=True + ) + + is_geldig = serializers.SerializerMethodField( + help_text=_("Indicates whether or not the table is expired.") + ) + + def get_is_geldig(self, attrs: dict) -> bool: + if einddatum := attrs.get("einddatumGeldigheid"): + parsed_datetime = datetime.fromisoformat(einddatum) + if parsed_datetime < datetime.now(tz=parsed_datetime.tzinfo): + return False + return True diff --git a/src/openforms/contrib/referentielijsten/api/viewsets.py b/src/openforms/contrib/referentielijsten/api/viewsets.py new file mode 100644 index 0000000000..b4f2994910 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/api/viewsets.py @@ -0,0 +1,55 @@ +from django.shortcuts import get_object_or_404 +from django.utils.translation import gettext_lazy as _ + +from drf_spectacular.utils import extend_schema, extend_schema_view +from requests.exceptions import RequestException +from rest_framework import authentication, permissions, serializers, status, viewsets +from rest_framework.decorators import action +from rest_framework.response import Response +from zgw_consumers.client import build_client +from zgw_consumers.models import Service + +from openforms.api.utils import mark_experimental + +from ..client import ReferentielijstenClient +from .serializers import ReferentielijstTabellenSerializer + + +@extend_schema_view( + get=extend_schema( + summary=_("List tabellen for a Referentielijsten service"), + description=_( + "Return a list of available (JSON) tabellen in a given Referentielijsten service configured " + "in the backend.\n\n" + "Note that this endpoint is **EXPERIMENTAL**." + ), + responses={ + 200: ReferentielijstTabellenSerializer(many=True), + }, + ) +) +@mark_experimental +class ReferentielijstenTabellenViewSet(viewsets.ViewSet): + """ + List tabellen for a given Referentielijst service + """ + + authentication_classes = (authentication.SessionAuthentication,) + permission_classes = (permissions.IsAdminUser,) + serializer_class = ReferentielijstTabellenSerializer + + @action(detail=False, methods=["get"], url_path="(?P[-a-zA-Z0-9_]+)") + def get(self, request, service_slug: str | None = None): + service = get_object_or_404(Service, slug=service_slug) + try: + with build_client( + service, client_factory=ReferentielijstenClient + ) as client: + result = client.get_tabellen() + except RequestException: + result = [] + + assert issubclass(self.serializer_class, serializers.Serializer) + serializer = self.serializer_class(data=result, many=True) + serializer.is_valid() + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/src/openforms/contrib/referentielijsten/client.py b/src/openforms/contrib/referentielijsten/client.py index edf492bc87..12b8bc6d51 100644 --- a/src/openforms/contrib/referentielijsten/client.py +++ b/src/openforms/contrib/referentielijsten/client.py @@ -17,7 +17,28 @@ class TabelItem(TypedDict): aanvullendeGegevens: Any +class Beheerder(TypedDict): + naam: str + email: str + afdeling: str + organisatie: str + + +class Tabel(TypedDict): + code: str + naam: str + beheerder: Beheerder + einddatumGeldigheid: str | None # ISO 8601 datetime string + + class ReferentielijstenClient(APIClient): + def get_tabellen(self) -> list[Tabel]: + response = self.get("tabellen", timeout=10) + response.raise_for_status() + data = response.json() + all_data = list(pagination_helper(self, data)) + return all_data + def get_items_for_tabel(self, code: str) -> list[TabelItem]: response = self.get("items", params={"tabel__code": code}, timeout=10) response.raise_for_status() diff --git a/src/openforms/js/components/formio_builder/WebformBuilder.js b/src/openforms/js/components/formio_builder/WebformBuilder.js index 0c290c1dbf..3cd1b1b55e 100644 --- a/src/openforms/js/components/formio_builder/WebformBuilder.js +++ b/src/openforms/js/components/formio_builder/WebformBuilder.js @@ -24,7 +24,7 @@ import { getRegistrationAttributes, getValidatorPlugins, } from './plugins'; -import {getServices} from './referentielijsten'; +import {getReferentielijstenTabellen, getServices} from './referentielijsten'; let _supportedLanguages = undefined; const getSupportedLanguages = () => { @@ -169,6 +169,7 @@ class WebformBuilder extends WebformBuilderFormio { getValidatorPlugins={getValidatorPlugins} getRegistrationAttributes={getRegistrationAttributes} getServices={getServices} + getReferentielijstenTabellen={getReferentielijstenTabellen} getPrefillPlugins={getPrefillPlugins} getPrefillAttributes={getPrefillAttributes} getFileTypes={async () => FILE_TYPES} diff --git a/src/openforms/js/components/formio_builder/referentielijsten.js b/src/openforms/js/components/formio_builder/referentielijsten.js index fecb76c251..b9a4bab578 100644 --- a/src/openforms/js/components/formio_builder/referentielijsten.js +++ b/src/openforms/js/components/formio_builder/referentielijsten.js @@ -4,3 +4,8 @@ export const getServices = async type => { const resp = await get(`/api/v2/services?type=${encodeURIComponent(type)}`); return resp.data; }; + +export const getReferentielijstenTabellen = async service => { + const resp = await get(`/api/v2/referentielijst-tabellen/${service}`); + return resp.data; +}; From e58f4086fd202058eb61b0a55629cf31c34b531c Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Mon, 3 Feb 2025 15:25:32 +0100 Subject: [PATCH 3/5] :white_check_mark: [#5016] Tests for referentielijst tabellen endpoint and update docker fixtures for Referentielijsten API --- docker/docker-compose.referentielijsten.yml | 2 +- .../fixtures/referentielijsten_fixtures.json | 1240 ++++++++++++++++- .../referentielijsten/tests/__init__.py | 0 ...est_referentielijsten_api_returns_404.yaml | 77 + ...ed_tabellen_have_the_right_properties.yaml | 49 + .../tests/test_tabellen_list.py | 93 ++ 6 files changed, 1459 insertions(+), 2 deletions(-) create mode 100644 src/openforms/contrib/referentielijsten/tests/__init__.py create mode 100644 src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_referentielijsten_api_returns_404.yaml create mode 100644 src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_returned_tabellen_have_the_right_properties.yaml create mode 100644 src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py diff --git a/docker/docker-compose.referentielijsten.yml b/docker/docker-compose.referentielijsten.yml index f95e1912ff..0520f90862 100644 --- a/docker/docker-compose.referentielijsten.yml +++ b/docker/docker-compose.referentielijsten.yml @@ -20,7 +20,7 @@ services: - open-forms-dev referentielijsten-web.local: - image: maykinmedia/referentielijsten-api:${REFERENTIELIJSTEN_VERSION:-0.2.0} + image: maykinmedia/referentielijsten-api:${REFERENTIELIJSTEN_VERSION:-latest} environment: &referentielijsten_web_env - DJANGO_SETTINGS_MODULE=referentielijsten.conf.docker - SECRET_KEY=${SECRET_KEY:-7&3f^bo1(-5($bre4iv-!nt%1xr!b54b&y7+97j5f&ndm_e=lz} diff --git a/docker/referentielijsten/fixtures/referentielijsten_fixtures.json b/docker/referentielijsten/fixtures/referentielijsten_fixtures.json index a3a5a74f50..904fe588ed 100644 --- a/docker/referentielijsten/fixtures/referentielijsten_fixtures.json +++ b/docker/referentielijsten/fixtures/referentielijsten_fixtures.json @@ -4,7 +4,7 @@ "pk": 1, "fields": { "password": "pbkdf2_sha256$600000$DCgCQRA6R57PicaatiWGHU$S65r6Yedgkfv/exr8gFZogpyuCgortmrloq7+LBdnyY=", - "last_login": "2025-01-07T14:17:06.242Z", + "last_login": "2025-02-03T08:48:13.944Z", "is_superuser": true, "username": "admin", "first_name": "", @@ -30,6 +30,32 @@ "beheerder_organisatie": "" } }, +{ + "model": "api.tabel", + "pk": 2, + "fields": { + "code": "tabel-with-many-items", + "naam": "Tabel with many items", + "einddatum_geldigheid": null, + "beheerder_naam": "", + "beheerder_email": "", + "beheerder_afdeling": "", + "beheerder_organisatie": "" + } +}, +{ + "model": "api.tabel", + "pk": 3, + "fields": { + "code": "not-geldig-anymore", + "naam": "Tabel that is not geldig anymore", + "einddatum_geldigheid": "2020-02-03T08:48:49Z", + "beheerder_naam": "", + "beheerder_email": "", + "beheerder_afdeling": "", + "beheerder_organisatie": "" + } +}, { "model": "api.item", "pk": 1, @@ -53,5 +79,1217 @@ "einddatum_geldigheid": null, "aanvullende_gegevens": null } +}, +{ + "model": "api.item", + "pk": 3, + "fields": { + "tabel": 2, + "code": "0", + "naam": "0", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 4, + "fields": { + "tabel": 2, + "code": "1", + "naam": "1", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 5, + "fields": { + "tabel": 2, + "code": "2", + "naam": "2", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 6, + "fields": { + "tabel": 2, + "code": "3", + "naam": "3", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 7, + "fields": { + "tabel": 2, + "code": "4", + "naam": "4", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 8, + "fields": { + "tabel": 2, + "code": "5", + "naam": "5", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 9, + "fields": { + "tabel": 2, + "code": "6", + "naam": "6", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 10, + "fields": { + "tabel": 2, + "code": "7", + "naam": "7", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 11, + "fields": { + "tabel": 2, + "code": "8", + "naam": "8", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 12, + "fields": { + "tabel": 2, + "code": "9", + "naam": "9", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 13, + "fields": { + "tabel": 2, + "code": "10", + "naam": "10", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 14, + "fields": { + "tabel": 2, + "code": "11", + "naam": "11", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 15, + "fields": { + "tabel": 2, + "code": "12", + "naam": "12", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 16, + "fields": { + "tabel": 2, + "code": "13", + "naam": "13", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 17, + "fields": { + "tabel": 2, + "code": "14", + "naam": "14", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 18, + "fields": { + "tabel": 2, + "code": "15", + "naam": "15", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 19, + "fields": { + "tabel": 2, + "code": "16", + "naam": "16", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 20, + "fields": { + "tabel": 2, + "code": "17", + "naam": "17", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 21, + "fields": { + "tabel": 2, + "code": "18", + "naam": "18", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 22, + "fields": { + "tabel": 2, + "code": "19", + "naam": "19", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 23, + "fields": { + "tabel": 2, + "code": "20", + "naam": "20", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 24, + "fields": { + "tabel": 2, + "code": "21", + "naam": "21", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 25, + "fields": { + "tabel": 2, + "code": "22", + "naam": "22", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 26, + "fields": { + "tabel": 2, + "code": "23", + "naam": "23", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 27, + "fields": { + "tabel": 2, + "code": "24", + "naam": "24", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 28, + "fields": { + "tabel": 2, + "code": "25", + "naam": "25", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 29, + "fields": { + "tabel": 2, + "code": "26", + "naam": "26", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 30, + "fields": { + "tabel": 2, + "code": "27", + "naam": "27", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 31, + "fields": { + "tabel": 2, + "code": "28", + "naam": "28", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 32, + "fields": { + "tabel": 2, + "code": "29", + "naam": "29", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 33, + "fields": { + "tabel": 2, + "code": "30", + "naam": "30", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 34, + "fields": { + "tabel": 2, + "code": "31", + "naam": "31", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 35, + "fields": { + "tabel": 2, + "code": "32", + "naam": "32", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 36, + "fields": { + "tabel": 2, + "code": "33", + "naam": "33", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 37, + "fields": { + "tabel": 2, + "code": "34", + "naam": "34", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 38, + "fields": { + "tabel": 2, + "code": "35", + "naam": "35", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 39, + "fields": { + "tabel": 2, + "code": "36", + "naam": "36", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 40, + "fields": { + "tabel": 2, + "code": "37", + "naam": "37", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 41, + "fields": { + "tabel": 2, + "code": "38", + "naam": "38", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 42, + "fields": { + "tabel": 2, + "code": "39", + "naam": "39", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 43, + "fields": { + "tabel": 2, + "code": "40", + "naam": "40", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 44, + "fields": { + "tabel": 2, + "code": "41", + "naam": "41", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 45, + "fields": { + "tabel": 2, + "code": "42", + "naam": "42", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 46, + "fields": { + "tabel": 2, + "code": "43", + "naam": "43", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 47, + "fields": { + "tabel": 2, + "code": "44", + "naam": "44", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 48, + "fields": { + "tabel": 2, + "code": "45", + "naam": "45", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 49, + "fields": { + "tabel": 2, + "code": "46", + "naam": "46", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 50, + "fields": { + "tabel": 2, + "code": "47", + "naam": "47", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 51, + "fields": { + "tabel": 2, + "code": "48", + "naam": "48", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 52, + "fields": { + "tabel": 2, + "code": "49", + "naam": "49", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 53, + "fields": { + "tabel": 2, + "code": "50", + "naam": "50", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 54, + "fields": { + "tabel": 2, + "code": "51", + "naam": "51", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 55, + "fields": { + "tabel": 2, + "code": "52", + "naam": "52", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 56, + "fields": { + "tabel": 2, + "code": "53", + "naam": "53", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 57, + "fields": { + "tabel": 2, + "code": "54", + "naam": "54", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 58, + "fields": { + "tabel": 2, + "code": "55", + "naam": "55", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 59, + "fields": { + "tabel": 2, + "code": "56", + "naam": "56", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 60, + "fields": { + "tabel": 2, + "code": "57", + "naam": "57", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 61, + "fields": { + "tabel": 2, + "code": "58", + "naam": "58", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 62, + "fields": { + "tabel": 2, + "code": "59", + "naam": "59", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 63, + "fields": { + "tabel": 2, + "code": "60", + "naam": "60", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 64, + "fields": { + "tabel": 2, + "code": "61", + "naam": "61", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 65, + "fields": { + "tabel": 2, + "code": "62", + "naam": "62", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 66, + "fields": { + "tabel": 2, + "code": "63", + "naam": "63", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 67, + "fields": { + "tabel": 2, + "code": "64", + "naam": "64", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 68, + "fields": { + "tabel": 2, + "code": "65", + "naam": "65", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 69, + "fields": { + "tabel": 2, + "code": "66", + "naam": "66", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 70, + "fields": { + "tabel": 2, + "code": "67", + "naam": "67", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 71, + "fields": { + "tabel": 2, + "code": "68", + "naam": "68", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 72, + "fields": { + "tabel": 2, + "code": "69", + "naam": "69", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 73, + "fields": { + "tabel": 2, + "code": "70", + "naam": "70", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 74, + "fields": { + "tabel": 2, + "code": "71", + "naam": "71", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 75, + "fields": { + "tabel": 2, + "code": "72", + "naam": "72", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 76, + "fields": { + "tabel": 2, + "code": "73", + "naam": "73", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 77, + "fields": { + "tabel": 2, + "code": "74", + "naam": "74", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 78, + "fields": { + "tabel": 2, + "code": "75", + "naam": "75", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 79, + "fields": { + "tabel": 2, + "code": "76", + "naam": "76", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 80, + "fields": { + "tabel": 2, + "code": "77", + "naam": "77", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 81, + "fields": { + "tabel": 2, + "code": "78", + "naam": "78", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 82, + "fields": { + "tabel": 2, + "code": "79", + "naam": "79", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 83, + "fields": { + "tabel": 2, + "code": "80", + "naam": "80", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 84, + "fields": { + "tabel": 2, + "code": "81", + "naam": "81", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 85, + "fields": { + "tabel": 2, + "code": "82", + "naam": "82", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 86, + "fields": { + "tabel": 2, + "code": "83", + "naam": "83", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 87, + "fields": { + "tabel": 2, + "code": "84", + "naam": "84", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 88, + "fields": { + "tabel": 2, + "code": "85", + "naam": "85", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 89, + "fields": { + "tabel": 2, + "code": "86", + "naam": "86", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 90, + "fields": { + "tabel": 2, + "code": "87", + "naam": "87", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 91, + "fields": { + "tabel": 2, + "code": "88", + "naam": "88", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 92, + "fields": { + "tabel": 2, + "code": "89", + "naam": "89", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 93, + "fields": { + "tabel": 2, + "code": "90", + "naam": "90", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 94, + "fields": { + "tabel": 2, + "code": "91", + "naam": "91", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 95, + "fields": { + "tabel": 2, + "code": "92", + "naam": "92", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 96, + "fields": { + "tabel": 2, + "code": "93", + "naam": "93", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 97, + "fields": { + "tabel": 2, + "code": "94", + "naam": "94", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 98, + "fields": { + "tabel": 2, + "code": "95", + "naam": "95", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 99, + "fields": { + "tabel": 2, + "code": "96", + "naam": "96", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 100, + "fields": { + "tabel": 2, + "code": "97", + "naam": "97", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 101, + "fields": { + "tabel": 2, + "code": "98", + "naam": "98", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 102, + "fields": { + "tabel": 2, + "code": "99", + "naam": "99", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } +}, +{ + "model": "api.item", + "pk": 103, + "fields": { + "tabel": 2, + "code": "100", + "naam": "100", + "begindatum_geldigheid": null, + "einddatum_geldigheid": null, + "aanvullende_gegevens": null + } } ] diff --git a/src/openforms/contrib/referentielijsten/tests/__init__.py b/src/openforms/contrib/referentielijsten/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_referentielijsten_api_returns_404.yaml b/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_referentielijsten_api_returns_404.yaml new file mode 100644 index 0000000000..9809784149 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_referentielijsten_api_returns_404.yaml @@ -0,0 +1,77 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIiLCJpYXQiOjE3Mzg1NzkyMDIsImNsaWVudF9pZCI6IiIsInVzZXJfaWQiOiIiLCJ1c2VyX3JlcHJlc2VudGF0aW9uIjoiIn0.89Fz5WVphhmfDZILaKBym5ZcIKQkx1ECFZ_z85pBCxo + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.2 + method: GET + uri: http://localhost:8004/incorrect/tabellen + response: + body: + string: "\n\n \n + \ \n Referentielijsten\n + \ \n + \ \n \n \n \n \n \n \n \n\n \n + \
\n \n\n

Sorry, the requested page could not + be found (404)

\n\n\n\n
\n\n \n \n \n + \ \n\n" + headers: + Content-Length: + - '2864' + Content-Security-Policy: + - 'worker-src ''self'' blob:; font-src ''self'' fonts.gstatic.com; default-src + ''self''; object-src ''none''; frame-ancestors ''none''; img-src ''self'' + data: cdn.redoc.ly; base-uri ''self''; style-src ''self'' ''unsafe-inline'' + fonts.googleapis.com; form-action ''self''; frame-src ''self''; script-src + ''self'' ''unsafe-inline''' + Content-Type: + - text/html; charset=utf-8 + Cross-Origin-Opener-Policy: + - same-origin + Referrer-Policy: + - same-origin + Vary: + - origin, Cookie + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + status: + code: 404 + message: Not Found +version: 1 diff --git a/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_returned_tabellen_have_the_right_properties.yaml b/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_returned_tabellen_have_the_right_properties.yaml new file mode 100644 index 0000000000..2565de7146 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/tests/files/vcr_cassettes/ReferentielijstTabellenEndpointTests/ReferentielijstTabellenEndpointTests.test_returned_tabellen_have_the_right_properties.yaml @@ -0,0 +1,49 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Authorization: + - Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIiLCJpYXQiOjE3Mzg1NzkyMDIsImNsaWVudF9pZCI6IiIsInVzZXJfaWQiOiIiLCJ1c2VyX3JlcHJlc2VudGF0aW9uIjoiIn0.89Fz5WVphhmfDZILaKBym5ZcIKQkx1ECFZ_z85pBCxo + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.2 + method: GET + uri: http://localhost:8004/api/v1/tabellen + response: + body: + string: '{"count":3,"next":null,"previous":null,"results":[{"code":"not-geldig-anymore","naam":"Tabel + that is not geldig anymore","beheerder":{"naam":"","email":"","afdeling":"","organisatie":""},"einddatumGeldigheid":"2020-02-03T08:48:49Z"},{"code":"tabel-with-many-items","naam":"Tabel + with many items","beheerder":{"naam":"","email":"","afdeling":"","organisatie":""},"einddatumGeldigheid":null},{"code":"tabel1","naam":"Tabel1","beheerder":{"naam":"John + Doe","email":"john@doe.nl","afdeling":"","organisatie":""},"einddatumGeldigheid":"2025-04-11T13:02:25Z"}]}' + headers: + Allow: + - GET, HEAD, OPTIONS + Content-Length: + - '555' + Content-Security-Policy: + - 'worker-src ''self'' blob:; font-src ''self'' fonts.gstatic.com; default-src + ''self''; object-src ''none''; frame-ancestors ''none''; img-src ''self'' + data: cdn.redoc.ly; base-uri ''self''; style-src ''self'' ''unsafe-inline'' + fonts.googleapis.com; form-action ''self''; frame-src ''self''; script-src + ''self'' ''unsafe-inline''' + Content-Type: + - application/json + Cross-Origin-Opener-Policy: + - same-origin + Referrer-Policy: + - same-origin + Vary: + - origin + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + status: + code: 200 + message: OK +version: 1 diff --git a/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py b/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py new file mode 100644 index 0000000000..a24b8e2302 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py @@ -0,0 +1,93 @@ +from pathlib import Path + +from rest_framework import status +from rest_framework.reverse import reverse +from rest_framework.test import APITestCase +from zgw_consumers.test.factories import ServiceFactory + +from openforms.accounts.tests.factories import StaffUserFactory, UserFactory +from openforms.utils.tests.vcr import OFVCRMixin + +TESTS_DIR = Path(__file__).parent.resolve() +TEST_FILES = TESTS_DIR / "files" + + +class ReferentielijstTabellenEndpointTests(OFVCRMixin, APITestCase): + VCR_TEST_FILES = TEST_FILES + + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + cls.user = UserFactory.create() + cls.admin_user = StaffUserFactory.create() + + cls.service = ServiceFactory.create( + slug="referentielijsten", api_root="http://localhost:8004/api/v1/" + ) + + def test_tabellen_list_is_forbidden_for_normal_users(self): + endpoint = reverse( + "api:referentielijst-tabellen-get", + kwargs={"service_slug": "referentielijsten"}, + ) + self.client.force_authenticate(user=self.user) + + response = self.client.get(endpoint) + + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_returned_tabellen_have_the_right_properties(self): + endpoint = reverse( + "api:referentielijst-tabellen-get", + kwargs={"service_slug": "referentielijsten"}, + ) + self.client.force_authenticate(user=self.admin_user) + + response = self.client.get(endpoint) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + tabellen = response.json() + + self.assertEqual( + tabellen, + [ + { + "code": "not-geldig-anymore", + "naam": "Tabel that is not geldig anymore", + "isGeldig": False, + }, + { + "code": "tabel-with-many-items", + "naam": "Tabel with many items", + "isGeldig": True, + }, + {"code": "tabel1", "naam": "Tabel1", "isGeldig": True}, + ], + ) + + def test_service_not_found(self): + endpoint = reverse( + "api:referentielijst-tabellen-get", kwargs={"service_slug": "non-existent"} + ) + self.client.force_authenticate(user=self.admin_user) + + response = self.client.get(endpoint) + + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_referentielijsten_api_returns_404(self): + ServiceFactory.create( + slug="incorrect-api-root", api_root="http://localhost:8004/incorrect/" + ) + endpoint = reverse( + "api:referentielijst-tabellen-get", + kwargs={"service_slug": "incorrect-api-root"}, + ) + self.client.force_authenticate(user=self.admin_user) + + response = self.client.get(endpoint) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.json(), []) From 055d7116cc09985da07c945bd785356fdc854a79 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Thu, 6 Feb 2025 15:53:57 +0100 Subject: [PATCH 4/5] :arrow_up: [#5016] Upgrade formio-builder to 0.37.0 --- package-lock.json | 15 +++++++-------- package.json | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index a8ff5f5dda..2838fb1382 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.1.1", "@open-formulieren/design-tokens": "^0.53.0", - "@open-formulieren/formio-builder": "^0.35.0", + "@open-formulieren/formio-builder": "^0.37.0", "@open-formulieren/leaflet-tools": "^1.0.0", "@open-formulieren/monaco-json-editor": "^0.2.0", "@tinymce/tinymce-react": "^4.3.2", @@ -4498,11 +4498,10 @@ "integrity": "sha512-3Pv32ULCuFOJZ2GaqcpvB45u6xScr0lmW5ETB9P1Ox9TG5nvMcVSwuwYe/GwxbzmvtZgiMQRMKRFT9lNYLeREQ==" }, "node_modules/@open-formulieren/formio-builder": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/formio-builder/-/formio-builder-0.35.0.tgz", - "integrity": "sha512-/qu3BgbqLnIE/YUpP7sjbI/p/xtZbMOLBNyFzUEdZbEM6st4a3vCC0A7xAb8uGFbl67qLOwunUN4Te0D6VsorA==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/formio-builder/-/formio-builder-0.37.0.tgz", + "integrity": "sha512-EnaDJk0lC7yC8iq1Z3HnpUYGYwnqmBmz4Fq1FzIwDnIKxr9BKUnNvmRYhbWIuz6XXNG5NDPsm2a3b60t0OQz9w==", "hasInstallScript": true, - "license": "EUPL-1.2", "dependencies": { "@ckeditor/ckeditor5-react": "^6.2.0", "@floating-ui/react": "^0.26.4", @@ -21524,9 +21523,9 @@ "integrity": "sha512-3Pv32ULCuFOJZ2GaqcpvB45u6xScr0lmW5ETB9P1Ox9TG5nvMcVSwuwYe/GwxbzmvtZgiMQRMKRFT9lNYLeREQ==" }, "@open-formulieren/formio-builder": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/formio-builder/-/formio-builder-0.35.0.tgz", - "integrity": "sha512-/qu3BgbqLnIE/YUpP7sjbI/p/xtZbMOLBNyFzUEdZbEM6st4a3vCC0A7xAb8uGFbl67qLOwunUN4Te0D6VsorA==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/formio-builder/-/formio-builder-0.37.0.tgz", + "integrity": "sha512-EnaDJk0lC7yC8iq1Z3HnpUYGYwnqmBmz4Fq1FzIwDnIKxr9BKUnNvmRYhbWIuz6XXNG5NDPsm2a3b60t0OQz9w==", "requires": { "@ckeditor/ckeditor5-react": "^6.2.0", "@floating-ui/react": "^0.26.4", diff --git a/package.json b/package.json index bdd3f5227d..23e89b8394 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.1.1", "@open-formulieren/design-tokens": "^0.53.0", - "@open-formulieren/formio-builder": "^0.35.0", + "@open-formulieren/formio-builder": "^0.37.0", "@open-formulieren/leaflet-tools": "^1.0.0", "@open-formulieren/monaco-json-editor": "^0.2.0", "@tinymce/tinymce-react": "^4.3.2", From 67483fe979b2e3bde09722e2c00bfbdaddf268ba Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Thu, 6 Feb 2025 17:08:27 +0100 Subject: [PATCH 5/5] :ok_hand: [#5016] Process PR feedback --- src/openapi.yaml | 13 ++---- src/openforms/api/urls.py | 12 +++--- src/openforms/api/utils.py | 9 +++- .../referentielijsten/api/serializers.py | 4 -- .../contrib/referentielijsten/api/viewsets.py | 41 +++++++------------ .../tests/test_tabellen_list.py | 8 ++-- .../formio_builder/referentielijsten.js | 2 +- src/openforms/services/api/viewsets.py | 5 +-- 8 files changed, 38 insertions(+), 56 deletions(-) diff --git a/src/openapi.yaml b/src/openapi.yaml index 0df897a580..4084d36b17 100644 --- a/src/openapi.yaml +++ b/src/openapi.yaml @@ -3719,7 +3719,7 @@ paths: get: operationId: referentielijst_tabellen_list description: |- - Return a list of available (JSON) tabellen in a given Referentielijsten service configured in the backend. + Return a list of available tabellen in a given Referentielijsten service configured in the backend. Note that this endpoint is **EXPERIMENTAL**. summary: List tabellen for a Referentielijsten service @@ -3728,7 +3728,6 @@ paths: name: service_slug schema: type: string - pattern: ^[-a-zA-Z0-9_]+$ required: true tags: - referentielijst-tabellen @@ -4210,7 +4209,9 @@ paths: name: type schema: type: string - description: 'The type of Services to return, possible values: `referentielijsten`' + enum: + - referentielijsten + description: The type of Services to return tags: - services security: @@ -9704,18 +9705,12 @@ components: naam: type: string description: The name of the table. - einddatumGeldigheid: - type: string - format: date-time - writeOnly: true - description: The timestamp on which the tabel expires. isGeldig: type: boolean readOnly: true description: Indicates whether or not the table is expired. required: - code - - einddatumGeldigheid - isGeldig - naam x-experimental: true diff --git a/src/openforms/api/urls.py b/src/openforms/api/urls.py index 9ba9b8337e..5aa0982187 100644 --- a/src/openforms/api/urls.py +++ b/src/openforms/api/urls.py @@ -63,13 +63,6 @@ # services router.register("services", ServiceViewSet) -# referentielijsten -router.register( - "referentielijst-tabellen", - ReferentielijstenTabellenViewSet, - basename="referentielijst-tabellen", -) - # service fetch configurations router.register("service-fetch-configurations", ServiceFetchConfigurationViewSet) @@ -130,6 +123,11 @@ path("formio/", include("openforms.formio.api.urls")), path("geo/", include("openforms.contrib.kadaster.api.urls")), path("i18n/", include("openforms.translations.api.urls")), + path( + "referentielijst-tabellen/", + ReferentielijstenTabellenViewSet.as_view(), + name="referentielijst-tabellen-list", + ), path("", include(router.urls)), path("", include(forms_router.urls)), path("", include(submissions_router.urls)), diff --git a/src/openforms/api/utils.py b/src/openforms/api/utils.py index f711cb9e23..e2df09d20a 100644 --- a/src/openforms/api/utils.py +++ b/src/openforms/api/utils.py @@ -1,6 +1,6 @@ import re from collections.abc import Mapping -from typing import Any +from typing import Any, TypeVar from django.db import models @@ -46,7 +46,12 @@ def get_model_serializer_instance(serializer: ModelSerializer) -> models.Model: return serializer.Meta.model() -def mark_experimental(func_or_class): +T = TypeVar( + "T", bound=type +) # ensure `mark_experimental` does not change the type signature + + +def mark_experimental(func_or_class: T) -> T: if issubclass(func_or_class, Serializer): extend_fn = extend_schema_serializer elif issubclass(func_or_class, APIView): diff --git a/src/openforms/contrib/referentielijsten/api/serializers.py b/src/openforms/contrib/referentielijsten/api/serializers.py index 208518d9a1..2b7fa35e0b 100644 --- a/src/openforms/contrib/referentielijsten/api/serializers.py +++ b/src/openforms/contrib/referentielijsten/api/serializers.py @@ -13,10 +13,6 @@ class ReferentielijstTabellenSerializer(serializers.Serializer): help_text=_("The unique code that identifies the table.") ) naam = serializers.CharField(help_text=_("The name of the table.")) - einddatumGeldigheid = serializers.DateTimeField( - help_text=_("The timestamp on which the tabel expires."), write_only=True - ) - is_geldig = serializers.SerializerMethodField( help_text=_("Indicates whether or not the table is expired.") ) diff --git a/src/openforms/contrib/referentielijsten/api/viewsets.py b/src/openforms/contrib/referentielijsten/api/viewsets.py index b4f2994910..1f7ca7444b 100644 --- a/src/openforms/contrib/referentielijsten/api/viewsets.py +++ b/src/openforms/contrib/referentielijsten/api/viewsets.py @@ -1,46 +1,38 @@ from django.shortcuts import get_object_or_404 from django.utils.translation import gettext_lazy as _ -from drf_spectacular.utils import extend_schema, extend_schema_view +from drf_spectacular.utils import extend_schema from requests.exceptions import RequestException -from rest_framework import authentication, permissions, serializers, status, viewsets -from rest_framework.decorators import action -from rest_framework.response import Response +from rest_framework import authentication, permissions +from rest_framework.views import APIView from zgw_consumers.client import build_client from zgw_consumers.models import Service from openforms.api.utils import mark_experimental +from openforms.api.views import ListMixin -from ..client import ReferentielijstenClient +from ..client import ReferentielijstenClient, Tabel from .serializers import ReferentielijstTabellenSerializer -@extend_schema_view( - get=extend_schema( - summary=_("List tabellen for a Referentielijsten service"), - description=_( - "Return a list of available (JSON) tabellen in a given Referentielijsten service configured " - "in the backend.\n\n" - "Note that this endpoint is **EXPERIMENTAL**." - ), - responses={ - 200: ReferentielijstTabellenSerializer(many=True), - }, - ) +@extend_schema( + summary=_("List tabellen for a Referentielijsten service"), ) @mark_experimental -class ReferentielijstenTabellenViewSet(viewsets.ViewSet): +class ReferentielijstenTabellenViewSet(ListMixin, APIView): """ - List tabellen for a given Referentielijst service + Return a list of available tabellen in a given Referentielijsten service configured in the backend. + + Note that this endpoint is **EXPERIMENTAL**. """ authentication_classes = (authentication.SessionAuthentication,) permission_classes = (permissions.IsAdminUser,) serializer_class = ReferentielijstTabellenSerializer - @action(detail=False, methods=["get"], url_path="(?P[-a-zA-Z0-9_]+)") - def get(self, request, service_slug: str | None = None): - service = get_object_or_404(Service, slug=service_slug) + def get_objects(self) -> list[Tabel]: + service = get_object_or_404(Service, slug=self.kwargs["service_slug"]) + try: with build_client( service, client_factory=ReferentielijstenClient @@ -49,7 +41,4 @@ def get(self, request, service_slug: str | None = None): except RequestException: result = [] - assert issubclass(self.serializer_class, serializers.Serializer) - serializer = self.serializer_class(data=result, many=True) - serializer.is_valid() - return Response(serializer.data, status=status.HTTP_200_OK) + return result diff --git a/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py b/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py index a24b8e2302..a5b4253558 100644 --- a/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py +++ b/src/openforms/contrib/referentielijsten/tests/test_tabellen_list.py @@ -28,7 +28,7 @@ def setUpTestData(cls): def test_tabellen_list_is_forbidden_for_normal_users(self): endpoint = reverse( - "api:referentielijst-tabellen-get", + "api:referentielijst-tabellen-list", kwargs={"service_slug": "referentielijsten"}, ) self.client.force_authenticate(user=self.user) @@ -39,7 +39,7 @@ def test_tabellen_list_is_forbidden_for_normal_users(self): def test_returned_tabellen_have_the_right_properties(self): endpoint = reverse( - "api:referentielijst-tabellen-get", + "api:referentielijst-tabellen-list", kwargs={"service_slug": "referentielijsten"}, ) self.client.force_authenticate(user=self.admin_user) @@ -69,7 +69,7 @@ def test_returned_tabellen_have_the_right_properties(self): def test_service_not_found(self): endpoint = reverse( - "api:referentielijst-tabellen-get", kwargs={"service_slug": "non-existent"} + "api:referentielijst-tabellen-list", kwargs={"service_slug": "non-existent"} ) self.client.force_authenticate(user=self.admin_user) @@ -82,7 +82,7 @@ def test_referentielijsten_api_returns_404(self): slug="incorrect-api-root", api_root="http://localhost:8004/incorrect/" ) endpoint = reverse( - "api:referentielijst-tabellen-get", + "api:referentielijst-tabellen-list", kwargs={"service_slug": "incorrect-api-root"}, ) self.client.force_authenticate(user=self.admin_user) diff --git a/src/openforms/js/components/formio_builder/referentielijsten.js b/src/openforms/js/components/formio_builder/referentielijsten.js index b9a4bab578..f4ac014277 100644 --- a/src/openforms/js/components/formio_builder/referentielijsten.js +++ b/src/openforms/js/components/formio_builder/referentielijsten.js @@ -1,7 +1,7 @@ import {get} from 'utils/fetch'; export const getServices = async type => { - const resp = await get(`/api/v2/services?type=${encodeURIComponent(type)}`); + const resp = await get(`/api/v2/services`, {type: type}); return resp.data; }; diff --git a/src/openforms/services/api/viewsets.py b/src/openforms/services/api/viewsets.py index 2492378842..621f7c53a7 100644 --- a/src/openforms/services/api/viewsets.py +++ b/src/openforms/services/api/viewsets.py @@ -23,10 +23,9 @@ name="type", type=str, location=OpenApiParameter.QUERY, - description=_( - "The type of Services to return, possible values: `referentielijsten`" - ), + description=_("The type of Services to return."), required=False, + enum=["referentielijsten"], ) ], ),