Skip to content

Commit

Permalink
Merge pull request #53 from maykinmedia/feature/jwtsecret-configurati…
Browse files Browse the repository at this point in the history
…on-step

✨ Add ConfigurationStep for JWTSecrets
  • Loading branch information
stevenbal authored Dec 10, 2024
2 parents 4b07304 + 6956bd4 commit 8280778
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 0 deletions.
1 change: 1 addition & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ python:
extra_requirements:
- notifications
- docs
- setup-configuration

1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Features
:caption: Contents:

quickstart
setup_config
ref/index


Expand Down
37 changes: 37 additions & 0 deletions docs/setup_config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Setup configuration
===================

Loading JWTSecrets from a YAML file
***************************************************

This library provides a ``ConfigurationStep``
(from the library ``django-setup-configuration``, see the
`documentation <https://github.com/maykinmedia/django-setup-configuration>`_
for more information on how to run ``setup_configuration``)
to configure the client credentials.

To add this step to your configuration steps, add ``django_setup_configuration`` to ``INSTALLED_APPS`` and add the following setting:

.. code:: python
SETUP_CONFIGURATION_STEPS = [
...
"vng_api_common.contrib.setup_configuration.steps.JWTSecretsConfigurationStep"
...
]
The YAML file that is passed to ``setup_configuration`` must set the
``vng_api_common_credentials_config_enable`` flag to ``true`` to enable the step. Any number of ``identifier`` and
``secret`` pairs can be defined under ``vng_api_common_credentials.items``

Example file:

.. code:: yaml
vng_api_common_credentials_config_enable: True
vng_api_common_credentials:
items:
- identifier: user-id
secret: super-secret
- identifier: user-id2
secret: super-secret2
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ tests =
zgw-consumers-oas
testutils =
zgw-consumers-oas
setup-configuration =
django-setup-configuration>=0.4.0
pep8 = flake8
coverage = pytest-cov
docs =
Expand Down
1 change: 1 addition & 0 deletions testapp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"simple_certmanager",
"zgw_consumers",
"notifications_api_common",
"django_setup_configuration",
"vng_api_common",
"vng_api_common.authorizations",
"vng_api_common.notifications",
Expand Down
7 changes: 7 additions & 0 deletions tests/files/setup_config_jwtsecrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vng_api_common_credentials_config_enable: True
vng_api_common_credentials:
items:
- identifier: user-id
secret: super-secret
- identifier: user-id2
secret: super-secret2
62 changes: 62 additions & 0 deletions tests/test_configuration_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import pytest
from django_setup_configuration.test_utils import execute_single_step

from vng_api_common.contrib.setup_configuration.steps import JWTSecretsConfigurationStep
from vng_api_common.models import JWTSecret

CONFIG_FILE_PATH = "tests/files/setup_config_jwtsecrets.yaml"


@pytest.mark.django_db
def test_execute_configuration_step_success():
execute_single_step(JWTSecretsConfigurationStep, yaml_source=CONFIG_FILE_PATH)

assert JWTSecret.objects.count() == 2

credential1, credential2 = JWTSecret.objects.all()

assert credential1.identifier == "user-id"
assert credential1.secret == "super-secret"

assert credential2.identifier == "user-id2"
assert credential2.secret == "super-secret2"


@pytest.mark.django_db
def test_execute_configuration_step_update_existing():
JWTSecret.objects.create(identifier="user-id", secret="old")
JWTSecret.objects.create(identifier="user-id2", secret="old2")

execute_single_step(JWTSecretsConfigurationStep, yaml_source=CONFIG_FILE_PATH)

assert JWTSecret.objects.count() == 2

credential1, credential2 = JWTSecret.objects.all()

assert credential1.identifier == "user-id"
assert credential1.secret == "super-secret"

assert credential2.identifier == "user-id2"
assert credential2.secret == "super-secret2"


@pytest.mark.django_db
def test_execute_configuration_step_idempotent():
def make_assertions():
assert JWTSecret.objects.count() == 2

credential1, credential2 = JWTSecret.objects.all()

assert credential1.identifier == "user-id"
assert credential1.secret == "super-secret"

assert credential2.identifier == "user-id2"
assert credential2.secret == "super-secret2"

execute_single_step(JWTSecretsConfigurationStep, yaml_source=CONFIG_FILE_PATH)

make_assertions()

execute_single_step(JWTSecretsConfigurationStep, yaml_source=CONFIG_FILE_PATH)

make_assertions()
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ DJANGO =
extras =
tests
coverage
setup-configuration
deps =
django42: Django~=4.2.0
setenv =
Expand Down Expand Up @@ -52,6 +53,7 @@ extras =
notifications
tests
docs
setup-configuration
commands=
pytest check_sphinx.py -v \
--tb=auto \
Expand Down
Empty file.
Empty file.
18 changes: 18 additions & 0 deletions vng_api_common/contrib/setup_configuration/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django_setup_configuration.models import ConfigurationModel
from pydantic import Field

from vng_api_common.models import JWTSecret


class SingleJWTSecretConfigurationModel(ConfigurationModel):
class Meta:
django_model_refs = {
JWTSecret: [
"identifier",
"secret",
]
}


class JWTSecretsConfigurationModel(ConfigurationModel):
items: list[SingleJWTSecretConfigurationModel] = Field(default_factory=list)
23 changes: 23 additions & 0 deletions vng_api_common/contrib/setup_configuration/steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django_setup_configuration.configuration import BaseConfigurationStep

from vng_api_common.models import JWTSecret

from .models import JWTSecretsConfigurationModel


class JWTSecretsConfigurationStep(BaseConfigurationStep[JWTSecretsConfigurationModel]):
"""
Configure credentials for Applications that need access
"""

verbose_name = "Configuration to create credentials"
config_model = JWTSecretsConfigurationModel
namespace = "vng_api_common_credentials"
enable_setting = "vng_api_common_credentials_config_enable"

def execute(self, model: JWTSecretsConfigurationModel):
for config in model.items:
JWTSecret.objects.update_or_create(
identifier=config.identifier,
defaults={"secret": config.secret},
)

0 comments on commit 8280778

Please sign in to comment.