Skip to content

Commit

Permalink
Merge pull request #1116 from maykinmedia/feature/2262-setup-config-o…
Browse files Browse the repository at this point in the history
…penzaak-openklant

✨ [#2262] Add setup configuration steps for ZGW and KIC
  • Loading branch information
stevenbal authored Mar 29, 2024
2 parents 35b67e2 + 93b3be8 commit bf6778c
Show file tree
Hide file tree
Showing 14 changed files with 975 additions and 8 deletions.
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ django-mailer
django-image-cropping
django-log-outgoing-requests
xsdata
django-setup-configuration

# django cms
django-cms
Expand Down
3 changes: 3 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ django==4.2.11
# django-relativedelta
# django-sekizai
# django-sendfile2
# django-setup-configuration
# django-simple-certmanager
# django-sniplates
# django-solo
Expand Down Expand Up @@ -239,6 +240,8 @@ django-sessionprofile==1.0
# via
# -r requirements/base.in
# django-digid-eherkenning
django-setup-configuration==0.1.0
# via -r requirements/base.in
django-simple-certmanager==1.4.1
# via
# django-digid-eherkenning
Expand Down
5 changes: 5 additions & 0 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ django==4.2.11
# django-relativedelta
# django-sekizai
# django-sendfile2
# django-setup-configuration
# django-simple-certmanager
# django-sniplates
# django-solo
Expand Down Expand Up @@ -404,6 +405,10 @@ django-sessionprofile==1.0
# -c requirements/base.txt
# -r requirements/base.txt
# django-digid-eherkenning
django-setup-configuration==0.1.0
# via
# -c requirements/base.txt
# -r requirements/base.txt
django-simple-certmanager==1.4.1
# via
# -c requirements/base.txt
Expand Down
5 changes: 5 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ django==4.2.11
# django-relativedelta
# django-sekizai
# django-sendfile2
# django-setup-configuration
# django-silk
# django-simple-certmanager
# django-sniplates
Expand Down Expand Up @@ -447,6 +448,10 @@ django-sessionprofile==1.0
# -c requirements/ci.txt
# -r requirements/ci.txt
# django-digid-eherkenning
django-setup-configuration==0.1.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
django-silk==5.1.0
# via -r requirements/dev.in
django-simple-certmanager==1.4.1
Expand Down
6 changes: 2 additions & 4 deletions src/open_inwoner/cms/cases/views/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -940,10 +940,8 @@ def register_by_api(self, form, config: OpenKlantConfig):
if ztc and ztc.contact_subject_code:
data["onderwerp"] = ztc.contact_subject_code

if contactmomenten_client := build_client_openklant("contactmomenten"):
contactmoment = contactmomenten_client.create_contactmoment(
data, klant=klant
)
if contactmoment_client := build_client_openklant("contactmomenten"):
contactmoment = contactmoment_client.create_contactmoment(data, klant=klant)
if contactmoment:
self.log_system_action(
"registered contactmoment by API", user=self.request.user
Expand Down
103 changes: 103 additions & 0 deletions src/open_inwoner/conf/app/setup_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from ..utils import config

SETUP_CONFIGURATION_STEPS = [
"open_inwoner.configurations.bootstrap.zgw.ZakenAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.zgw.CatalogiAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.zgw.DocumentenAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.zgw.FormulierenAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.zgw.ZGWAPIsConfigurationStep",
"open_inwoner.configurations.bootstrap.kic.KlantenAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.kic.ContactmomentenAPIConfigurationStep",
"open_inwoner.configurations.bootstrap.kic.KICAPIsConfigurationStep",
]
OIP_ORGANIZATION = config("OIP_ORGANIZATION", "")

# ZGW configuration variables
ZGW_CONFIG_ENABLE = config("ZGW_CONFIG_ENABLE", default=True)
ZGW_CONFIG_ZAKEN_API_ROOT = config("ZGW_CONFIG_ZAKEN_API_ROOT", "")
if ZGW_CONFIG_ZAKEN_API_ROOT and not ZGW_CONFIG_ZAKEN_API_ROOT.endswith("/"):
ZGW_CONFIG_ZAKEN_API_ROOT = f"{ZGW_CONFIG_ZAKEN_API_ROOT.strip()}/"
ZGW_CONFIG_ZAKEN_OAS_URL = ZGW_CONFIG_ZAKEN_API_ROOT # this is still required by the form, but not actually used
ZGW_CONFIG_ZAKEN_API_CLIENT_ID = config("ZGW_CONFIG_ZAKEN_API_CLIENT_ID", "")
ZGW_CONFIG_ZAKEN_API_SECRET = config("ZGW_CONFIG_ZAKEN_API_SECRET", "")
ZGW_CONFIG_CATALOGI_API_ROOT = config("ZGW_CONFIG_CATALOGI_API_ROOT", "")
if ZGW_CONFIG_CATALOGI_API_ROOT and not ZGW_CONFIG_CATALOGI_API_ROOT.endswith("/"):
ZGW_CONFIG_CATALOGI_API_ROOT = f"{ZGW_CONFIG_CATALOGI_API_ROOT.strip()}/"
ZGW_CONFIG_CATALOGI_OAS_URL = ZGW_CONFIG_CATALOGI_API_ROOT # this is still required by the form, but not actually used
ZGW_CONFIG_CATALOGI_API_CLIENT_ID = config("ZGW_CONFIG_CATALOGI_API_CLIENT_ID", "")
ZGW_CONFIG_CATALOGI_API_SECRET = config("ZGW_CONFIG_CATALOGI_API_SECRET", "")
ZGW_CONFIG_DOCUMENTEN_API_ROOT = config("ZGW_CONFIG_DOCUMENTEN_API_ROOT", "")
if ZGW_CONFIG_DOCUMENTEN_API_ROOT and not ZGW_CONFIG_DOCUMENTEN_API_ROOT.endswith("/"):
ZGW_CONFIG_DOCUMENTEN_API_ROOT = f"{ZGW_CONFIG_DOCUMENTEN_API_ROOT.strip()}/"
ZGW_CONFIG_DOCUMENTEN_OAS_URL = ZGW_CONFIG_DOCUMENTEN_API_ROOT # this is still required by the form, but not actually used
ZGW_CONFIG_DOCUMENTEN_API_CLIENT_ID = config("ZGW_CONFIG_DOCUMENTEN_API_CLIENT_ID", "")
ZGW_CONFIG_DOCUMENTEN_API_SECRET = config("ZGW_CONFIG_DOCUMENTEN_API_SECRET", "")
ZGW_CONFIG_FORMULIEREN_API_ROOT = config("ZGW_CONFIG_FORMULIEREN_API_ROOT", "")
if ZGW_CONFIG_FORMULIEREN_API_ROOT and not ZGW_CONFIG_FORMULIEREN_API_ROOT.endswith(
"/"
):
ZGW_CONFIG_FORMULIEREN_API_ROOT = f"{ZGW_CONFIG_FORMULIEREN_API_ROOT.strip()}/"
ZGW_CONFIG_FORMULIEREN_OAS_URL = ZGW_CONFIG_FORMULIEREN_API_ROOT # this is still required by the form, but not actually used
ZGW_CONFIG_FORMULIEREN_API_CLIENT_ID = config(
"ZGW_CONFIG_FORMULIEREN_API_CLIENT_ID", ""
)
ZGW_CONFIG_FORMULIEREN_API_SECRET = config("ZGW_CONFIG_FORMULIEREN_API_SECRET", "")
# ZGW config options
ZGW_CONFIG_ZAAK_MAX_CONFIDENTIALITY = config(
"ZGW_CONFIG_ZAAK_MAX_CONFIDENTIALITY", None
)
ZGW_CONFIG_DOCUMENT_MAX_CONFIDENTIALITY = config(
"ZGW_CONFIG_DOCUMENT_MAX_CONFIDENTIALITY", None
)
ZGW_CONFIG_ACTION_REQUIRED_DEADLINE_DAYS = config("ACTION_REQUIRED_DEADLINE_DAYS", None)
ZGW_CONFIG_ALLOWED_FILE_EXTENSIONS = config("ZGW_CONFIG_ALLOWED_FILE_EXTENSIONS", None)
ZGW_CONFIG_MIJN_AANVRAGEN_TITLE_TEXT = config(
"ZGW_CONFIG_MIJN_AANVRAGEN_TITLE_TEXT", None
)
ZGW_CONFIG_ENABLE_CATEGORIES_FILTERING_WITH_ZAKEN = config(
"ZGW_CONFIG_ENABLE_CATEGORIES_FILTERING_WITH_ZAKEN", None
)
ZGW_CONFIG_SKIP_NOTIFICATION_STATUSTYPE_INFORMEREN = config(
"ZGW_CONFIG_SKIP_NOTIFICATION_STATUSTYPE_INFORMEREN", None
)
ZGW_CONFIG_REFORMAT_ESUITE_ZAAK_IDENTIFICATIE = config(
"ZGW_CONFIG_REFORMAT_ESUITE_ZAAK_IDENTIFICATIE", None
)
ZGW_CONFIG_FETCH_EHERKENNING_ZAKEN_WITH_RSIN = config(
"ZGW_CONFIG_FETCH_EHERKENNING_ZAKEN_WITH_RSIN", None
)

# KIC configuration variables
KIC_CONFIG_ENABLE = config("KIC_CONFIG_ENABLE", default=True)
KIC_CONFIG_KLANTEN_API_ROOT = config("KIC_CONFIG_KLANTEN_API_ROOT", "")
if KIC_CONFIG_KLANTEN_API_ROOT and not KIC_CONFIG_KLANTEN_API_ROOT.endswith("/"):
KIC_CONFIG_KLANTEN_API_ROOT = f"{KIC_CONFIG_KLANTEN_API_ROOT.strip()}/"
KIC_CONFIG_KLANTEN_OAS_URL = KIC_CONFIG_KLANTEN_API_ROOT # this is still required by the form, but not actually used
KIC_CONFIG_KLANTEN_API_CLIENT_ID = config("KIC_CONFIG_KLANTEN_API_CLIENT_ID", "")
KIC_CONFIG_KLANTEN_API_SECRET = config("KIC_CONFIG_KLANTEN_API_SECRET", "")
KIC_CONFIG_CONTACTMOMENTEN_API_ROOT = config("KIC_CONFIG_CONTACTMOMENTEN_API_ROOT", "")
if (
KIC_CONFIG_CONTACTMOMENTEN_API_ROOT
and not KIC_CONFIG_CONTACTMOMENTEN_API_ROOT.endswith("/")
):
KIC_CONFIG_CONTACTMOMENTEN_API_ROOT = (
f"{KIC_CONFIG_CONTACTMOMENTEN_API_ROOT.strip()}/"
)
KIC_CONFIG_CONTACTMOMENTEN_OAS_URL = KIC_CONFIG_CONTACTMOMENTEN_API_ROOT # this is still required by the form, but not actually used
KIC_CONFIG_CONTACTMOMENTEN_API_CLIENT_ID = config(
"KIC_CONFIG_CONTACTMOMENTEN_API_CLIENT_ID", ""
)
KIC_CONFIG_CONTACTMOMENTEN_API_SECRET = config(
"KIC_CONFIG_CONTACTMOMENTEN_API_SECRET", ""
)
KIC_CONFIG_REGISTER_EMAIL = config("KIC_CONFIG_REGISTER_EMAIL", None)
KIC_CONFIG_REGISTER_CONTACT_MOMENT = config("KIC_CONFIG_REGISTER_CONTACT_MOMENT", None)
KIC_CONFIG_REGISTER_BRONORGANISATIE_RSIN = config(
"KIC_CONFIG_REGISTER_BRONORGANISATIE_RSIN", None
)
KIC_CONFIG_REGISTER_CHANNEL = config("KIC_CONFIG_REGISTER_CHANNEL", None)
KIC_CONFIG_REGISTER_TYPE = config("KIC_CONFIG_REGISTER_TYPE", None)
KIC_CONFIG_REGISTER_EMPLOYEE_ID = config("KIC_CONFIG_REGISTER_EMPLOYEE_ID", None)
KIC_CONFIG_USE_RSIN_FOR_INNNNPID_QUERY_PARAMETER = config(
"KIC_CONFIG_USE_RSIN_FOR_INNNNPID_QUERY_PARAMETER", None
)
5 changes: 5 additions & 0 deletions src/open_inwoner/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
"mailer",
"log_outgoing_requests",
"formtools",
"django_setup_configuration",
# Project applications.
"open_inwoner.components",
"open_inwoner.kvk",
Expand Down Expand Up @@ -929,6 +930,10 @@
}
}

