diff --git a/docs/conf.py b/docs/conf.py index 96a2651..d2cfebd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -37,6 +37,7 @@ "sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.viewcode", + "django_setup_configuration.documentation.setup_config_example", ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/setup_config.rst b/docs/setup_config.rst index cbc2838..2fdfdab 100644 --- a/docs/setup_config.rst +++ b/docs/setup_config.rst @@ -10,6 +10,12 @@ This library provides a ``ConfigurationStep`` for more information on how to run ``setup_configuration``) to configure any number of ``Services`` from a YAML file. +To make use of this, you must install the ``setup-configuration`` dependency group: + +.. code-block:: bash + + pip install zgw-consumers[setup-configuration] + To add this step to your configuration steps, add ``django_setup_configuration`` to ``INSTALLED_APPS`` and add the following setting: .. code:: python @@ -22,33 +28,8 @@ To add this step to your configuration steps, add ``django_setup_configuration`` The YAML file that is passed to ``setup_configuration`` must set the ``zgw_consumers_config_enable`` flag to ``true`` to enable the step and also provide ``services`` under -the ``zgw_consumers`` namespace to configure ``Services`` - -Example file: - - .. code:: yaml - - zgw_consumers_config_enable: True - zgw_consumers: - services: - # all possible configurable fields - - identifier: objecten-test - label: Objecten API test - api_root: http://objecten.local/api/v1/ - api_connection_check_path: objects - api_type: orc - auth_type: api_key - header_key: Authorization - header_value: Token foo - client_id: client - secret: super-secret - nlx: http://some-outway-adress.local:8080/ - user_id: open-formulieren - user_representation: Open Formulieren - timeout: 5 - # minimum required fields - - identifier: objecttypen-test - label: Objecttypen API test - api_root: http://objecttypen.local/api/v1/ - api_type: orc - auth_type: api_key +the ``zgw_consumers`` namespace to configure ``Services``. + +Below is an example of what this YAML file can look like: + +.. setup-config-example:: zgw_consumers.contrib.setup_configuration.steps.ServiceConfigurationStep diff --git a/zgw_consumers/contrib/setup_configuration/models.py b/zgw_consumers/contrib/setup_configuration/models.py index 18dcbbd..49bcbc4 100644 --- a/zgw_consumers/contrib/setup_configuration/models.py +++ b/zgw_consumers/contrib/setup_configuration/models.py @@ -9,7 +9,7 @@ class SingleServiceConfigurationModel(ConfigurationModel): # client_certificate: FilePath = DjangoModelRef(Service, "client_certificate") # server_certificate: FilePath = DjangoModelRef(Service, "server_certificate") # Identifier is mapped to slug, because slug isn't a very descriptive name for devops - identifier: str = DjangoModelRef(Service, "slug") + identifier: str = DjangoModelRef(Service, "slug", examples=["service-identifier"]) class Meta: django_model_refs = { @@ -29,7 +29,19 @@ class Meta: "timeout", ] } + extra_kwargs = { + "label": {"examples": ["Service label"]}, + "api_root": {"examples": ["https://example.com/api/v1/"]}, + "api_connection_check_path": {"examples": ["some/relative/path"]}, + "client_id": {"examples": ["modify-this"]}, + "secret": {"examples": ["modify-this"]}, + "header_key": {"examples": ["Authorization"]}, + "header_value": {"examples": ["Token "]}, + "nlx": {"examples": ["http://some-outway-adress.local:8080/"]}, + "user_id": {"examples": ["client-id"]}, + "user_representation": {"examples": ["Name of the user"]}, + } class ServicesConfigurationModel(ConfigurationModel): - services: list[SingleServiceConfigurationModel] = Field(default_factory=list) + services: list[SingleServiceConfigurationModel] = Field() diff --git a/zgw_consumers/contrib/setup_configuration/steps.py b/zgw_consumers/contrib/setup_configuration/steps.py index 3411323..abc83b2 100644 --- a/zgw_consumers/contrib/setup_configuration/steps.py +++ b/zgw_consumers/contrib/setup_configuration/steps.py @@ -7,7 +7,9 @@ class ServiceConfigurationStep(BaseConfigurationStep[ServicesConfigurationModel]): """ - Configure Services to connect with external APIs + Configure any number of external Services to connect with, + along with the credentials needed to communicate with them. This allows the application + to integrate with other applications. """ verbose_name = "Configuration to connect with external services" diff --git a/zgw_consumers/migrations/0023_add_help_texts_to_service_fields.py b/zgw_consumers/migrations/0023_add_help_texts_to_service_fields.py new file mode 100644 index 0000000..c827646 --- /dev/null +++ b/zgw_consumers/migrations/0023_add_help_texts_to_service_fields.py @@ -0,0 +1,76 @@ +# Generated by Django 4.2.18 on 2025-01-21 11:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("zgw_consumers", "0022_set_default_service_slug"), + ] + + operations = [ + migrations.AlterField( + model_name="service", + name="api_root", + field=models.CharField( + help_text="The root of the service that will be used to construct the URLs when making requests", + max_length=255, + unique=True, + verbose_name="api root url", + ), + ), + migrations.AlterField( + model_name="service", + name="auth_type", + field=models.CharField( + choices=[ + ("no_auth", "No authorization"), + ("api_key", "API key"), + ("zgw", "ZGW client_id + secret"), + ], + default="zgw", + help_text="The method of to authorize with the service", + max_length=20, + verbose_name="authorization type", + ), + ), + migrations.AlterField( + model_name="service", + name="client_id", + field=models.CharField( + blank=True, + help_text="The client ID used to construct the JSON Web Token to connect with the service (only needed if auth type is `zgw`)", + max_length=255, + ), + ), + migrations.AlterField( + model_name="service", + name="header_key", + field=models.CharField( + blank=True, + help_text="The header key used to store the API key (only needed if auth type is `api_key`)", + max_length=100, + verbose_name="header key", + ), + ), + migrations.AlterField( + model_name="service", + name="header_value", + field=models.CharField( + blank=True, + help_text="The API key to connect with the service (only needed if auth type is `api_key`)", + max_length=255, + verbose_name="header value", + ), + ), + migrations.AlterField( + model_name="service", + name="secret", + field=models.CharField( + blank=True, + help_text="The secret used to construct the JSON Web Token to connect with the service (only needed if auth type is `zgw`)", + max_length=255, + ), + ), + ] diff --git a/zgw_consumers/models/services.py b/zgw_consumers/models/services.py index 1f2f130..dbe3e97 100644 --- a/zgw_consumers/models/services.py +++ b/zgw_consumers/models/services.py @@ -47,7 +47,14 @@ class Service(RestAPIService): max_length=255, ) api_type = models.CharField(_("type"), max_length=20, choices=APITypes.choices) - api_root = models.CharField(_("api root url"), max_length=255, unique=True) + api_root = models.CharField( + _("api root url"), + help_text=_( + "The root of the service that will be used to construct the URLs when making requests" + ), + max_length=255, + unique=True, + ) api_connection_check_path = models.CharField( _("connection check endpoint"), help_text=_( @@ -64,16 +71,45 @@ class Service(RestAPIService): ) # credentials for the API - client_id = models.CharField(max_length=255, blank=True) - secret = models.CharField(max_length=255, blank=True) + client_id = models.CharField( + max_length=255, + blank=True, + help_text=_( + "The client ID used to construct the JSON Web Token to connect " + "with the service (only needed if auth type is `zgw`)" + ), + ) + secret = models.CharField( + max_length=255, + blank=True, + help_text=_( + "The secret used to construct the JSON Web Token to connect with " + "the service (only needed if auth type is `zgw`)" + ), + ) auth_type = models.CharField( _("authorization type"), max_length=20, choices=AuthTypes.choices, default=AuthTypes.zgw, + help_text=_("The method of to authorize with the service"), + ) + header_key = models.CharField( + _("header key"), + max_length=100, + blank=True, + help_text=_( + "The header key used to store the API key (only needed if auth type is `api_key`)" + ), + ) + header_value = models.CharField( + _("header value"), + max_length=255, + blank=True, + help_text=_( + "The API key to connect with the service (only needed if auth type is `api_key`)" + ), ) - header_key = models.CharField(_("header key"), max_length=100, blank=True) - header_value = models.CharField(_("header value"), max_length=255, blank=True) nlx = models.URLField( _("NLX url"), max_length=1000, blank=True, help_text=_("NLX (outway) address") )