diff --git a/src/openforms/fixtures/admin_index_unlisted.json b/src/openforms/fixtures/admin_index_unlisted.json
index db613aae81..388824fb21 100644
--- a/src/openforms/fixtures/admin_index_unlisted.json
+++ b/src/openforms/fixtures/admin_index_unlisted.json
@@ -20,6 +20,7 @@
"qmatic.QmaticConfig",
"registrations_email.EmailConfig",
"registrations_microsoft_graph.MSGraphRegistrationConfig",
+ "registrations_objects_api.ObjectsAPIGroupConfig",
"registrations_objects_api.ObjectsAPIConfig",
"stuf.StufService",
"stuf_bg.StufBGConfig",
diff --git a/src/openforms/js/compiled-lang/en.json b/src/openforms/js/compiled-lang/en.json
index 7f76ed270e..8cfcf1dcaa 100644
--- a/src/openforms/js/compiled-lang/en.json
+++ b/src/openforms/js/compiled-lang/en.json
@@ -1893,6 +1893,12 @@
"value": "Decision definition ID"
}
],
+ "Ijrbrp": [
+ {
+ "type": 0,
+ "value": "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ }
+ ],
"Ika4IH": [
{
"type": 0,
@@ -4499,6 +4505,12 @@
"value": "House number"
}
],
+ "mgs/Xe": [
+ {
+ "type": 0,
+ "value": "Objects API group"
+ }
+ ],
"mpzdoT": [
{
"type": 0,
diff --git a/src/openforms/js/compiled-lang/nl.json b/src/openforms/js/compiled-lang/nl.json
index 64ca781076..5d64b6a534 100644
--- a/src/openforms/js/compiled-lang/nl.json
+++ b/src/openforms/js/compiled-lang/nl.json
@@ -1897,6 +1897,12 @@
"value": "Beslisdefinitie-ID"
}
],
+ "Ijrbrp": [
+ {
+ "type": 0,
+ "value": "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ }
+ ],
"Ika4IH": [
{
"type": 0,
@@ -4504,6 +4510,12 @@
"value": "Huisnummer"
}
],
+ "mgs/Xe": [
+ {
+ "type": 0,
+ "value": "Objects API group"
+ }
+ ],
"mpzdoT": [
{
"type": 0,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/LegacyConfigFields.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/LegacyConfigFields.js
index c3bfad01a9..3bccc2dc87 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/LegacyConfigFields.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/LegacyConfigFields.js
@@ -4,15 +4,17 @@ import {useIntl} from 'react-intl';
import {CustomFieldTemplate} from 'components/admin/RJSFWrapper';
import {Checkbox, NumberInput, TextArea, TextInput} from 'components/admin/forms/Inputs';
+import Select from 'components/admin/forms/Select';
import {ValidationErrorContext} from 'components/admin/forms/ValidationErrors';
-import {getErrorMarkup, getFieldErrors} from './utils';
+import {getChoicesFromSchema, getErrorMarkup, getFieldErrors} from './utils';
-const LegacyConfigFields = ({index, name, formData, onChange}) => {
+const LegacyConfigFields = ({index, name, schema, formData, onChange}) => {
const intl = useIntl();
const validationErrors = useContext(ValidationErrorContext);
const {
+ objectsApiGroup = '',
objecttype = '',
objecttypeVersion = '',
productaanvraagType = '',
@@ -32,6 +34,33 @@ const LegacyConfigFields = ({index, name, formData, onChange}) => {
return (
<>
+
+
+
{
LegacyConfigFields.propTypes = {
index: PropTypes.number,
name: PropTypes.string,
+ schema: PropTypes.any,
formData: PropTypes.shape({
+ objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
version: PropTypes.number,
objecttype: PropTypes.string,
objecttypeVersion: PropTypes.string,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectTypeVersionSelect.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectTypeVersionSelect.js
index 5eae963f72..6b8e3b87e2 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectTypeVersionSelect.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectTypeVersionSelect.js
@@ -15,6 +15,7 @@ const getObjecttypeVersionsEndpoint = objecttype => {
};
const ObjectTypeVersionSelect = ({
+ objectsApiGroup,
availableObjecttypes = [],
selectedObjecttype,
selectedVersion,
@@ -31,13 +32,15 @@ const ObjectTypeVersionSelect = ({
// no match -> no versions to retrieve;
if (!objecttype) return [];
- const response = await get(getObjecttypeVersionsEndpoint(objecttype));
+ const params = {};
+ if (objectsApiGroup) params.objects_api_group = objectsApiGroup;
+ const response = await get(getObjecttypeVersionsEndpoint(objecttype), params);
if (!response.ok) {
throw new Error('Loading available object types failed');
}
const versions = response.data;
return versions.sort((v1, v2) => v2.version - v1.version);
- }, [selectedObjecttype, objecttypeUrls]);
+ }, [selectedObjecttype, objecttypeUrls, objectsApiGroup]);
const choices =
loading || error
@@ -76,6 +79,7 @@ const ObjectTypeVersionSelect = ({
};
ObjectTypeVersionSelect.propTypes = {
+ objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
availableObjecttypes: PropTypes.array,
selectedObjecttype: PropTypes.string.isRequired,
selectedVersion: PropTypes.string.isRequired,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectsApiOptionsFormFields.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectsApiOptionsFormFields.js
index e0f52518ad..c4726b2563 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectsApiOptionsFormFields.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectsApiOptionsFormFields.js
@@ -99,6 +99,7 @@ const ObjectsApiOptionsFormFields = ({index, name, schema, formData, onChange})
@@ -111,6 +112,7 @@ const ObjectsApiOptionsFormFields = ({index, name, schema, formData, onChange})
@@ -126,6 +128,7 @@ ObjectsApiOptionsFormFields.propTypes = {
name: PropTypes.string,
schema: PropTypes.any,
formData: PropTypes.shape({
+ objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
version: PropTypes.number,
objecttype: PropTypes.string,
objecttypeVersion: PropTypes.string,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/V2ConfigFields.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/V2ConfigFields.js
index 2815c93c26..96b20f6042 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/V2ConfigFields.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/V2ConfigFields.js
@@ -4,23 +4,21 @@ import {FormattedMessage, useIntl} from 'react-intl';
import {CustomFieldTemplate} from 'components/admin/RJSFWrapper';
import {Checkbox, TextInput} from 'components/admin/forms/Inputs';
+import Select from 'components/admin/forms/Select';
import {ValidationErrorContext} from 'components/admin/forms/ValidationErrors';
import ErrorMessage from 'components/errors/ErrorMessage';
import ObjectTypeSelect from './ObjectTypeSelect';
import ObjectTypeVersionSelect from './ObjectTypeVersionSelect';
import {useGetAvailableObjectTypes} from './hooks';
-import {getErrorMarkup, getFieldErrors} from './utils';
+import {getChoicesFromSchema, getErrorMarkup, getFieldErrors} from './utils';
-const V2ConfigFields = ({index, name, formData, onChange}) => {
+const V2ConfigFields = ({index, name, schema, formData, onChange}) => {
const intl = useIntl();
const validationErrors = useContext(ValidationErrorContext);
- // Track available object types and versions in this component so the state can be
- // shared.
- const availableObjectTypesState = useGetAvailableObjectTypes();
-
const {
+ objectsApiGroup = '',
objecttype = '',
objecttypeVersion = '',
informatieobjecttypeSubmissionReport = '',
@@ -30,6 +28,10 @@ const V2ConfigFields = ({index, name, formData, onChange}) => {
organisatieRsin = '',
} = formData;
+ // Track available object types and versions in this component so the state can be
+ // shared.
+ const availableObjectTypesState = useGetAvailableObjectTypes(objectsApiGroup);
+
const buildErrorsComponent = field => {
const rawErrors = getFieldErrors(name, index, validationErrors, field);
return rawErrors ? getErrorMarkup(rawErrors) : null;
@@ -49,6 +51,33 @@ const V2ConfigFields = ({index, name, formData, onChange}) => {
return (
<>
+
+
+
{
>
{/* TODO: fallback to legacy UI if there are loading errors */}
{
V2ConfigFields.propTypes = {
index: PropTypes.number,
name: PropTypes.string,
+ schema: PropTypes.any,
formData: PropTypes.shape({
+ objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
version: PropTypes.number,
objecttype: PropTypes.string,
objecttypeVersion: PropTypes.string,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/hooks.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/hooks.js
index 3e7039bfd2..7e17df3148 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/hooks.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/hooks.js
@@ -3,22 +3,20 @@ import useAsync from 'react-use/esm/useAsync';
import {REGISTRATION_OBJECTTYPES_ENDPOINT} from 'components/admin/form_design/constants';
import {get} from 'utils/fetch';
-export const useGetAvailableObjectTypes = () => {
+export const useGetAvailableObjectTypes = objectsApiGroup => {
const {
loading,
value: availableObjecttypes = [],
error,
- } = useAsync(
- async () => {
- const response = await get(REGISTRATION_OBJECTTYPES_ENDPOINT);
- if (!response.ok) {
- throw new Error('Loading available object types failed');
- }
- return response.data;
- },
- // available object types only need to be loaded once when the component mounts
- []
- );
+ } = useAsync(async () => {
+ const params = {};
+ if (objectsApiGroup) params.objects_api_group = objectsApiGroup;
+ const response = await get(REGISTRATION_OBJECTTYPES_ENDPOINT, params);
+ if (!response.ok) {
+ throw new Error('Loading available object types failed');
+ }
+ return response.data;
+ }, [objectsApiGroup]);
return {
loading,
diff --git a/src/openforms/js/components/admin/form_design/registrations/objectsapi/utils.js b/src/openforms/js/components/admin/form_design/registrations/objectsapi/utils.js
index a0d2852110..7d0b92c4a6 100644
--- a/src/openforms/js/components/admin/form_design/registrations/objectsapi/utils.js
+++ b/src/openforms/js/components/admin/form_design/registrations/objectsapi/utils.js
@@ -3,6 +3,15 @@ import React from 'react';
// TODO This is duplicated from the ZGW registration, but will be cleaned up
// with the backend UI refactor.
+const getChoicesFromSchema = (enums, enumNames) => {
+ let finalChoices = {};
+ Object.keys(enums).forEach(key => {
+ finalChoices[enums[key]] = enumNames[key];
+ });
+
+ return finalChoices;
+};
+
const getFieldErrors = (name, index, errors, field) => {
const errorMessages = [];
@@ -30,6 +39,8 @@ const getErrorMarkup = errorMessages => {
);
};
+// End TODO
+
const VARIABLE_TYPE_MAP = {
boolean: 'boolean',
int: 'integer',
@@ -89,4 +100,4 @@ const asJsonSchema = (variable, components) => {
};
};
-export {getErrorMarkup, getFieldErrors, asJsonSchema};
+export {getChoicesFromSchema, getErrorMarkup, getFieldErrors, asJsonSchema};
diff --git a/src/openforms/js/components/form/file.js b/src/openforms/js/components/form/file.js
index 467db20a05..cdcaa1f475 100644
--- a/src/openforms/js/components/form/file.js
+++ b/src/openforms/js/components/form/file.js
@@ -25,6 +25,7 @@ const getInformatieObjectTypen = async (backend, options) => {
}
case 'objects_api':
return await get('/api/v2/registration/informatieobjecttypen', {
+ objects_api_group: options.objectsApiGroup,
registration_backend: backend,
});
default:
diff --git a/src/openforms/js/lang/en.json b/src/openforms/js/lang/en.json
index df8fc2ac0a..1d06524e12 100644
--- a/src/openforms/js/lang/en.json
+++ b/src/openforms/js/lang/en.json
@@ -839,6 +839,11 @@
"description": "Decision definition ID label",
"originalDefault": "Decision definition ID"
},
+ "Ijrbrp": {
+ "defaultMessage": "Which Objects API group to use. If not provided, the default Objects API group will be used.",
+ "description": "Objects API group selection",
+ "originalDefault": "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ },
"Ika4IH": {
"defaultMessage": "Submissions will be deleted",
"description": "delete_permanently removal method option label",
@@ -2079,6 +2084,11 @@
"description": "JSON variable type \"Form field\" representation",
"originalDefault": "Form field"
},
+ "mgs/Xe": {
+ "defaultMessage": "Objects API group",
+ "description": "Objects API group",
+ "originalDefault": "Objects API group"
+ },
"myvtu0": {
"defaultMessage": "Manage process variables",
"description": "Open manage camunda process vars modal button",
diff --git a/src/openforms/js/lang/nl.json b/src/openforms/js/lang/nl.json
index 171bac3364..2f197bf945 100644
--- a/src/openforms/js/lang/nl.json
+++ b/src/openforms/js/lang/nl.json
@@ -845,6 +845,11 @@
"description": "Decision definition ID label",
"originalDefault": "Decision definition ID"
},
+ "Ijrbrp": {
+ "defaultMessage": "Which Objects API group to use. If not provided, the default Objects API group will be used.",
+ "description": "Objects API group selection",
+ "originalDefault": "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ },
"Ika4IH": {
"defaultMessage": "Inzendingen worden permanent verwijderd",
"description": "delete_permanently removal method option label",
@@ -2093,6 +2098,11 @@
"description": "JSON variable type \"Form field\" representation",
"originalDefault": "Form field"
},
+ "mgs/Xe": {
+ "defaultMessage": "Objects API group",
+ "description": "Objects API group",
+ "originalDefault": "Objects API group"
+ },
"myvtu0": {
"defaultMessage": "Beheer procesvariabelen",
"description": "Open manage camunda process vars modal button",
diff --git a/src/openforms/registrations/api/filters.py b/src/openforms/registrations/api/filters.py
index 0541d6f6ae..7b646e1a8c 100644
--- a/src/openforms/registrations/api/filters.py
+++ b/src/openforms/registrations/api/filters.py
@@ -5,7 +5,10 @@
from openforms.api.fields import PrimaryKeyRelatedAsChoicesField
from openforms.contrib.zgw.clients.catalogi import CatalogiClient
-from openforms.registrations.contrib.objects_api.models import ObjectsAPIConfig
+from openforms.registrations.contrib.objects_api.models import (
+ ObjectsAPIConfig,
+ ObjectsAPIGroupConfig,
+)
from openforms.registrations.contrib.zgw_apis.client import get_catalogi_client
from openforms.registrations.contrib.zgw_apis.models import ZGWApiGroupConfig, ZgwConfig
@@ -23,33 +26,54 @@ class ListInformatieObjectTypenQueryParamsSerializer(serializers.Serializer):
label=_("ZGW API set"),
required=False,
)
+ objects_api_group = PrimaryKeyRelatedAsChoicesField(
+ queryset=ObjectsAPIGroupConfig.objects.all(),
+ help_text=_(
+ "The primary key of the Objects API group to use. If provided, the informatieobjecttypen from the Catalogi API "
+ "in this group will be returned. Otherwise, the Catalogi API in the default Objects API group will be used to find "
+ "informatieobjecttypen."
+ ),
+ label=_("Objects API group"),
+ required=False,
+ )
registration_backend = serializers.ChoiceField(
help_text=_("The ID of the registration backend to use."),
label=_("Registration backend ID"),
- required=False,
choices=[],
)
def get_fields(self):
fields = super().get_fields()
# lazy set choices
- if "registration_backend" in fields:
- fields["registration_backend"].choices = register.get_choices()
+ fields["registration_backend"].choices = register.get_choices()
return fields
def get_ztc_client(self) -> CatalogiClient | None:
registration_backend = self.validated_data.get("registration_backend")
- zgw_api_group: ZGWApiGroupConfig = self.validated_data.get("zgw_api_group")
+ zgw_api_group: ZGWApiGroupConfig | None = self.validated_data.get(
+ "zgw_api_group"
+ )
+ objects_api_group: ObjectsAPIGroupConfig | None = self.validated_data.get(
+ "objects_api_group"
+ )
- if registration_backend == "zgw-create-zaak" and zgw_api_group is not None:
- return get_catalogi_client(zgw_api_group)
+ if registration_backend == "zgw-create-zaak":
+ if zgw_api_group is not None:
+ return get_catalogi_client(zgw_api_group)
+ else:
+ config = ZgwConfig.get_solo()
+ assert isinstance(config, ZgwConfig)
+ if group := config.default_zgw_api_group:
+ return get_catalogi_client(group)
elif registration_backend == "objects_api":
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
- if service := config.catalogi_service:
- return build_client(service, client_factory=CatalogiClient)
+ if objects_api_group is not None:
+ service = objects_api_group.catalogi_service
+ else:
+ config = ObjectsAPIConfig.get_solo()
+ assert isinstance(config, ObjectsAPIConfig)
+ if config.default_objects_api_group is None:
+ return
+ service = config.default_objects_api_group.catalogi_service
- config = ZgwConfig.get_solo()
- assert isinstance(config, ZgwConfig)
- if group := config.default_zgw_api_group:
- return get_catalogi_client(group)
+ if service is not None:
+ return build_client(service, client_factory=CatalogiClient)
diff --git a/src/openforms/registrations/contrib/objects_api/admin.py b/src/openforms/registrations/contrib/objects_api/admin.py
index 2c3feb4b36..548855363b 100644
--- a/src/openforms/registrations/contrib/objects_api/admin.py
+++ b/src/openforms/registrations/contrib/objects_api/admin.py
@@ -2,9 +2,34 @@
from solo.admin import SingletonModelAdmin
-from .models import ObjectsAPIConfig
+from .models import ObjectsAPIConfig, ObjectsAPIGroupConfig
@admin.register(ObjectsAPIConfig)
class ObjectsAPIConfigAdmin(SingletonModelAdmin):
pass
+
+
+@admin.register(ObjectsAPIGroupConfig)
+class ObjectsAPIGroupConfigAdmin(admin.ModelAdmin):
+ list_display = (
+ "name",
+ "objects_service",
+ "objecttypes_service",
+ "drc_service",
+ "catalogi_service",
+ )
+ list_select_related = (
+ "objects_service",
+ "objecttypes_service",
+ "drc_service",
+ "catalogi_service",
+ )
+ search_fields = ("name",)
+ raw_id_fields = (
+ "objects_service",
+ "objecttypes_service",
+ "drc_service",
+ "catalogi_service",
+ )
+ ordering = ("name",)
diff --git a/src/openforms/registrations/contrib/objects_api/api/serializers.py b/src/openforms/registrations/contrib/objects_api/api/serializers.py
index 78e0c2fb1e..306d5b3c9f 100644
--- a/src/openforms/registrations/contrib/objects_api/api/serializers.py
+++ b/src/openforms/registrations/contrib/objects_api/api/serializers.py
@@ -2,6 +2,21 @@
from rest_framework import serializers
+from openforms.api.fields import PrimaryKeyRelatedAsChoicesField
+
+from ..models import ObjectsAPIGroupConfig
+
+
+class ObjectsAPIGroupInputSerializer(serializers.Serializer):
+ objects_api_group = PrimaryKeyRelatedAsChoicesField(
+ queryset=ObjectsAPIGroupConfig.objects.all(),
+ label=("Objects API group"),
+ help_text=_(
+ "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ ),
+ required=False,
+ )
+
class ObjecttypeSerializer(serializers.Serializer):
# Keys are defined in camel case as this is what we get from the Objecttype API
@@ -43,7 +58,7 @@ class TargetPathsSerializer(serializers.Serializer):
)
-class TargetPathsInputSerializer(serializers.Serializer):
+class TargetPathsInputSerializer(ObjectsAPIGroupInputSerializer):
objecttype_url = serializers.URLField(
label=_("objecttype url"), help_text=("The URL of the objecttype.")
)
diff --git a/src/openforms/registrations/contrib/objects_api/api/views.py b/src/openforms/registrations/contrib/objects_api/api/views.py
index 08992a5573..2277380132 100644
--- a/src/openforms/registrations/contrib/objects_api/api/views.py
+++ b/src/openforms/registrations/contrib/objects_api/api/views.py
@@ -3,7 +3,8 @@
from django.utils.translation import gettext_lazy as _
-from drf_spectacular.utils import extend_schema, extend_schema_view
+from drf_spectacular.types import OpenApiTypes
+from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework import authentication, exceptions, permissions, views
from rest_framework.request import Request
from rest_framework.response import Response
@@ -12,18 +13,30 @@
from ..client import get_objecttypes_client
from ..json_schema import InvalidReference, iter_json_schema_paths, json_schema_matches
+from ..models import ObjectsAPIConfig
from .serializers import (
+ ObjectsAPIGroupInputSerializer,
ObjecttypeSerializer,
ObjecttypeVersionSerializer,
TargetPathsInputSerializer,
TargetPathsSerializer,
)
-
-@extend_schema_view(
- get=extend_schema(
- tags=["registration"],
+# TODO: https://github.com/open-formulieren/open-forms/issues/611
+OBJECTS_API_GROUP_QUERY_PARAMETER = OpenApiParameter(
+ name="objects_api_group",
+ type=OpenApiTypes.STR,
+ location=OpenApiParameter.QUERY,
+ description=_(
+ "Which Objects API group to use. If not provided, the default Objects API group will be used."
),
+ required=False,
+)
+
+
+@extend_schema(
+ tags=["registration"],
+ parameters=[OBJECTS_API_GROUP_QUERY_PARAMETER],
)
class ObjecttypesListView(ListMixin, views.APIView):
"""
@@ -37,14 +50,24 @@ class ObjecttypesListView(ListMixin, views.APIView):
serializer_class = ObjecttypeSerializer
def get_objects(self) -> list[dict[str, Any]]:
- with get_objecttypes_client() as client:
+ input_serializer = ObjectsAPIGroupInputSerializer(
+ data=self.request.query_params
+ )
+ if not input_serializer.is_valid(raise_exception=False):
+ return []
+
+ config_group = (
+ input_serializer.validated_data.get("objects_api_group")
+ or ObjectsAPIConfig.get_solo().default_objects_api_group
+ )
+
+ with get_objecttypes_client(config_group) as client:
return client.list_objecttypes()
-@extend_schema_view(
- get=extend_schema(
- tags=["registration"],
- ),
+@extend_schema(
+ tags=["registration"],
+ parameters=[OBJECTS_API_GROUP_QUERY_PARAMETER],
)
class ObjecttypeVersionsListView(ListMixin, views.APIView):
"""
@@ -58,7 +81,18 @@ class ObjecttypeVersionsListView(ListMixin, views.APIView):
serializer_class = ObjecttypeVersionSerializer
def get_objects(self) -> list[dict[str, Any]]:
- with get_objecttypes_client() as client:
+ input_serializer = ObjectsAPIGroupInputSerializer(
+ data=self.request.query_params
+ )
+ if not input_serializer.is_valid(raise_exception=False):
+ return []
+
+ config_group = (
+ input_serializer.validated_data.get("objects_api_group")
+ or ObjectsAPIConfig.get_solo().default_objects_api_group
+ )
+
+ with get_objecttypes_client(config_group) as client:
return client.list_objecttype_versions(self.kwargs["submission_uuid"])
@@ -85,8 +119,12 @@ def post(self, request: Request, *args: Any, **kwargs: Any):
objecttype_uuid = match.group()
- with get_objecttypes_client() as client:
+ config_group = (
+ input_serializer.validated_data.get("objects_api_group")
+ or ObjectsAPIConfig.get_solo().default_objects_api_group
+ )
+ with get_objecttypes_client(config_group) as client:
json_schema = client.get_objecttype_version(
objecttype_uuid, input_serializer.validated_data["objecttype_version"]
)["jsonSchema"]
diff --git a/src/openforms/registrations/contrib/objects_api/checks.py b/src/openforms/registrations/contrib/objects_api/checks.py
index 9c0d712b3f..67c0fd2237 100644
--- a/src/openforms/registrations/contrib/objects_api/checks.py
+++ b/src/openforms/registrations/contrib/objects_api/checks.py
@@ -10,93 +10,105 @@
get_objects_client,
get_objecttypes_client,
)
-from .models import ObjectsAPIConfig
+from .models import ObjectsAPIGroupConfig
-def check_objects_service():
- with get_objects_client() as client:
+def check_objects_service(config: ObjectsAPIGroupConfig):
+ with get_objects_client(config) as client:
resp = client.get("objects", params={"pageSize": 1})
resp.raise_for_status()
if not 200 <= resp.status_code < 300:
- raise InvalidPluginConfiguration(_("Missing API credentials"))
+ raise InvalidPluginConfiguration(
+ _(
+ "Missing Objects API credentials for Objects API group {objects_api_group}"
+ ).format(objects_api_group=config.name)
+ )
-def check_objecttypes_service():
- with get_objecttypes_client() as client:
+def check_objecttypes_service(config: ObjectsAPIGroupConfig):
+ with get_objecttypes_client(config) as client:
resp = client.get("objecttypes", params={"pageSize": 1})
resp.raise_for_status()
if not 200 <= resp.status_code < 300:
- raise InvalidPluginConfiguration(_("Missing API credentials"))
+ raise InvalidPluginConfiguration(
+ _(
+ "Missing Objecttypes API credentials for Objects API group {objects_api_group}"
+ ).format(objects_api_group=config.name)
+ )
-def check_documents_service():
- with get_documents_client() as client:
+def check_documents_service(config: ObjectsAPIGroupConfig):
+ with get_documents_client(config) as client:
resp = client.get("enkelvoudiginformatieobjecten")
resp.raise_for_status()
def check_config():
- # First, check that the necessary services are configured correctly.
+ configs = ObjectsAPIGroupConfig.objects.all()
services = (
(check_objects_service, "objects_service"),
(check_objecttypes_service, "objecttypes_service"),
(check_documents_service, "drc_service"),
)
+ for config in configs:
+ # First, check that the necessary services are configured correctly.
+ for check_function, field_name in services:
+ api_name = ObjectsAPIGroupConfig._meta.get_field(field_name).verbose_name # type: ignore
+ try:
+ check_function(config)
+ except NoServiceConfigured as exc:
+ raise InvalidPluginConfiguration(
+ _(
+ "{api_name} endpoint is not configured for Objects API group {objects_api_group}."
+ ).format(api_name=api_name, objects_api_group=config.name)
+ ) from exc
+ except requests.RequestException as exc:
+ raise InvalidPluginConfiguration(
+ _("Client error: {exception}").format(exception=exc)
+ )
- for check_function, field_name in services:
- api_name = ObjectsAPIConfig._meta.get_field(field_name).verbose_name # type: ignore
- try:
- check_function()
- except NoServiceConfigured as exc:
- raise InvalidPluginConfiguration(
- _("{api_name} endpoint is not configured.").format(api_name=api_name)
- ) from exc
- except requests.RequestException as exc:
- raise InvalidPluginConfiguration(
- _("Client error: {exception}").format(exception=exc)
+ urls = [
+ "objecttype",
+ "informatieobjecttype_submission_report",
+ "informatieobjecttype_submission_csv",
+ "informatieobjecttype_attachment",
+ ]
+ # we don't know for sure that these URLs share the same base, so instead we use a
+ # raw requests session to get connection pooling without tying this to the configured
+ # services.
+ with requests.Session() as session:
+ error_template = _(
+ "Could not access default '{service_field}' ({url}) for Objects API group {objects_api_group}: {exception}"
)
+ for service_field in urls:
+ # these fields are optional defaults, but if configured, they need to point to
+ # something that looks right.
+ if not (url := getattr(config, service_field)):
+ continue
+
+ # this is a deliberate non-authenticated call, a 403 means we're hitting a
+ # valid endpoint
+ try:
+ response = session.get(url)
+ except requests.RequestException as exc:
+ raise InvalidPluginConfiguration(
+ error_template.format(
+ service_field=service_field,
+ url=url,
+ objects_api_group=config.name,
+ exception=exc,
+ )
+ ) from exc
+
+ # okay, looks like a valid endpoint
+ if response.status_code in (200, 403) or response.ok:
+ continue
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
-
- urls = [
- "objecttype",
- "informatieobjecttype_submission_report",
- "informatieobjecttype_submission_csv",
- "informatieobjecttype_attachment",
- ]
- # we don't know for sure that these URLs share the same base, so instead we use a
- # raw requests session to get connection pooling without tying this to the configured
- # services.
- with requests.Session() as session:
- error_template = _(
- "Could not access default '{service_field}' ({url}): {exception}"
- )
- for service_field in urls:
- # these fields are optional defaults, but if configured, they need to point to
- # something that looks right.
- if not (url := getattr(config, service_field)):
- continue
-
- # this is a deliberate non-authenticated call, a 403 means we're hitting a
- # valid endpoint
- try:
- response = session.get(url)
- except requests.RequestException as exc:
raise InvalidPluginConfiguration(
error_template.format(
- service_field=service_field, url=url, exception=exc
+ service_field=service_field,
+ url=url,
+ objects_api_group=config.name,
+ exception=f"HTTP status {response.status_code}",
)
- ) from exc
-
- # okay, looks like a valid endpoint
- if response.status_code in (200, 403) or response.ok:
- continue
-
- raise InvalidPluginConfiguration(
- error_template.format(
- service_field=service_field,
- url=url,
- exception=f"HTTP status {response.status_code}",
)
- )
diff --git a/src/openforms/registrations/contrib/objects_api/client.py b/src/openforms/registrations/contrib/objects_api/client.py
index 3b73219dcc..4c30333617 100644
--- a/src/openforms/registrations/contrib/objects_api/client.py
+++ b/src/openforms/registrations/contrib/objects_api/client.py
@@ -14,32 +14,26 @@
from openforms.contrib.objects_api.clients import ObjectsClient, ObjecttypesClient
from openforms.contrib.zgw.clients import DocumentenClient
-from .models import ObjectsAPIConfig
+from .models import ObjectsAPIGroupConfig
class NoServiceConfigured(RuntimeError):
pass
-def get_objects_client() -> ObjectsClient:
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
+def get_objects_client(config: ObjectsAPIGroupConfig) -> ObjectsClient:
if not (service := config.objects_service):
raise NoServiceConfigured("No Objects API service configured!")
return build_client(service, client_factory=ObjectsClient)
-def get_objecttypes_client() -> ObjecttypesClient:
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
+def get_objecttypes_client(config: ObjectsAPIGroupConfig) -> ObjecttypesClient:
if not (service := config.objecttypes_service):
raise NoServiceConfigured("No Objecttypes API service configured!")
return build_client(service, client_factory=ObjecttypesClient)
-def get_documents_client() -> DocumentenClient:
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
+def get_documents_client(config: ObjectsAPIGroupConfig) -> DocumentenClient:
if not (service := config.drc_service):
raise NoServiceConfigured("No Documents API service configured!")
return build_client(service, client_factory=DocumentenClient)
diff --git a/src/openforms/registrations/contrib/objects_api/config.py b/src/openforms/registrations/contrib/objects_api/config.py
index 7a92270dba..a10765f4b4 100644
--- a/src/openforms/registrations/contrib/objects_api/config.py
+++ b/src/openforms/registrations/contrib/objects_api/config.py
@@ -7,12 +7,15 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
+from openforms.api.fields import PrimaryKeyRelatedAsChoicesField
from openforms.api.utils import get_from_serializer_data_or_instance
from openforms.formio.api.fields import FormioVariableKeyField
from openforms.template.validators import DjangoTemplateValidator
from openforms.utils.mixins import JsonSchemaSerializerMixin
from openforms.utils.validators import validate_rsin
+from .models import ObjectsAPIGroupConfig
+
class VersionChoices(models.IntegerChoices):
V1 = 1, _("v1, template based")
@@ -49,7 +52,14 @@ class ObjecttypeVariableMappingSerializer(serializers.Serializer):
class ObjectsAPIOptionsSerializer(JsonSchemaSerializerMixin, serializers.Serializer):
-
+ objects_api_group = PrimaryKeyRelatedAsChoicesField(
+ queryset=ObjectsAPIGroupConfig.objects.all(),
+ label=("Objects API group"),
+ help_text=_(
+ "Which Objects API group to use. If not provided, the default Objects API group will be used."
+ ),
+ required=False,
+ )
version = serializers.ChoiceField(
label=_("options version"),
help_text=_(
diff --git a/src/openforms/registrations/contrib/objects_api/migrations/0016_objectsapigroupconfig.py b/src/openforms/registrations/contrib/objects_api/migrations/0016_objectsapigroupconfig.py
new file mode 100644
index 0000000000..25ae169fcd
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/migrations/0016_objectsapigroupconfig.py
@@ -0,0 +1,183 @@
+# Generated by Django 4.2.11 on 2024-05-27 13:04
+
+from django.db import migrations, models
+import django.db.models.deletion
+import openforms.registrations.contrib.objects_api.models
+import openforms.template.validators
+import openforms.utils.validators
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("zgw_consumers", "0020_service_timeout"),
+ (
+ "registrations_objects_api",
+ "0015_alter_objectsapiconfig_objecttype_and_more",
+ ),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="ObjectsAPIGroupConfig",
+ fields=[
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "name",
+ models.CharField(
+ help_text="A recognisable name for this set of Objects APIs.",
+ max_length=255,
+ verbose_name="name",
+ ),
+ ),
+ (
+ "objecttype",
+ models.URLField(
+ blank=True,
+ editable=False,
+ help_text="Default URL of the ProductAanvraag OBJECTTYPE in the Objecttypes API. The objecttype should have the following three attributes: 1) submission_id; 2) type (the type of productaanvraag); 3) data (the submitted form data)",
+ max_length=1000,
+ verbose_name="objecttype",
+ ),
+ ),
+ (
+ "objecttype_version",
+ models.IntegerField(
+ blank=True,
+ editable=False,
+ help_text="Default version of the OBJECTTYPE in the Objecttypes API",
+ null=True,
+ verbose_name="objecttype version",
+ ),
+ ),
+ (
+ "productaanvraag_type",
+ models.CharField(
+ blank=True,
+ help_text="Description of the 'ProductAanvraag' type. This value is saved in the 'type' attribute of the 'ProductAanvraag'.",
+ max_length=255,
+ verbose_name="Productaanvraag type",
+ ),
+ ),
+ (
+ "informatieobjecttype_submission_report",
+ models.URLField(
+ blank=True,
+ help_text="Default URL that points to the INFORMATIEOBJECTTYPE in the Catalogi API to be used for the submission report PDF",
+ max_length=1000,
+ verbose_name="submission report informatieobjecttype",
+ ),
+ ),
+ (
+ "informatieobjecttype_submission_csv",
+ models.URLField(
+ blank=True,
+ help_text="Default URL that points to the INFORMATIEOBJECTTYPE in the Catalogi API to be used for the submission report CSV",
+ max_length=1000,
+ verbose_name="submission report CSV informatieobjecttype",
+ ),
+ ),
+ (
+ "informatieobjecttype_attachment",
+ models.URLField(
+ blank=True,
+ help_text="Default URL that points to the INFORMATIEOBJECTTYPE in the Catalogi API to be used for the submission attachments",
+ max_length=1000,
+ verbose_name="attachment informatieobjecttype",
+ ),
+ ),
+ (
+ "organisatie_rsin",
+ models.CharField(
+ blank=True,
+ help_text="Default RSIN of organization, which creates the INFORMATIEOBJECT",
+ max_length=9,
+ validators=[openforms.utils.validators.RSINValidator()],
+ verbose_name="organisation RSIN",
+ ),
+ ),
+ (
+ "content_json",
+ models.TextField(
+ default=openforms.registrations.contrib.objects_api.models.get_content_text,
+ help_text="This template is evaluated with the submission data and the resulting JSON is sent to the objects API.",
+ validators=[
+ openforms.template.validators.DjangoTemplateValidator(
+ backend="openforms.template.openforms_backend"
+ )
+ ],
+ verbose_name="JSON content template",
+ ),
+ ),
+ (
+ "payment_status_update_json",
+ models.TextField(
+ default=openforms.registrations.contrib.objects_api.models.get_payment_status_update_text,
+ help_text="This template is evaluated with the submission data and the resulting JSON is sent to the objects API with a PATCH to update the payment field.",
+ validators=[
+ openforms.template.validators.DjangoTemplateValidator(
+ backend="openforms.template.openforms_backend"
+ )
+ ],
+ verbose_name="payment status update JSON template",
+ ),
+ ),
+ (
+ "catalogi_service",
+ models.ForeignKey(
+ limit_choices_to={"api_type": "ztc"},
+ null=True,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="zgw_consumers.service",
+ verbose_name="Catalogi API",
+ ),
+ ),
+ (
+ "drc_service",
+ models.ForeignKey(
+ limit_choices_to={"api_type": "drc"},
+ null=True,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="zgw_consumers.service",
+ verbose_name="Documenten API",
+ ),
+ ),
+ (
+ "objects_service",
+ models.ForeignKey(
+ limit_choices_to={"api_type": "orc"},
+ null=True,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="zgw_consumers.service",
+ verbose_name="Objects API",
+ ),
+ ),
+ (
+ "objecttypes_service",
+ models.ForeignKey(
+ limit_choices_to={"api_type": "orc"},
+ null=True,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="zgw_consumers.service",
+ verbose_name="Objecttypes API",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Objects API group",
+ "verbose_name_plural": "Objects API groups",
+ },
+ ),
+ ]
diff --git a/src/openforms/registrations/contrib/objects_api/migrations/0017_move_singleton_data.py b/src/openforms/registrations/contrib/objects_api/migrations/0017_move_singleton_data.py
new file mode 100644
index 0000000000..7502173c12
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/migrations/0017_move_singleton_data.py
@@ -0,0 +1,89 @@
+# Generated by Django 4.2.11 on 2024-05-27 13:06
+
+from django.db import migrations
+
+from django.db.migrations.state import StateApps
+from django.db.backends.base.schema import BaseDatabaseSchemaEditor
+
+
+def move_singleton_data_to_objects_api_set_model(
+ apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
+) -> None:
+ ObjectsAPIConfig = apps.get_model("registrations_objects_api", "ObjectsAPIConfig")
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+
+ solo_model = ObjectsAPIConfig.objects.first()
+ if not solo_model:
+ return
+
+ new_config_set = ObjectsAPIGroupConfig(
+ name="Objects APIs",
+ objects_service=solo_model.objects_service,
+ objecttypes_service=solo_model.objecttypes_service,
+ drc_service=solo_model.drc_service,
+ catalogi_service=solo_model.catalogi_service,
+ objecttype=solo_model.objecttype,
+ objecttype_version=solo_model.objecttype_version,
+ productaanvraag_type=solo_model.productaanvraag_type,
+ informatieobjecttype_submission_report=solo_model.informatieobjecttype_submission_report,
+ informatieobjecttype_submission_csv=solo_model.informatieobjecttype_submission_csv,
+ informatieobjecttype_attachment=solo_model.informatieobjecttype_attachment,
+ organisatie_rsin=solo_model.organisatie_rsin,
+ content_json=solo_model.content_json,
+ payment_status_update_json=solo_model.payment_status_update_json,
+ )
+
+ new_config_set.save()
+
+
+def reconfigure_objects_api_solo_model(
+ apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
+) -> None:
+ ObjectsAPIConfig = apps.get_model("registrations_objects_api", "ObjectsAPIConfig")
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+
+ solo_model = ObjectsAPIConfig.objects.first()
+ objects_api_group = ObjectsAPIGroupConfig.objects.all().order_by("pk").first()
+
+ if not solo_model or not objects_api_group:
+ return
+
+ solo_model.objects_service = objects_api_group.objects_service
+ solo_model.objecttypes_service = objects_api_group.objecttypes_service
+ solo_model.drc_service = objects_api_group.drc_service
+ solo_model.catalogi_service = objects_api_group.catalogi_service
+ solo_model.objecttype = objects_api_group.objecttype
+ solo_model.objecttype_version = objects_api_group.objecttype_version
+ solo_model.productaanvraag_type = objects_api_group.productaanvraag_type
+ solo_model.informatieobjecttype_submission_report = (
+ objects_api_group.informatieobjecttype_submission_report
+ )
+ solo_model.informatieobjecttype_submission_csv = (
+ objects_api_group.informatieobjecttype_submission_csv
+ )
+ solo_model.informatieobjecttype_attachment = (
+ objects_api_group.informatieobjecttype_attachment
+ )
+ solo_model.organisatie_rsin = objects_api_group.organisatie_rsin
+ solo_model.organisatie_rsin = objects_api_group.organisatie_rsin
+ solo_model.content_json = objects_api_group.content_json
+ solo_model.payment_status_update_json = objects_api_group.payment_status_update_json
+ solo_model.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrations_objects_api", "0016_objectsapigroupconfig"),
+ ]
+
+ operations = [
+ migrations.RunPython(
+ move_singleton_data_to_objects_api_set_model,
+ reconfigure_objects_api_solo_model,
+ ),
+ ]
diff --git a/src/openforms/registrations/contrib/objects_api/migrations/0018_alter_objectsapiconfig_options_and_more.py b/src/openforms/registrations/contrib/objects_api/migrations/0018_alter_objectsapiconfig_options_and_more.py
new file mode 100644
index 0000000000..3f9a48f904
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/migrations/0018_alter_objectsapiconfig_options_and_more.py
@@ -0,0 +1,81 @@
+# Generated by Django 4.2.11 on 2024-05-27 15:02
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrations_objects_api", "0017_move_singleton_data"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="objectsapiconfig",
+ options={"verbose_name": "Objects APIs configuration"},
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="catalogi_service",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="content_json",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="drc_service",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="informatieobjecttype_attachment",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="informatieobjecttype_submission_csv",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="informatieobjecttype_submission_report",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="objects_service",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="objecttype",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="objecttype_version",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="objecttypes_service",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="organisatie_rsin",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="payment_status_update_json",
+ ),
+ migrations.RemoveField(
+ model_name="objectsapiconfig",
+ name="productaanvraag_type",
+ ),
+ migrations.AddField(
+ model_name="objectsapiconfig",
+ name="default_objects_api_group",
+ field=models.ForeignKey(
+ help_text="Which Objects API group should be used by default.",
+ null=True,
+ on_delete=django.db.models.deletion.PROTECT,
+ to="registrations_objects_api.objectsapigroupconfig",
+ verbose_name="default Objects API group.",
+ ),
+ ),
+ ]
diff --git a/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default.py b/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default.py
new file mode 100644
index 0000000000..3b36298d02
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.11 on 2024-05-28 10:14
+
+from django.db import migrations
+
+
+from django.db.migrations.state import StateApps
+from django.db.backends.base.schema import BaseDatabaseSchemaEditor
+
+
+def attach_default_objects_api_group(
+ apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
+) -> None:
+ ObjectsAPIConfig = apps.get_model("registrations_objects_api", "ObjectsAPIConfig")
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+
+ # There should be at most one (since it was created by migration 0017_move_singleton_data).
+ # But in case that there are multiple, we just pick one.
+ objects_api_group = ObjectsAPIGroupConfig.objects.first()
+ if not objects_api_group:
+ return
+
+ solo_config = ObjectsAPIConfig.objects.get()
+ solo_config.default_objects_api_group = objects_api_group
+ solo_config.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("registrations_objects_api", "0018_alter_objectsapiconfig_options_and_more"),
+ ]
+
+ operations = [
+ migrations.RunPython(
+ attach_default_objects_api_group, migrations.RunPython.noop
+ ),
+ ]
diff --git a/src/openforms/registrations/contrib/objects_api/models.py b/src/openforms/registrations/contrib/objects_api/models.py
index 461054ae93..6769d81321 100644
--- a/src/openforms/registrations/contrib/objects_api/models.py
+++ b/src/openforms/registrations/contrib/objects_api/models.py
@@ -25,10 +25,28 @@ def get_payment_status_update_text() -> str:
class ObjectsAPIConfig(SingletonModel):
"""
- global configuration and defaults
+ Entry point to the default Objects APIs set.
"""
- objects_service = models.OneToOneField(
+ default_objects_api_group = models.ForeignKey(
+ to="ObjectsAPIGroupConfig",
+ on_delete=models.PROTECT,
+ verbose_name=_("default Objects API group."),
+ help_text=_("Which Objects API group should be used by default."),
+ null=True,
+ )
+
+ class Meta:
+ verbose_name = _("Objects APIs configuration")
+
+
+class ObjectsAPIGroupConfig(models.Model):
+ name = models.CharField(
+ _("name"),
+ max_length=255,
+ help_text=_("A recognisable name for this set of Objects APIs."),
+ )
+ objects_service = models.ForeignKey(
"zgw_consumers.Service",
verbose_name=_("Objects API"),
on_delete=models.PROTECT,
@@ -36,7 +54,7 @@ class ObjectsAPIConfig(SingletonModel):
null=True,
related_name="+",
)
- objecttypes_service = models.OneToOneField(
+ objecttypes_service = models.ForeignKey(
"zgw_consumers.Service",
verbose_name=_("Objecttypes API"),
on_delete=models.PROTECT,
@@ -44,7 +62,7 @@ class ObjectsAPIConfig(SingletonModel):
null=True,
related_name="+",
)
- drc_service = models.OneToOneField(
+ drc_service = models.ForeignKey(
"zgw_consumers.Service",
verbose_name=_("Documenten API"),
on_delete=models.PROTECT,
@@ -52,7 +70,7 @@ class ObjectsAPIConfig(SingletonModel):
null=True,
related_name="+",
)
- catalogi_service = models.OneToOneField(
+ catalogi_service = models.ForeignKey(
"zgw_consumers.Service",
verbose_name=_("Catalogi API"),
on_delete=models.PROTECT,
@@ -153,7 +171,11 @@ class ObjectsAPIConfig(SingletonModel):
)
class Meta:
- verbose_name = _("Objects API configuration")
+ verbose_name = _("Objects API group")
+ verbose_name_plural = _("Objects API groups")
+
+ def __str__(self) -> str:
+ return self.name
def clean(self) -> None:
super().clean()
@@ -174,6 +196,7 @@ def clean(self) -> None:
)
def apply_defaults_to(self, options):
+ options.setdefault("objects_api_group", self)
options.setdefault("version", 1)
options.setdefault("objecttype", self.objecttype)
options.setdefault("objecttype_version", self.objecttype_version)
diff --git a/src/openforms/registrations/contrib/objects_api/plugin.py b/src/openforms/registrations/contrib/objects_api/plugin.py
index ae1bc5d259..20647e061b 100644
--- a/src/openforms/registrations/contrib/objects_api/plugin.py
+++ b/src/openforms/registrations/contrib/objects_api/plugin.py
@@ -17,7 +17,7 @@
from .checks import check_config
from .client import get_objects_client
from .config import ObjectsAPIOptionsSerializer
-from .models import ObjectsAPIConfig
+from .models import ObjectsAPIConfig, ObjectsAPIGroupConfig
from .registration_variables import register as variables_registry
from .submission_registration import HANDLER_MAPPING
from .typing import RegistrationOptions
@@ -49,6 +49,15 @@ class ObjectsAPIRegistration(BasePlugin):
verbose_name = _("Objects API registration")
configuration_options = ObjectsAPIOptionsSerializer
+ @staticmethod
+ def get_objects_api_config(options: RegistrationOptions) -> ObjectsAPIGroupConfig:
+ objects_api_group = options.get("objects_api_group")
+ if objects_api_group is None:
+ config = ObjectsAPIConfig.get_solo()
+ assert isinstance(config, ObjectsAPIConfig)
+ objects_api_group = config.default_objects_api_group
+ return objects_api_group # type: ignore | can it really be None?
+
@override
def register_submission(
self, submission: Submission, options: RegistrationOptions
@@ -59,8 +68,7 @@ def register_submission(
will be created differently. The actual logic lives in the ``submission_registration`` submodule.
"""
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
+ config = self.get_objects_api_config(options)
config.apply_defaults_to(options)
handler = HANDLER_MAPPING[options["version"]]
@@ -72,7 +80,7 @@ def register_submission(
options=options,
)
- with get_objects_client() as objects_client:
+ with get_objects_client(config) as objects_client:
response = execute_unless_result_exists(
partial(objects_client.create_object, object_data=object_data),
submission,
@@ -108,8 +116,7 @@ def get_custom_templatetags_libraries(self) -> list[str]:
def update_payment_status(
self, submission: Submission, options: RegistrationOptions
) -> dict[str, Any] | None:
- config = ObjectsAPIConfig.get_solo()
- assert isinstance(config, ObjectsAPIConfig)
+ config = self.get_objects_api_config(options)
config.apply_defaults_to(options)
handler = HANDLER_MAPPING[options["version"]]
@@ -121,7 +128,7 @@ def update_payment_status(
return
object_url = submission.registration_result["url"]
- with get_objects_client() as objects_client:
+ with get_objects_client(config) as objects_client:
response = objects_client.patch(
url=object_url,
json=updated_object_data,
diff --git a/src/openforms/registrations/contrib/objects_api/submission_registration.py b/src/openforms/registrations/contrib/objects_api/submission_registration.py
index 617ec1de68..71a5200087 100644
--- a/src/openforms/registrations/contrib/objects_api/submission_registration.py
+++ b/src/openforms/registrations/contrib/objects_api/submission_registration.py
@@ -219,7 +219,7 @@ def save_registration_data(
submission_attachments: list[ObjectsAPISubmissionAttachment] = []
with (
- get_documents_client() as documents_client,
+ get_documents_client(options["objects_api_group"]) as documents_client,
save_and_raise(registration_data, submission_attachments),
):
if not registration_data.pdf_url:
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointTests/ObjecttypeVersionsAPIEndpointTests.test_list_objecttype_verions_unknown_objecttype.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointTests/ObjecttypeVersionsAPIEndpointTests.test_list_objecttype_versions_unknown_objecttype.yaml
similarity index 100%
rename from src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointTests/ObjecttypeVersionsAPIEndpointTests.test_list_objecttype_verions_unknown_objecttype.yaml
rename to src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointTests/ObjecttypeVersionsAPIEndpointTests.test_list_objecttype_versions_unknown_objecttype.yaml
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_verions_unknown_objecttype.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_verions_unknown_objecttype.yaml
deleted file mode 100644
index bbc4f89c37..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_verions_unknown_objecttype.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes/39da819c-ac6c-4037-ae2b-6bfc39f6564b/versions
- response:
- body:
- string: '{"count":0,"next":null,"previous":null,"results":[]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '52'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_versions.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_versions.yaml
deleted file mode 100644
index f89fab844b..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_list_objecttype_versions.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions
- response:
- body:
- string: '{"count":1,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1","version":1,"objectType":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","status":"published","jsonSchema":{"$id":"https://example.com/tree.schema.json","type":"object","title":"Tree","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"height":{"type":"integer","description":"The
- height of the tree."}}},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"}]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '585'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_staff_user_required.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_staff_user_required.yaml
deleted file mode 100644
index f89fab844b..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypeVersionsAPIEndpointsTests/ObjecttypeVersionsAPIEndpointsTests.test_staff_user_required.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions
- response:
- body:
- string: '{"count":1,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1","version":1,"objectType":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","status":"published","jsonSchema":{"$id":"https://example.com/tree.schema.json","type":"object","title":"Tree","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"height":{"type":"integer","description":"The
- height of the tree."}}},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"}]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '585'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes.yaml
deleted file mode 100644
index cdabace3c7..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes
- response:
- body:
- string: '{"count":2,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3"]}]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '1407'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_default_objects_api_group.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_default_objects_api_group.yaml
new file mode 100644
index 0000000000..a02d0b7bb3
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_default_objects_api_group.yaml
@@ -0,0 +1,39 @@
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Authorization:
+ - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.31.0
+ method: GET
+ uri: http://localhost:8001/api/v2/objecttypes
+ response:
+ body:
+ string: '{"count":5,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e","uuid":"644ab597-e88c-43c0-8321-f12113510b0e","name":"Fieldset
+ component","namePlural":"Fieldset component","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705","uuid":"f1dde4fe-b7f9-46dc-84ae-429ae49e3705","name":"Geo
+ in data","namePlural":"Geo in data","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2","uuid":"527b8408-7421-4808-a744-43ccb7bdaaa2","name":"File
+ Uploads","namePlural":"File Uploads","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2"]}]}'
+ headers:
+ Allow:
+ - GET, POST, HEAD, OPTIONS
+ Content-Length:
+ - '3229'
+ Content-Type:
+ - application/json
+ Referrer-Policy:
+ - same-origin
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_explicit_objects_api_group.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_explicit_objects_api_group.yaml
new file mode 100644
index 0000000000..a02d0b7bb3
--- /dev/null
+++ b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_list_objecttypes_explicit_objects_api_group.yaml
@@ -0,0 +1,39 @@
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Authorization:
+ - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.31.0
+ method: GET
+ uri: http://localhost:8001/api/v2/objecttypes
+ response:
+ body:
+ string: '{"count":5,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e","uuid":"644ab597-e88c-43c0-8321-f12113510b0e","name":"Fieldset
+ component","namePlural":"Fieldset component","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705","uuid":"f1dde4fe-b7f9-46dc-84ae-429ae49e3705","name":"Geo
+ in data","namePlural":"Geo in data","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2","uuid":"527b8408-7421-4808-a744-43ccb7bdaaa2","name":"File
+ Uploads","namePlural":"File Uploads","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2"]}]}'
+ headers:
+ Allow:
+ - GET, POST, HEAD, OPTIONS
+ Content-Length:
+ - '3229'
+ Content-Type:
+ - application/json
+ Referrer-Policy:
+ - same-origin
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_staff_user_required.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_staff_user_required.yaml
index cdabace3c7..a02d0b7bb3 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_staff_user_required.yaml
+++ b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointTests/ObjecttypesAPIEndpointTests.test_staff_user_required.yaml
@@ -16,12 +16,15 @@ interactions:
uri: http://localhost:8001/api/v2/objecttypes
response:
body:
- string: '{"count":2,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3"]}]}'
+ string: '{"count":5,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e","uuid":"644ab597-e88c-43c0-8321-f12113510b0e","name":"Fieldset
+ component","namePlural":"Fieldset component","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/644ab597-e88c-43c0-8321-f12113510b0e/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705","uuid":"f1dde4fe-b7f9-46dc-84ae-429ae49e3705","name":"Geo
+ in data","namePlural":"Geo in data","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/f1dde4fe-b7f9-46dc-84ae-429ae49e3705/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2","uuid":"527b8408-7421-4808-a744-43ccb7bdaaa2","name":"File
+ Uploads","namePlural":"File Uploads","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/527b8408-7421-4808-a744-43ccb7bdaaa2/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2"]}]}'
headers:
Allow:
- GET, POST, HEAD, OPTIONS
Content-Length:
- - '1407'
+ - '3229'
Content-Type:
- application/json
Referrer-Policy:
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_list_objecttypes.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_list_objecttypes.yaml
deleted file mode 100644
index cdabace3c7..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_list_objecttypes.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes
- response:
- body:
- string: '{"count":2,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3"]}]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '1407'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_staff_user_required.yaml b/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_staff_user_required.yaml
deleted file mode 100644
index cdabace3c7..0000000000
--- a/src/openforms/registrations/contrib/objects_api/tests/files/vcr_cassettes/ObjecttypesAPIEndpointsTests/ObjecttypesAPIEndpointsTests.test_staff_user_required.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-interactions:
-- request:
- body: null
- headers:
- Accept:
- - '*/*'
- Accept-Encoding:
- - gzip, deflate, br
- Authorization:
- - Token 171be5abaf41e7856b423ad513df1ef8f867ff48
- Connection:
- - keep-alive
- User-Agent:
- - python-requests/2.31.0
- method: GET
- uri: http://localhost:8001/api/v2/objecttypes
- response:
- body:
- string: '{"count":2,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3"]}]}'
- headers:
- Allow:
- - GET, POST, HEAD, OPTIONS
- Content-Length:
- - '1407'
- Content-Type:
- - application/json
- Referrer-Policy:
- - same-origin
- X-Content-Type-Options:
- - nosniff
- X-Frame-Options:
- - DENY
- status:
- code: 200
- message: OK
-version: 1
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_api_endpoints.py b/src/openforms/registrations/contrib/objects_api/tests/test_api_endpoints.py
index 96778e60a6..1ab1b177a8 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_api_endpoints.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_api_endpoints.py
@@ -8,6 +8,7 @@
from openforms.accounts.tests.factories import StaffUserFactory, UserFactory
from openforms.utils.tests.vcr import OFVCRMixin
+from ..models import ObjectsAPIConfig
from .test_objecttypes_client import get_test_config
@@ -21,8 +22,8 @@ def setUp(self) -> None:
self.endpoint = reverse_lazy("api:objects_api:object-types")
patcher = patch(
- "openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
- return_value=get_test_config(),
+ "openforms.registrations.contrib.objects_api.api.views.ObjectsAPIConfig.get_solo",
+ return_value=ObjectsAPIConfig(default_objects_api_group=get_test_config()),
)
self.config_mock = patcher.start()
@@ -51,31 +52,50 @@ def test_staff_user_required(self):
self.assertEqual(response.status_code, status.HTTP_200_OK)
- def test_list_objecttypes(self):
+ def test_list_objecttypes_default_objects_api_group(self):
+ # As no `ObjectsAPIGroupConfig` is persisted, the endpoint implementation
+ # will default to the `ObjectsAPIConfig.default_objects_api_group`.
+ # This test is not duplicated for the other endpoints.
staff_user = StaffUserFactory.create()
self.client.force_authenticate(user=staff_user)
response = self.client.get(self.endpoint)
+ tree_objecttype = next(obj for obj in response.json() if obj["name"] == "Tree")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
- response.json(),
- [
- {
- "dataClassification": "confidential",
- "name": "Tree",
- "namePlural": "Trees",
- "url": "http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f",
- "uuid": "3edfdaf7-f469-470b-a391-bb7ea015bd6f",
- },
- {
- "dataClassification": "open",
- "name": "Person",
- "namePlural": "Persons",
- "url": "http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48",
- "uuid": "8e46e0a5-b1b4-449b-b9e9-fa3cea655f48",
- },
- ],
+ tree_objecttype,
+ {
+ "dataClassification": "confidential",
+ "name": "Tree",
+ "namePlural": "Trees",
+ "url": "http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f",
+ "uuid": "3edfdaf7-f469-470b-a391-bb7ea015bd6f",
+ },
+ )
+
+ def test_list_objecttypes_explicit_objects_api_group(self):
+ staff_user = StaffUserFactory.create()
+ self.client.force_authenticate(user=staff_user)
+
+ config = get_test_config()
+ config.objecttypes_service.save()
+ config.save()
+
+ response = self.client.get(self.endpoint, data={"objects_api_group": config.pk})
+
+ tree_objecttype = next(obj for obj in response.json() if obj["name"] == "Tree")
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(
+ tree_objecttype,
+ {
+ "dataClassification": "confidential",
+ "name": "Tree",
+ "namePlural": "Trees",
+ "url": "http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f",
+ "uuid": "3edfdaf7-f469-470b-a391-bb7ea015bd6f",
+ },
)
@@ -91,8 +111,8 @@ def setUp(self) -> None:
)
patcher = patch(
- "openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
- return_value=get_test_config(),
+ "openforms.registrations.contrib.objects_api.api.views.ObjectsAPIConfig.get_solo",
+ return_value=ObjectsAPIConfig(default_objects_api_group=get_test_config()),
)
self.config_mock = patcher.start()
@@ -130,7 +150,7 @@ def test_list_objecttype_versions(self):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), [{"status": "published", "version": 1}])
- def test_list_objecttype_verions_unknown_objecttype(self):
+ def test_list_objecttype_versions_unknown_objecttype(self):
staff_user = StaffUserFactory.create()
self.client.force_authenticate(user=staff_user)
@@ -158,8 +178,8 @@ def setUp(self) -> None:
self.endpoint = reverse_lazy("api:objects_api:target-paths")
patcher = patch(
- "openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
- return_value=get_test_config(),
+ "openforms.registrations.contrib.objects_api.api.views.ObjectsAPIConfig.get_solo",
+ return_value=ObjectsAPIConfig(default_objects_api_group=get_test_config()),
)
self.config_mock = patcher.start()
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_backend.py b/src/openforms/registrations/contrib/objects_api/tests/test_backend.py
index 48608741d0..23b67da832 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_backend.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_backend.py
@@ -17,7 +17,7 @@
SubmissionFileAttachmentFactory,
)
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
@@ -34,18 +34,20 @@ def setUp(self):
super().setUp()
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ )
)
config_patcher = patch(
- "openforms.registrations.contrib.objects_api.models.ObjectsAPIConfig.get_solo",
+ "openforms.registrations.contrib.objects_api.plugin.ObjectsAPIConfig.get_solo",
return_value=config,
)
self.mock_get_config = config_patcher.start()
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_backend_v1.py b/src/openforms/registrations/contrib/objects_api/tests/test_backend_v1.py
index 66dc679314..110db69452 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_backend_v1.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_backend_v1.py
@@ -19,7 +19,7 @@
)
from ....constants import RegistrationAttribute
-from ..models import ObjectsAPIConfig, ObjectsAPIRegistrationData
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig, ObjectsAPIRegistrationData
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
from ..submission_registration import ObjectsAPIV1Handler
from ..typing import RegistrationOptionsV1
@@ -50,51 +50,53 @@ def setUp(self):
super().setUp()
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
- objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
- objecttype_version=1,
- productaanvraag_type="terugbelnotitie",
- informatieobjecttype_submission_report="https://catalogi.nl/api/v1/informatieobjecttypen/1",
- informatieobjecttype_submission_csv="https://catalogi.nl/api/v1/informatieobjecttypen/4",
- informatieobjecttype_attachment="https://catalogi.nl/api/v1/informatieobjecttypen/3",
- organisatie_rsin="000000000",
- content_json=textwrap.dedent(
- """
- {
- "bron": {
- "naam": "Open Formulieren",
- "kenmerk": "{{ submission.kenmerk }}"
- },
- "type": "{{ productaanvraag_type }}",
- "aanvraaggegevens": {% json_summary %},
- "taal": "{{ submission.language_code }}",
- "betrokkenen": [
- {
- "inpBsn" : "{{ variables.auth_bsn }}",
- "rolOmschrijvingGeneriek" : "initiator"
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
+ objecttype_version=1,
+ productaanvraag_type="terugbelnotitie",
+ informatieobjecttype_submission_report="https://catalogi.nl/api/v1/informatieobjecttypen/1",
+ informatieobjecttype_submission_csv="https://catalogi.nl/api/v1/informatieobjecttypen/4",
+ informatieobjecttype_attachment="https://catalogi.nl/api/v1/informatieobjecttypen/3",
+ organisatie_rsin="000000000",
+ content_json=textwrap.dedent(
+ """
+ {
+ "bron": {
+ "naam": "Open Formulieren",
+ "kenmerk": "{{ submission.kenmerk }}"
+ },
+ "type": "{{ productaanvraag_type }}",
+ "aanvraaggegevens": {% json_summary %},
+ "taal": "{{ submission.language_code }}",
+ "betrokkenen": [
+ {
+ "inpBsn" : "{{ variables.auth_bsn }}",
+ "rolOmschrijvingGeneriek" : "initiator"
+ }
+ ],
+ "pdf": "{{ submission.pdf_url }}",
+ "csv": "{{ submission.csv_url }}",
+ "bijlagen": {% uploaded_attachment_urls %},
+ "payment": {
+ "completed": {% if payment.completed %}true{% else %}false{% endif %},
+ "amount": {{ payment.amount }},
+ "public_order_ids": {{ payment.public_order_ids }}
}
- ],
- "pdf": "{{ submission.pdf_url }}",
- "csv": "{{ submission.csv_url }}",
- "bijlagen": {% uploaded_attachment_urls %},
- "payment": {
- "completed": {% if payment.completed %}true{% else %}false{% endif %},
- "amount": {{ payment.amount }},
- "public_order_ids": {{ payment.public_order_ids }}
- }
- }"""
- ),
+ }"""
+ ),
+ )
)
config_patcher = patch(
- "openforms.registrations.contrib.objects_api.models.ObjectsAPIConfig.get_solo",
+ "openforms.registrations.contrib.objects_api.plugin.ObjectsAPIConfig.get_solo",
return_value=config,
)
self.mock_get_config = config_patcher.start()
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_backend_v2.py b/src/openforms/registrations/contrib/objects_api/tests/test_backend_v2.py
index d11930e1ce..520630cd89 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_backend_v2.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_backend_v2.py
@@ -15,7 +15,7 @@
)
from openforms.utils.tests.vcr import OFVCRMixin
-from ..models import ObjectsAPIConfig, ObjectsAPIRegistrationData
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig, ObjectsAPIRegistrationData
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
from ..submission_registration import ObjectsAPIV2Handler
from ..typing import RegistrationOptionsV2
@@ -35,27 +35,29 @@ def setUp(self):
super().setUp()
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="http://localhost:8002/api/v2/",
- api_type=APITypes.orc,
- oas="https://example.com/",
- header_key="Authorization",
- # See the docker compose fixtures:
- header_value="Token 7657474c3d75f56ae0abd0d1bf7994b09964dca9",
- auth_type=AuthTypes.api_key,
- ),
- drc_service=ServiceFactory.build(
- api_root="http://localhost:8003/documenten/api/v1/",
- api_type=APITypes.drc,
- # See the docker compose fixtures:
- client_id="test_client_id",
- secret="test_secret_key",
- auth_type=AuthTypes.zgw,
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="http://localhost:8002/api/v2/",
+ api_type=APITypes.orc,
+ oas="https://example.com/",
+ header_key="Authorization",
+ # See the docker compose fixtures:
+ header_value="Token 7657474c3d75f56ae0abd0d1bf7994b09964dca9",
+ auth_type=AuthTypes.api_key,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="http://localhost:8003/documenten/api/v1/",
+ api_type=APITypes.drc,
+ # See the docker compose fixtures:
+ client_id="test_client_id",
+ secret="test_secret_key",
+ auth_type=AuthTypes.zgw,
+ ),
+ )
)
config_patcher = patch(
- "openforms.registrations.contrib.objects_api.models.ObjectsAPIConfig.get_solo",
+ "openforms.registrations.contrib.objects_api.plugin.ObjectsAPIConfig.get_solo",
return_value=config,
)
self.mock_get_config = config_patcher.start()
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_config_checks.py b/src/openforms/registrations/contrib/objects_api/tests/test_config_checks.py
index 89d453c0d5..98bd647c0c 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_config_checks.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_config_checks.py
@@ -1,7 +1,4 @@
-from copy import copy
-from unittest.mock import patch
-
-from django.test import SimpleTestCase
+from django.test import TestCase
import requests
import requests_mock
@@ -9,24 +6,23 @@
from zgw_consumers.test.factories import ServiceFactory
from openforms.plugins.exceptions import InvalidPluginConfiguration
-from openforms.utils.tests.nlx import DisableNLXRewritingMixin
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIGroupConfig
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
-class ConfigCheckTests(DisableNLXRewritingMixin, SimpleTestCase):
+class ConfigCheckTests(TestCase):
def setUp(self):
super().setUp()
- self.config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
+ self.config = ObjectsAPIGroupConfig.objects.create(
+ objects_service=ServiceFactory.create(
api_root="https://objects.example.com/api/v1/",
),
- objecttypes_service=ServiceFactory.build(
+ objecttypes_service=ServiceFactory.create(
api_root="https://objecttypes.example.com/api/v1/",
),
- drc_service=ServiceFactory.build(
+ drc_service=ServiceFactory.create(
api_root="https://documents.example.com/api/v1/",
api_type=APITypes.drc,
),
@@ -35,12 +31,6 @@ def setUp(self):
objecttype_version=42,
organisatie_rsin="123456782",
)
- patcher = patch(
- "openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
- return_value=self.config,
- )
- self.mock_get_solo = patcher.start()
- self.addCleanup(patcher.stop)
def _mockForValidServiceConfiguration(self, m: requests_mock.Mocker) -> None:
m.get(
@@ -58,6 +48,7 @@ def _mockForValidServiceConfiguration(self, m: requests_mock.Mocker) -> None:
def test_no_objects_service_configured(self):
self.config.objects_service = None
+ self.config.save()
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
with self.assertRaises(InvalidPluginConfiguration):
@@ -71,6 +62,7 @@ def test_no_objecttypes_service_configured(self, m: requests_mock.Mocker):
json={"results": []},
)
self.config.objecttypes_service = None
+ self.config.save()
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
with self.assertRaises(InvalidPluginConfiguration):
@@ -127,6 +119,7 @@ def test_objecttypes_service_misconfigured_redirect(self, m):
@requests_mock.Mocker()
def test_no_documents_service_configured(self, m):
self.config.drc_service = None
+ self.config.save()
m.get(
"https://objects.example.com/api/v1/objects?pageSize=1",
json={"results": []},
@@ -153,10 +146,9 @@ def test_invalid_url_references_with_error(self, m):
)
for field in fields:
with self.subTest(field=field):
- config = copy(self.config)
- assert not getattr(config, field, "")
- setattr(config, field, "https://example.com")
- self.mock_get_solo.return_value = config
+ assert not getattr(self.config, field, "")
+ setattr(self.config, field, "https://example.com")
+ self.config.save()
with self.assertRaises(InvalidPluginConfiguration):
plugin.check_config()
@@ -174,10 +166,9 @@ def test_invalid_url_references_with_unexpected_status(self, m):
)
for field in fields:
with self.subTest(field=field):
- config = copy(self.config)
- assert not getattr(config, field, "")
- setattr(config, field, "https://example.com")
- self.mock_get_solo.return_value = config
+ assert not getattr(self.config, field, "")
+ setattr(self.config, field, "https://example.com")
+ self.config.save()
with self.assertRaises(InvalidPluginConfiguration):
plugin.check_config()
@@ -201,10 +192,9 @@ def test_valid_url_references(self, m):
)
for field in fields:
with self.subTest(field=field):
- config = copy(self.config)
- assert not getattr(config, field, "")
- setattr(config, field, "https://example.com")
- self.mock_get_solo.return_value = config
+ assert not getattr(self.config, field, "")
+ setattr(self.config, field, "https://example.com")
+ self.config.save()
try:
plugin.check_config()
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py b/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py
index 1e412bb147..3cc0c6efd7 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py
@@ -1,6 +1,6 @@
from django.db.migrations.state import StateApps
-from zgw_consumers.constants import AuthTypes
+from zgw_consumers.constants import APITypes, AuthTypes
from openforms.registrations.contrib.objects_api.plugin import (
PLUGIN_IDENTIFIER as OBJECTS_API_PLUGIN_IDENTIFIER,
@@ -177,3 +177,245 @@ def test_migration_does_nothing_if_no_objects_api_config(self):
"registrations_objects_api", "ObjectsAPIConfig"
)
self.assertRaises(ObjectsAPIConfig.DoesNotExist, ObjectsAPIConfig.objects.get)
+
+
+class MoveExistingObjectsAPIConfigMigrationTests(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0016_objectsapigroupconfig"
+ migrate_to = "0017_move_singleton_data"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+ Service = apps.get_model("zgw_consumers", "Service")
+
+ objects_api = Service.objects.create(
+ label="Objects API",
+ api_root="http://objectsapi.nl/api/v1/",
+ api_type=APITypes.orc,
+ )
+ objecttypes_api = Service.objects.create(
+ label="Objecttypes API",
+ api_root="http://objecttypesapi.nl/api/v1/",
+ api_type=APITypes.orc,
+ )
+ documents_api = Service.objects.create(
+ label="Documents API",
+ api_root="http://documentsapi.nl/api/v1/",
+ api_type=APITypes.drc,
+ )
+ catalogi_api = Service.objects.create(
+ label="Catalogi API",
+ api_root="http://catalogiapi.nl/api/v1/",
+ api_type=APITypes.ztc,
+ )
+
+ ObjectsAPIConfig.objects.create(
+ objects_service=objects_api,
+ objecttypes_service=objecttypes_api,
+ drc_service=documents_api,
+ catalogi_service=catalogi_api,
+ objecttype="http://objecttypesapi.nl/api/v1/objecttypes/1",
+ objecttype_version=1,
+ informatieobjecttype_attachment="https://catalogiapi.nl/api/v1/informatieobjecttypen/1",
+ informatieobjecttype_submission_csv="https://catalogiapi.nl/api/v1/informatieobjecttypen/2",
+ informatieobjecttype_submission_report="https://catalogiapi.nl/api/v1/informatieobjecttypen/3",
+ organisatie_rsin="100000009",
+ productaanvraag_type="testproduct",
+ content_json="{{ content_json }}",
+ payment_status_update_json="{{ payment_status_update_json }}",
+ )
+
+ def test_services_migrated_correctly(self):
+ ObjectsAPIGroupConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+
+ migrated_services = ObjectsAPIGroupConfig.objects.all()
+
+ self.assertEqual(1, migrated_services.count())
+
+ group = migrated_services.get()
+
+ self.assertEqual(group.objects_service.label, "Objects API")
+ self.assertEqual(group.objecttypes_service.label, "Objecttypes API")
+ self.assertEqual(group.drc_service.label, "Documents API")
+ self.assertEqual(group.catalogi_service.label, "Catalogi API")
+ self.assertEqual(
+ group.objecttype, "http://objecttypesapi.nl/api/v1/objecttypes/1"
+ )
+ self.assertEqual(group.objecttype_version, 1)
+ self.assertEqual(
+ group.informatieobjecttype_attachment,
+ "https://catalogiapi.nl/api/v1/informatieobjecttypen/1",
+ )
+ self.assertEqual(
+ group.informatieobjecttype_submission_csv,
+ "https://catalogiapi.nl/api/v1/informatieobjecttypen/2",
+ )
+ self.assertEqual(
+ group.informatieobjecttype_submission_report,
+ "https://catalogiapi.nl/api/v1/informatieobjecttypen/3",
+ )
+ self.assertEqual(group.organisatie_rsin, "100000009")
+ self.assertEqual(group.productaanvraag_type, "testproduct")
+ self.assertEqual(group.content_json, "{{ content_json }}")
+ self.assertEqual(
+ group.payment_status_update_json, "{{ payment_status_update_json }}"
+ )
+
+
+class ReconfigureSoloModelBackwardsMigrationTests(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0017_move_singleton_data"
+ migrate_to = "0016_objectsapigroupconfig"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ ObjectsAPIConfig.objects.create()
+ self.objects_api_group_1 = ObjectsAPIGroupConfig.objects.create(
+ name="ZGW API 1", organisatie_rsin="100000001"
+ )
+ self.objects_api_group_2 = ObjectsAPIGroupConfig.objects.create(
+ name="ZGW API 2", organisatie_rsin="100000002"
+ )
+ self.assertTrue(self.objects_api_group_1.pk < self.objects_api_group_2.pk)
+
+ def test_solo_reconfigured_correctly(self):
+ ObjectsAPIConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ solo = ObjectsAPIConfig.objects.get()
+
+ self.assertEqual(solo.organisatie_rsin, "100000001")
+
+
+class BackwardsMigrationNoObjectsAPIGroupTests(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0017_move_singleton_data"
+ migrate_to = "0016_objectsapigroupconfig"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ ObjectsAPIConfig.objects.create()
+
+ def test_solo_reconfigured_correctly(self):
+ ObjectsAPIConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ solo = ObjectsAPIConfig.objects.get()
+
+ self.assertIsNone(solo.objects_service)
+
+
+class NoObjectsAPIConfigDoesntCreateObjectsAPIGroupMigrationTest(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0016_objectsapigroupconfig"
+ migrate_to = "0017_move_singleton_data"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ self.assertFalse(ObjectsAPIConfig.objects.exists())
+
+ def test_no_zgw_api_group_created(self):
+ ObjectsAPIGroupConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+
+ self.assertFalse(ObjectsAPIGroupConfig.objects.exists())
+
+
+class AddDefaultToSoloModelTests(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0018_alter_objectsapiconfig_options_and_more"
+ migrate_to = "0019_add_default"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+ Service = apps.get_model("zgw_consumers", "Service")
+
+ objects_api = Service.objects.create(
+ label="Objects API",
+ api_root="http://objectsapi.nl/api/v1/",
+ api_type=APITypes.orc,
+ )
+ objecttypes_api = Service.objects.create(
+ label="Objecttypes API",
+ api_root="http://objecttypesapi.nl/api/v1/",
+ api_type=APITypes.orc,
+ )
+ documents_api = Service.objects.create(
+ label="Documents API",
+ api_root="http://documentsapi.nl/api/v1/",
+ api_type=APITypes.drc,
+ )
+ catalogi_api = Service.objects.create(
+ label="Catalogi API",
+ api_root="http://catalogiapi.nl/api/v1/",
+ api_type=APITypes.ztc,
+ )
+
+ ObjectsAPIConfig.objects.create()
+ self.objects_api_group = ObjectsAPIGroupConfig.objects.create(
+ name="Objects API",
+ objects_service=objects_api,
+ objecttypes_service=objecttypes_api,
+ drc_service=documents_api,
+ catalogi_service=catalogi_api,
+ )
+
+ def test_services_migrated_correctly(self):
+ ObjectsAPIConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ solo = ObjectsAPIConfig.objects.get()
+
+ self.assertEqual(solo.default_objects_api_group.pk, self.objects_api_group.pk)
+
+
+class NoObjectsAPIGroupLeavesConfigEmptyMigrationTest(TestMigrations):
+ app = "registrations_objects_api"
+ migrate_from = "0018_alter_objectsapiconfig_options_and_more"
+ migrate_to = "0019_add_default"
+
+ def setUpBeforeMigration(self, apps: StateApps):
+ ObjectsAPIGroupConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIGroupConfig"
+ )
+ ObjectsAPIConfig = apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ self.assertFalse(ObjectsAPIGroupConfig.objects.exists())
+
+ ObjectsAPIConfig.objects.create()
+
+ def test_no_zgw_api_group_created(self):
+ ObjectsAPIConfig = self.apps.get_model(
+ "registrations_objects_api", "ObjectsAPIConfig"
+ )
+
+ solo = ObjectsAPIConfig.objects.get()
+
+ self.assertIsNone(solo.default_objects_api_group)
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_models.py b/src/openforms/registrations/contrib/objects_api/tests/test_models.py
index 92fffd72fc..f29b764750 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_models.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_models.py
@@ -4,13 +4,13 @@
from zgw_consumers.constants import APITypes
from zgw_consumers.test.factories import ServiceFactory
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIGroupConfig
class ObjectsAPIConfigTests(TestCase):
def test_invalid_objecttypes_url(self):
- config = ObjectsAPIConfig(
+ config = ObjectsAPIGroupConfig(
objecttypes_service=ServiceFactory.build(
api_root="https://objecttypen.nl/api/v1/",
api_type=APITypes.orc,
@@ -21,7 +21,7 @@ def test_invalid_objecttypes_url(self):
self.assertRaises(ValidationError, config.clean)
def test_valid_objecttypes_url(self):
- config = ObjectsAPIConfig(
+ config = ObjectsAPIGroupConfig(
objecttypes_service=ServiceFactory.build(
api_root="https://objecttypen.nl/api/v1/",
api_type=APITypes.orc,
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_objecttypes_client.py b/src/openforms/registrations/contrib/objects_api/tests/test_objecttypes_client.py
index 255ede8d72..1f4c5dbacd 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_objecttypes_client.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_objecttypes_client.py
@@ -1,5 +1,4 @@
from pathlib import Path
-from unittest.mock import patch
from django.test import TestCase
@@ -9,12 +8,13 @@
from openforms.utils.tests.vcr import OFVCRMixin
from ..client import get_objecttypes_client
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIGroupConfig
-def get_test_config() -> ObjectsAPIConfig:
- """Returns a preconfigured ``ObjectsAPIConfig`` instance matching the docker compose configuration."""
- return ObjectsAPIConfig(
+def get_test_config() -> ObjectsAPIGroupConfig:
+ """Returns a preconfigured ``ObjectsAPIGroupConfig`` instance matching the docker compose configuration."""
+
+ return ObjectsAPIGroupConfig(
objecttypes_service=Service(
api_root="http://localhost:8001/api/v2/",
api_type=APITypes.orc,
@@ -30,31 +30,25 @@ class ObjecttypesClientTest(OFVCRMixin, TestCase):
VCR_TEST_FILES = Path(__file__).parent / "files"
- def setUp(self) -> None:
- super().setUp()
-
- patcher = patch(
- "openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
- return_value=get_test_config(),
- )
-
- self.config_mock = patcher.start()
- self.addCleanup(patcher.stop)
+ @classmethod
+ def setUpTestData(cls) -> None:
+ super().setUpTestData()
+ cls.test_config = get_test_config()
def test_list_objecttypes(self):
- with get_objecttypes_client() as client:
+ with get_objecttypes_client(self.test_config) as client:
data = client.list_objecttypes()
self.assertEqual(len(data), 2)
def test_list_objectypes_pagination(self):
- with get_objecttypes_client() as client:
+ with get_objecttypes_client(self.test_config) as client:
data = client.list_objecttypes(page=1, page_size=1)
self.assertEqual(len(data), 1)
def test_list_objecttype_versions(self):
- with get_objecttypes_client() as client:
+ with get_objecttypes_client(self.test_config) as client:
data = client.list_objecttype_versions(
"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48"
)
@@ -62,7 +56,7 @@ def test_list_objecttype_versions(self):
self.assertEqual(len(data), 3)
def test_get_objecttype_version(self):
- with get_objecttypes_client() as client:
+ with get_objecttypes_client(self.test_config) as client:
data = client.get_objecttype_version(
"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48",
version=1,
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_template.py b/src/openforms/registrations/contrib/objects_api/tests/test_template.py
index d565d7c157..333c8aca9a 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_template.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_template.py
@@ -16,7 +16,7 @@
)
from openforms.submissions.tests.mixins import SubmissionsMixin
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
@@ -38,15 +38,17 @@ def test_default_template(self, m):
)
SubmissionFileAttachmentFactory.create(submission_step=submission.steps[0])
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
- productaanvraag_type="terugbelnotitie",
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ productaanvraag_type="terugbelnotitie",
+ )
)
m.post("https://objecten.nl/api/v1/objects", status_code=201, json={})
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
@@ -109,35 +111,37 @@ def test_default_template(self, m):
@freeze_time("2022-09-12")
def test_custom_template(self, m):
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
- content_json=textwrap.dedent(
- """
- {
- "bron": {
- "naam": "Open Formulieren",
- "kenmerk": "{{ submission.kenmerk }}"
- },
- "type": "{{ productaanvraag_type }}",
- "aanvraaggegevens": {% json_summary %},
- "taal": "{{ submission.language_code }}",
- "betrokkenen": [
- {
- "inpBsn" : "{{ variables.auth_bsn }}",
- "rolOmschrijvingGeneriek" : "initiator"
- }
- ],
- "pdf": "{{ submission.pdf_url }}",
- "csv": "{{ submission.csv_url }}",
- "bijlagen": {% uploaded_attachment_urls %}
- }"""
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ content_json=textwrap.dedent(
+ """
+ {
+ "bron": {
+ "naam": "Open Formulieren",
+ "kenmerk": "{{ submission.kenmerk }}"
+ },
+ "type": "{{ productaanvraag_type }}",
+ "aanvraaggegevens": {% json_summary %},
+ "taal": "{{ submission.language_code }}",
+ "betrokkenen": [
+ {
+ "inpBsn" : "{{ variables.auth_bsn }}",
+ "rolOmschrijvingGeneriek" : "initiator"
+ }
+ ],
+ "pdf": "{{ submission.pdf_url }}",
+ "csv": "{{ submission.csv_url }}",
+ "bijlagen": {% uploaded_attachment_urls %}
+ }"""
+ ),
+ )
)
submission = SubmissionFactory.from_components(
components_list=[
@@ -227,39 +231,41 @@ def test_custom_template(self, m):
def test_submission_with_objects_api_content_json_exceed_max_file_limit(self):
submission = SubmissionFactory.create(with_report=True)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
- content_json=textwrap.dedent(
- """
- {
- "bron": {
- "naam": "Open Formulieren",
- "kenmerk": "{{ submission.kenmerk }}"
- },
- "type": "{{ productaanvraag_type }}",
- "aanvraaggegevens": {% json_summary %},
- "taal": "{{ submission.language_code }}",
- "betrokkenen": [
- {
- "inpBsn" : "{{ variables.auth_bsn }}",
- "rolOmschrijvingGeneriek" : "initiator"
- }
- ],
- "pdf": "{{ submission.pdf_url }}",
- "csv": "{{ submission.csv_url }}",
- "bijlagen": [
- {% for attachment in submission.attachments %}
- "{{ attachment }}"{% if not forloop.last %},{% endif %}
- {% endfor %}
- ]
- }"""
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ content_json=textwrap.dedent(
+ """
+ {
+ "bron": {
+ "naam": "Open Formulieren",
+ "kenmerk": "{{ submission.kenmerk }}"
+ },
+ "type": "{{ productaanvraag_type }}",
+ "aanvraaggegevens": {% json_summary %},
+ "taal": "{{ submission.language_code }}",
+ "betrokkenen": [
+ {
+ "inpBsn" : "{{ variables.auth_bsn }}",
+ "rolOmschrijvingGeneriek" : "initiator"
+ }
+ ],
+ "pdf": "{{ submission.pdf_url }}",
+ "csv": "{{ submission.csv_url }}",
+ "bijlagen": [
+ {% for attachment in submission.attachments %}
+ "{{ attachment }}"{% if not forloop.last %},{% endif %}
+ {% endfor %}
+ ]
+ }"""
+ ),
+ )
)
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
@@ -282,15 +288,17 @@ def test_submission_with_objects_api_content_json_exceed_max_file_limit(self):
def test_submission_with_objects_api_content_json_not_valid_json(self):
submission = SubmissionFactory.create(with_report=True)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- drc_service=ServiceFactory.build(
- api_root="https://documenten.nl/api/v1/",
- api_type=APITypes.drc,
- ),
- content_json='{"key": "value",}', # Invalid JSON,
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ drc_service=ServiceFactory.build(
+ api_root="https://documenten.nl/api/v1/",
+ api_type=APITypes.drc,
+ ),
+ content_json='{"key": "value",}', # Invalid JSON,
+ )
)
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
@@ -352,9 +360,11 @@ def test_object_nulls_regression(self):
form_definition_kwargs={"slug": "stepwithnulls"},
)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(),
- drc_service=ServiceFactory.build(),
- content_json="{% json_summary %}",
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(),
+ drc_service=ServiceFactory.build(),
+ content_json="{% json_summary %}",
+ )
)
plugin = ObjectsAPIRegistration(PLUGIN_IDENTIFIER)
prefix = "openforms.registrations.contrib.objects_api"
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v1.py b/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v1.py
index 3dfcae1b4d..526b1b54d3 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v1.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v1.py
@@ -12,7 +12,7 @@
from openforms.payments.tests.factories import SubmissionPaymentFactory
from openforms.submissions.tests.factories import SubmissionFactory
-from ..models import ObjectsAPIConfig
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
@@ -41,20 +41,22 @@ def test_update_payment_status(self, m):
)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- payment_status_update_json=textwrap.dedent(
- """
- {
- "payment": {
- "completed": {% if payment.completed %}true{% else %}false{% endif %},
- "amount": {{ payment.amount }},
- "public_order_ids": [{% for order_id in payment.public_order_ids%}"{{ order_id|escapejs }}"{% if not forloop.last %},{% endif %}{% endfor %}]
- }
- }"""
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ payment_status_update_json=textwrap.dedent(
+ """
+ {
+ "payment": {
+ "completed": {% if payment.completed %}true{% else %}false{% endif %},
+ "amount": {{ payment.amount }},
+ "public_order_ids": [{% for order_id in payment.public_order_ids%}"{{ order_id|escapejs }}"{% if not forloop.last %},{% endif %}{% endfor %}]
+ }
+ }"""
+ ),
+ )
)
m.patch(
@@ -110,10 +112,12 @@ def test_template_overwritten_through_options(self, m):
)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ )
)
m.patch(
@@ -182,11 +186,13 @@ def test_no_template_specified(self, m):
)
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- payment_status_update_json="",
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ payment_status_update_json="",
+ )
)
m.patch(
diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v2.py b/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v2.py
index c18303064f..ecbf7058a9 100644
--- a/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v2.py
+++ b/src/openforms/registrations/contrib/objects_api/tests/test_update_payment_status_v2.py
@@ -15,7 +15,7 @@
from openforms.utils.tests.vcr import OFVCRMixin
from ..client import get_objects_client
-from ..models import ObjectsAPIConfig, ObjectsAPIRegistrationData
+from ..models import ObjectsAPIConfig, ObjectsAPIGroupConfig, ObjectsAPIRegistrationData
from ..plugin import PLUGIN_IDENTIFIER, ObjectsAPIRegistration
from ..typing import RegistrationOptionsV2
@@ -28,7 +28,7 @@ class ObjectsAPIPaymentStatusUpdateV2Tests(OFVCRMixin, TestCase):
def setUp(self):
super().setUp()
- config = ObjectsAPIConfig(
+ self.config_group = ObjectsAPIGroupConfig(
objects_service=ServiceFactory.build(
api_root="http://localhost:8002/api/v2/",
api_type=APITypes.orc,
@@ -40,6 +40,10 @@ def setUp(self):
),
)
+ config = ObjectsAPIConfig(
+ default_objects_api_group=self.config_group,
+ )
+
config_patcher = patch(
"openforms.registrations.contrib.objects_api.models.ObjectsAPIConfig.get_solo",
return_value=config,
@@ -50,7 +54,7 @@ def setUp(self):
def test_update_payment_status(self):
# We manually create the objects instance, to be in the same state after
# `plugin.register_submission` was called:
- with get_objects_client() as client:
+ with get_objects_client(self.config_group) as client:
data = client.create_object(
object_data=prepare_data_for_registration(
record_data={
diff --git a/src/openforms/registrations/contrib/objects_api/typing.py b/src/openforms/registrations/contrib/objects_api/typing.py
index fe3ae7c861..d87ba9409f 100644
--- a/src/openforms/registrations/contrib/objects_api/typing.py
+++ b/src/openforms/registrations/contrib/objects_api/typing.py
@@ -1,11 +1,17 @@
-from typing import Literal, TypeAlias, TypedDict
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Literal, TypeAlias, TypedDict
from typing_extensions import Required
+if TYPE_CHECKING:
+ from .models import ObjectsAPIGroupConfig
+
ConfigVersion: TypeAlias = Literal[1, 2]
class _BaseRegistrationOptions(TypedDict, total=False):
+ objects_api_group: ObjectsAPIGroupConfig
objecttype: Required[str]
objecttype_version: Required[int]
informatieobjecttype_submission_report: str
diff --git a/src/openforms/registrations/contrib/zgw_apis/plugin.py b/src/openforms/registrations/contrib/zgw_apis/plugin.py
index eb751148ba..46bd6df283 100644
--- a/src/openforms/registrations/contrib/zgw_apis/plugin.py
+++ b/src/openforms/registrations/contrib/zgw_apis/plugin.py
@@ -18,6 +18,7 @@
create_report_document,
)
from openforms.registrations.contrib.objects_api.client import get_objects_client
+from openforms.registrations.contrib.objects_api.models import ObjectsAPIConfig
from openforms.submissions.mapping import SKIP, FieldConf, apply_data_mapping
from openforms.submissions.models import Submission, SubmissionReport
from openforms.variables.utils import get_variables_for_context
@@ -498,7 +499,12 @@ def register_submission_to_objects_api(
submission, object_mapping, REGISTRATION_ATTRIBUTE, object_data
)
- with get_objects_client() as objects_client:
+ objects_api_config = ObjectsAPIConfig.get_solo()
+ assert isinstance(objects_api_config, ObjectsAPIConfig)
+
+ with get_objects_client(
+ objects_api_config.default_objects_api_group
+ ) as objects_client:
response = execute_unless_result_exists(
partial(objects_client.create_object, object_data=object_data),
submission,
diff --git a/src/openforms/registrations/contrib/zgw_apis/tests/test_backend.py b/src/openforms/registrations/contrib/zgw_apis/tests/test_backend.py
index 423ab856f0..4a0cd52468 100644
--- a/src/openforms/registrations/contrib/zgw_apis/tests/test_backend.py
+++ b/src/openforms/registrations/contrib/zgw_apis/tests/test_backend.py
@@ -15,7 +15,10 @@
from zgw_consumers.test.factories import ServiceFactory
from openforms.authentication.tests.factories import RegistratorInfoFactory
-from openforms.registrations.contrib.objects_api.models import ObjectsAPIConfig
+from openforms.registrations.contrib.objects_api.models import (
+ ObjectsAPIConfig,
+ ObjectsAPIGroupConfig,
+)
from openforms.submissions.constants import PostSubmissionEvents
from openforms.submissions.models import SubmissionStep
from openforms.submissions.tasks import pre_registration
@@ -1495,31 +1498,33 @@ def test_document_size_argument_present(self, m):
)
def test_submission_with_zgw_and_objects_api_backends(self, m, obj_api_config):
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
- objecttype_version=1,
- organisatie_rsin="000000000",
- content_json=textwrap.dedent(
- """
- {
- "bron": {
- "naam": "Open Formulieren",
- "kenmerk": "{{ submission.kenmerk }}"
- },
- "type": "{{ productaanvraag_type }}",
- "aanvraaggegevens": {% json_summary %},
- "taal": "{{ submission.language_code }}",
- "betrokkenen": [
- {
- "inpBsn" : "{{ variables.auth_bsn }}",
- "rolOmschrijvingGeneriek" : "initiator"
- }
- ],
- }"""
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
+ objecttype_version=1,
+ organisatie_rsin="000000000",
+ content_json=textwrap.dedent(
+ """
+ {
+ "bron": {
+ "naam": "Open Formulieren",
+ "kenmerk": "{{ submission.kenmerk }}"
+ },
+ "type": "{{ productaanvraag_type }}",
+ "aanvraaggegevens": {% json_summary %},
+ "taal": "{{ submission.language_code }}",
+ "betrokkenen": [
+ {
+ "inpBsn" : "{{ variables.auth_bsn }}",
+ "rolOmschrijvingGeneriek" : "initiator"
+ }
+ ],
+ }"""
+ ),
+ )
)
def get_create_json_for_object(req, ctx):
diff --git a/src/openforms/registrations/contrib/zgw_apis/tests/test_backend_partial_failure.py b/src/openforms/registrations/contrib/zgw_apis/tests/test_backend_partial_failure.py
index 52039de6a2..4c6eb62dda 100644
--- a/src/openforms/registrations/contrib/zgw_apis/tests/test_backend_partial_failure.py
+++ b/src/openforms/registrations/contrib/zgw_apis/tests/test_backend_partial_failure.py
@@ -11,7 +11,10 @@
from zgw_consumers.test import generate_oas_component
from zgw_consumers.test.factories import ServiceFactory
-from openforms.registrations.contrib.objects_api.models import ObjectsAPIConfig
+from openforms.registrations.contrib.objects_api.models import (
+ ObjectsAPIConfig,
+ ObjectsAPIGroupConfig,
+)
from openforms.submissions.constants import PostSubmissionEvents, RegistrationStatuses
from openforms.submissions.tasks import pre_registration
from openforms.submissions.tests.factories import (
@@ -396,31 +399,33 @@ class ObjectsAPIPartialRegistrationFailureTests(TestCase):
)
def test_failure_after_object_creation(self, m, obj_api_config):
config = ObjectsAPIConfig(
- objects_service=ServiceFactory.build(
- api_root="https://objecten.nl/api/v1/",
- api_type=APITypes.orc,
- ),
- objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
- objecttype_version=1,
- organisatie_rsin="000000000",
- content_json=textwrap.dedent(
- """
- {
- "bron": {
- "naam": "Open Formulieren",
- "kenmerk": "{{ submission.kenmerk }}"
- },
- "type": "{{ productaanvraag_type }}",
- "aanvraaggegevens": {% json_summary %},
- "taal": "{{ submission.language_code }}",
- "betrokkenen": [
- {
- "inpBsn" : "{{ variables.auth_bsn }}",
- "rolOmschrijvingGeneriek" : "initiator"
- }
- ],
- }"""
- ),
+ default_objects_api_group=ObjectsAPIGroupConfig(
+ objects_service=ServiceFactory.build(
+ api_root="https://objecten.nl/api/v1/",
+ api_type=APITypes.orc,
+ ),
+ objecttype="https://objecttypen.nl/api/v1/objecttypes/1",
+ objecttype_version=1,
+ organisatie_rsin="000000000",
+ content_json=textwrap.dedent(
+ """
+ {
+ "bron": {
+ "naam": "Open Formulieren",
+ "kenmerk": "{{ submission.kenmerk }}"
+ },
+ "type": "{{ productaanvraag_type }}",
+ "aanvraaggegevens": {% json_summary %},
+ "taal": "{{ submission.language_code }}",
+ "betrokkenen": [
+ {
+ "inpBsn" : "{{ variables.auth_bsn }}",
+ "rolOmschrijvingGeneriek" : "initiator"
+ }
+ ],
+ }"""
+ ),
+ )
)
zgw_api_group = ZGWApiGroupConfigFactory.create(
zrc_service__api_root="https://zaken.nl/api/v1/",
diff --git a/src/openforms/registrations/tests/test_views.py b/src/openforms/registrations/tests/test_views.py
index 91b6258ddc..d26e220f63 100644
--- a/src/openforms/registrations/tests/test_views.py
+++ b/src/openforms/registrations/tests/test_views.py
@@ -8,7 +8,10 @@
from zgw_consumers.test import generate_oas_component
from openforms.accounts.tests.factories import StaffUserFactory, UserFactory
-from openforms.registrations.contrib.objects_api.models import ObjectsAPIConfig
+from openforms.registrations.contrib.objects_api.models import (
+ ObjectsAPIConfig,
+ ObjectsAPIGroupConfig,
+)
from openforms.registrations.contrib.zgw_apis.models import ZgwConfig
from openforms.registrations.contrib.zgw_apis.tests.factories import (
ZGWApiGroupConfigFactory,
@@ -32,6 +35,13 @@ def setUpTestData(cls):
ztc_service__api_root="https://catalogus-2.nl/api/v1/",
)
+ cls.objects_api_group1 = ObjectsAPIGroupConfig.objects.create(
+ catalogi_service=cls.zgw_group1.ztc_service
+ )
+ cls.objects_api_group2 = ObjectsAPIGroupConfig.objects.create(
+ catalogi_service=cls.zgw_group2.ztc_service
+ )
+
def install_mocks(self, m):
informatieobjecttypen1 = [
generate_oas_component(
@@ -122,9 +132,10 @@ def test_must_be_logged_in_as_admin(self, m):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- def test_retrieve_without_filter_param(self, m):
+ def test_retrieve_without_explicit_zgw_api_group(self, m):
user = StaffUserFactory.create()
- url = reverse("api:iotypen-list")
+ url = furl(reverse("api:iotypen-list"))
+ url.args["registration_backend"] = "zgw-create-zaak"
self.client.force_login(user)
self.install_mocks(m)
@@ -133,7 +144,7 @@ def test_retrieve_without_filter_param(self, m):
"openforms.registrations.api.filters.ZgwConfig.get_solo",
return_value=ZgwConfig(default_zgw_api_group=self.zgw_group1),
):
- response = self.client.get(url)
+ response = self.client.get(url.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -141,17 +152,18 @@ def test_retrieve_without_filter_param(self, m):
self.assertEqual(len(data), 2)
- def test_retrieve_without_filter_param_no_default(self, m):
+ def test_retrieve_without_explicit_zgw_api_group_no_default(self, m):
user = StaffUserFactory.create()
- url = reverse("api:iotypen-list")
+ url = furl(reverse("api:iotypen-list"))
+ url.args["registration_backend"] = "zgw-create-zaak"
self.client.force_login(user)
- response = self.client.get(url)
+ response = self.client.get(url.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), [])
- def test_retrieve_with_filter_params(self, m):
+ def test_retrieve_with_explicit_zgw_api_group(self, m):
user = StaffUserFactory.create()
url = furl(reverse("api:iotypen-list"))
url.args["zgw_api_group"] = self.zgw_group2.pk
@@ -168,7 +180,7 @@ def test_retrieve_with_filter_params(self, m):
self.assertEqual(len(data), 1)
- def test_filter_with_invalid_param(self, m):
+ def test_filter_with_invalid_zgw_group(self, m):
user = StaffUserFactory.create()
url = furl(reverse("api:iotypen-list"))
url.args["zgw_api_group"] = "INVALID"
@@ -179,7 +191,7 @@ def test_filter_with_invalid_param(self, m):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), [])
- def test_with_object_api(self, m):
+ def test_retrieve_without_explicit_objects_api_group(self, m):
user = StaffUserFactory.create()
url = furl(reverse("api:iotypen-list"))
url.args["registration_backend"] = "objects_api"
@@ -189,7 +201,9 @@ def test_with_object_api(self, m):
with patch(
"openforms.registrations.api.filters.ObjectsAPIConfig.get_solo",
- return_value=ObjectsAPIConfig(catalogi_service=self.zgw_group1.ztc_service),
+ return_value=ObjectsAPIConfig(
+ default_objects_api_group=self.objects_api_group1
+ ),
):
response = self.client.get(url.url)
@@ -198,3 +212,42 @@ def test_with_object_api(self, m):
data = response.json()
self.assertEqual(len(data), 2)
+
+ def test_retrieve_without_explicit_objects_api_api_group_no_default(self, m):
+ user = StaffUserFactory.create()
+ url = furl(reverse("api:iotypen-list"))
+ url.args["registration_backend"] = "objects_api"
+ self.client.force_login(user)
+
+ response = self.client.get(url.url)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.json(), [])
+
+ def test_retrieve_with_explicit_objects_api_group(self, m):
+ user = StaffUserFactory.create()
+ url = furl(reverse("api:iotypen-list"))
+ url.args["objects_api_group"] = self.objects_api_group2.pk
+ url.args["registration_backend"] = "objects_api"
+ self.client.force_login(user)
+
+ self.install_mocks(m)
+
+ response = self.client.get(url.url)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ data = response.json()
+
+ self.assertEqual(len(data), 1)
+
+ def test_filter_with_invalid_objects_api_group(self, m):
+ user = StaffUserFactory.create()
+ url = furl(reverse("api:iotypen-list"))
+ url.args["objects_api_group"] = "INVALID"
+ self.client.force_login(user)
+
+ response = self.client.get(url.url)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.json(), [])