#
# django-setup-configuration
#
from .app.setup_configuration import * # noqa

#
# Project specific settings
Expand Down
Empty file.
167 changes: 167 additions & 0 deletions src/open_inwoner/configurations/bootstrap/kic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from django.conf import settings

import requests
from django_setup_configuration.configuration import BaseConfigurationStep
from django_setup_configuration.exceptions import SelfTestFailed
from zgw_consumers.constants import APITypes, AuthTypes
from zgw_consumers.models import Service

from open_inwoner.openklant.clients import build_client
from open_inwoner.openklant.models import OpenKlantConfig
from open_inwoner.utils.api import ClientError


class KlantenAPIConfigurationStep(BaseConfigurationStep):
"""
Configure the required Service to establish a connection with the Klanten API
"""

verbose_name = "Klanten API configuration"
required_settings = [
"KIC_CONFIG_KLANTEN_API_ROOT",
"KIC_CONFIG_KLANTEN_API_CLIENT_ID",
"KIC_CONFIG_KLANTEN_API_SECRET",
]
enable_setting = "KIC_CONFIG_ENABLE"

def is_configured(self) -> bool:
return Service.objects.filter(
api_root=settings.KIC_CONFIG_KLANTEN_API_ROOT
).exists()

def configure(self):
organization = settings.OIP_ORGANIZATION or settings.ENVIRONMENT
org_label = f"Open Inwoner {organization}".strip()

