From 93802911f4f6e0a90ee83e03e7ee1338e73492c1 Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Fri, 6 Dec 2024 12:23:33 +0100 Subject: [PATCH] [#467] update objecttypes step --- src/objects/conf/base.py | 9 ++- src/objects/config/models.py | 22 ++++++ src/objects/config/objecttypes.py | 107 +++++++++++++++--------------- src/objects/core/models.py | 11 ++- 4 files changed, 89 insertions(+), 60 deletions(-) create mode 100644 src/objects/config/models.py diff --git a/src/objects/conf/base.py b/src/objects/conf/base.py index be71aeec..c3914279 100644 --- a/src/objects/conf/base.py +++ b/src/objects/conf/base.py @@ -83,11 +83,10 @@ # # Django setup configuration # -SETUP_CONFIGURATION_STEPS = [ - "objects.config.site.SiteConfigurationStep", - "objects.config.objecttypes.ObjecttypesStep", - "objects.config.demo.DemoUserStep", -] +SETUP_CONFIGURATION_STEPS = ( + "zgw_consumers.contrib.setup_configuration.steps.ServiceConfigurationStep", + "objects.config.objecttypes.ObjectTypesStep", +) # diff --git a/src/objects/config/models.py b/src/objects/config/models.py new file mode 100644 index 00000000..20714a2a --- /dev/null +++ b/src/objects/config/models.py @@ -0,0 +1,22 @@ +from django_setup_configuration.fields import DjangoModelRef +from django_setup_configuration.models import ConfigurationModel +from zgw_consumers.models import Service +from pydantic import Field + +from objects.core.models import ObjectType + + +class ObjectTypeConfigurationModel(ConfigurationModel): + service_identifier: str = DjangoModelRef(Service, "slug") + name: str = DjangoModelRef(ObjectType, "_name") + + class Meta: + django_model_refs = { + ObjectType: ( + "uuid", + ) + } + + +class ObjectTypesConfigurationModel(ConfigurationModel): + items: list[ObjectTypeConfigurationModel] = Field() diff --git a/src/objects/config/objecttypes.py b/src/objects/config/objecttypes.py index 919fdff7..243c1ce0 100644 --- a/src/objects/config/objecttypes.py +++ b/src/objects/config/objecttypes.py @@ -1,59 +1,60 @@ -from django.conf import settings - -import requests +from django.core.exceptions import ValidationError +from django.db import IntegrityError from django_setup_configuration.configuration import BaseConfigurationStep -from django_setup_configuration.exceptions import SelfTestFailed -from zgw_consumers.client import build_client -from zgw_consumers.constants import APITypes, AuthTypes +from django_setup_configuration.exceptions import ConfigurationRunFailed +from zgw_consumers.contrib.setup_configuration.models import SingleServiceConfigurationModel from zgw_consumers.models import Service +from objects.config.models import ObjectTypesConfigurationModel +from objects.core.models import ObjectType -class ObjecttypesStep(BaseConfigurationStep): - """ - Configure credentials for Objects API to request Objecttypes API - - Normal mode doesn't change the token after its initial creation. - If the token is changed, run this command with 'overwrite' flag - """ +# TODO: remove previously used django settings? +# TODO: update documenation +class ObjectTypesConfigurationStep(BaseConfigurationStep): + config_model = ObjectTypesConfigurationModel verbose_name = "Objecttypes Configuration" - required_settings = [ - "OBJECTTYPES_API_ROOT", - "OBJECTS_OBJECTTYPES_TOKEN", - ] - enable_setting = "OBJECTS_OBJECTTYPES_CONFIG_ENABLE" - - def is_configured(self) -> bool: - return Service.objects.filter(api_root=settings.OBJECTTYPES_API_ROOT).exists() - - def configure(self) -> None: - Service.objects.update_or_create( - api_root=settings.OBJECTTYPES_API_ROOT, - defaults={ - "label": "Objecttypes API", - "api_type": APITypes.orc, - "oas": settings.OBJECTTYPES_API_OAS, - "auth_type": AuthTypes.api_key, - "header_key": "Authorization", - "header_value": f"Token {settings.OBJECTS_OBJECTTYPES_TOKEN}", - }, - ) - - def test_configuration(self) -> None: - """ - This check depends on the configuration in Objecttypes - """ - client = build_client( - Service.objects.get(api_root=settings.OBJECTTYPES_API_ROOT) - ) - try: - response = client.get("objecttypes") - except requests.RequestException as exc: - raise SelfTestFailed( - "Could not Could not retrieve list of objecttypes from Objecttypes API." - ) from exc - - try: - response.json() - except requests.exceptions.JSONDecodeError: - raise SelfTestFailed("Object type version didn't have any data") + + namespace = "objecttypes" + enable_setting = "objecttypes_config_enable" + + def execute(self, model: ObjectTypesConfigurationModel) -> None: + for item in model.items: + try: + service = Service.objects.get(slug=item.service_identifier) + except Service.DoesNotExist: + raise ConfigurationRunFailed( + f"No service found with identifier {item.service_identifier}" + ) + + objecttype_kwargs = dict( + service=service, + uuid=item.uuid, + _name=item.name, + ) + + objecttype_instance = ObjectType(**objecttype_kwargs) + + try: + objecttype_instance.full_clean( + exclude=("id", "service"), validate_unique=False + ) + except ValidationError as exception: + exception_message = ( + f"Validation error(s) occured for objecttype {item.uuid}." + ) + raise ConfigurationRunFailed(exception_message) from exception + + try: + ObjectType.objects.update_or_create( + uuid=item.uuid, + defaults={ + key: value for key, value in objecttype_kwargs.items() + if key != "uuid" + } + ) + except IntegrityError as exception: + exception_message = ( + f"Failed configuring ObjectType {item.uuid}." + ) + raise ConfigurationRunFailed(exception_message) from exception diff --git a/src/objects/core/models.py b/src/objects/core/models.py index ccf4fd36..3df3af1f 100644 --- a/src/objects/core/models.py +++ b/src/objects/core/models.py @@ -1,4 +1,5 @@ import datetime +from typing import Iterable, Optional import uuid from django.contrib.gis.db.models import GeometryField @@ -41,8 +42,14 @@ def url(self): # zds_client.get_operation_url() can be used here but it increases HTTP overhead return f"{self.service.api_root}objecttypes/{self.uuid}" - def clean(self): + def clean_fields(self, exclude: Optional[Iterable[str]] = None) -> None: + super().clean_fields(exclude=exclude) + + if exclude and "service" in exclude: + return + client = build_client(self.service) + try: response = client.get(url=self.url) except (requests.RequestException, ConnectionError, ValueError) as exc: @@ -51,7 +58,7 @@ def clean(self): try: object_type_data = response.json() except requests.exceptions.JSONDecodeError: - ValidationError("Object type version didn't have any data") + raise ValidationError("Object type version didn't have any data") if not self._name: self._name = object_type_data["name"]