Service.objects.update_or_create(
api_root=settings.KIC_CONFIG_KLANTEN_API_ROOT,
defaults={
"label": "Klanten API",
"api_type": APITypes.kc,
"oas": settings.KIC_CONFIG_KLANTEN_API_ROOT,
"auth_type": AuthTypes.zgw,
"client_id": settings.KIC_CONFIG_KLANTEN_API_CLIENT_ID,
"secret": settings.KIC_CONFIG_KLANTEN_API_SECRET,
"user_id": settings.KIC_CONFIG_KLANTEN_API_CLIENT_ID,
"user_representation": org_label,
},
)

def test_configuration(self):
"""
actual testing is done in final step
"""


class ContactmomentenAPIConfigurationStep(BaseConfigurationStep):
"""
Configure the required Service to establish a connection with the Contactmomenten API
"""

verbose_name = "Contactmomenten API configuration"
required_settings = [
"KIC_CONFIG_CONTACTMOMENTEN_API_ROOT",
"KIC_CONFIG_CONTACTMOMENTEN_API_CLIENT_ID",
"KIC_CONFIG_CONTACTMOMENTEN_API_SECRET",
]
enable_setting = "KIC_CONFIG_ENABLE"

def is_configured(self) -> bool:
return Service.objects.filter(
api_root=settings.KIC_CONFIG_CONTACTMOMENTEN_API_ROOT
).exists()

def configure(self):
organization = settings.OIP_ORGANIZATION or settings.ENVIRONMENT
org_label = f"Open Inwoner {organization}".strip()

Service.objects.update_or_create(
api_root=settings.KIC_CONFIG_CONTACTMOMENTEN_API_ROOT,
defaults={
"label": "Contactmomenten API",
"api_type": APITypes.cmc,
"oas": settings.KIC_CONFIG_CONTACTMOMENTEN_API_ROOT,
"auth_type": AuthTypes.zgw,
"client_id": settings.KIC_CONFIG_CONTACTMOMENTEN_API_CLIENT_ID,
"secret": settings.KIC_CONFIG_CONTACTMOMENTEN_API_SECRET,
"user_id": settings.KIC_CONFIG_CONTACTMOMENTEN_API_CLIENT_ID,
"user_representation": org_label,
},
)

def test_configuration(self):
"""
actual testing is done in final step
"""


class KICAPIsConfigurationStep(BaseConfigurationStep):
"""
Configure the KIC settings and set any feature flags or other options if specified
"""

verbose_name = "Klantinteractie APIs configuration"
enable_setting = "KIC_CONFIG_ENABLE"

def is_configured(self) -> bool:
kic_config = OpenKlantConfig.get_solo()
return bool(kic_config.klanten_service) and bool(
kic_config.contactmomenten_service
)

def configure(self):
config = OpenKlantConfig.get_solo()
config.klanten_service = Service.objects.get(
api_root=settings.KIC_CONFIG_KLANTEN_API_ROOT
)
config.contactmomenten_service = Service.objects.get(
api_root=settings.KIC_CONFIG_CONTACTMOMENTEN_API_ROOT
)

if settings.KIC_CONFIG_REGISTER_EMAIL:
config.register_email = settings.KIC_CONFIG_REGISTER_EMAIL
if settings.KIC_CONFIG_REGISTER_CONTACT_MOMENT is not None:
config.register_contact_moment = settings.KIC_CONFIG_REGISTER_CONTACT_MOMENT
if settings.KIC_CONFIG_REGISTER_BRONORGANISATIE_RSIN:
config.register_bronorganisatie_rsin = (
settings.KIC_CONFIG_REGISTER_BRONORGANISATIE_RSIN
)
if settings.KIC_CONFIG_REGISTER_CHANNEL:
config.register_channel = settings.KIC_CONFIG_REGISTER_CHANNEL
if settings.KIC_CONFIG_REGISTER_TYPE:
config.register_type = settings.KIC_CONFIG_REGISTER_TYPE
if settings.KIC_CONFIG_REGISTER_EMPLOYEE_ID:
config.register_employee_id = settings.KIC_CONFIG_REGISTER_EMPLOYEE_ID
if settings.KIC_CONFIG_USE_RSIN_FOR_INNNNPID_QUERY_PARAMETER is not None:
config.use_rsin_for_innNnpId_query_parameter = (
settings.KIC_CONFIG_USE_RSIN_FOR_INNNNPID_QUERY_PARAMETER
)

config.save()

def test_configuration(self):
"""
make requests to the APIs and verify that a connection can be made
"""
klanten_client = build_client("klanten")
contactmoment_client = build_client("contactmomenten")

try:
response = klanten_client.get(
"klanten", params={"subjectNatuurlijkPersoon__inpBsn": "000000000"}
)
response.raise_for_status()
except (ClientError, requests.RequestException) as exc:
raise SelfTestFailed(
"Could not retrieve list of klanten from Klanten API."
) from exc

try:
response = contactmoment_client.get(
"contactmomenten", params={"identificatie": "00000"}
)
response.raise_for_status()
except (ClientError, requests.RequestException) as exc:
raise SelfTestFailed(
"Could not retrieve list of objectcontactmomenten from Contactmomenten API."
) from exc
Loading

0 comments on commit bf6778c

Please sign in to comment.