diff --git a/src/nrc/tests/commands/files/setup_config_full.yaml b/src/nrc/tests/commands/files/setup_config_full.yaml new file mode 100644 index 00000000..69d8b5a3 --- /dev/null +++ b/src/nrc/tests/commands/files/setup_config_full.yaml @@ -0,0 +1,37 @@ +zgw_consumers_config_enable: True +zgw_consumers: + services: + - identifier: autorisaties-api + label: Objecttypen API test + api_root: http://localhost:8001/autorisaties/api/v1/ + api_type: ac + auth_type: zgw + client_id: open-notificaties + secret: oPMsHCEuoP9Qh8vP06D7 + user_id: open-notificaties + user_representation: Open Notificaties Demodam + +autorisaties_api_config_enable: True +autorisaties_api: + # Configure Open Notificaties to make use of Open Zaak's Autorisaties API + authorizations_api_service_identifier: autorisaties-api + +vng_api_common_credentials_config_enable: True +vng_api_common_credentials: + items: + # Credentials for Open Zaak to be able to make requests to Open Notificaties + - identifier: open-zaak + secret: G2LIVfXal1J93puQkV3O + +notifications_config_enable: True +notifications_config: + # No notifications_api_service necessary, because Open Notificaties doesn't send + # notifications to itself + notification_delivery_max_retries: 5 + notification_delivery_retry_backoff: 3 + notification_delivery_retry_backoff_max: 30 + +site_config_enable: True +site_config: + domain: opennotificaties.local:8000 + organization: Demodam diff --git a/src/nrc/tests/commands/test_setup_configuration.py b/src/nrc/tests/commands/test_setup_configuration.py index d087bdb9..4ac69148 100644 --- a/src/nrc/tests/commands/test_setup_configuration.py +++ b/src/nrc/tests/commands/test_setup_configuration.py @@ -1,36 +1,30 @@ import uuid from io import StringIO +from pathlib import Path from django.contrib.sites.models import Site -from django.core.management import CommandError, call_command -from django.test import TestCase, override_settings +from django.core.management import call_command +from django.test import TestCase from django.urls import reverse -import requests import requests_mock from jwt import decode +from notifications_api_common.contrib.setup_configuration.steps import ( + NotificationConfigurationStep, +) +from notifications_api_common.models import NotificationsConfig from rest_framework import status from vng_api_common.authorizations.models import AuthorizationsConfig from vng_api_common.authorizations.utils import generate_jwt +from vng_api_common.contrib.setup_configuration.steps import JWTSecretsConfigurationStep +from zgw_consumers.contrib.setup_configuration.steps import ServiceConfigurationStep -from nrc.config.authorization import AuthorizationStep, OpenZaakAuthStep -from nrc.config.notification_retry import NotificationRetryConfigurationStep +from nrc.config.authorization import AuthorizationStep from nrc.config.site import SiteConfigurationStep +CONFIG_FILE_PATH = Path("src/nrc/tests/commands/files/setup_config_full.yaml").resolve() + -@override_settings( - SITES_CONFIG_ENABLE=True, - OPENNOTIFICATIES_DOMAIN="open-notificaties.example.com", - OPENNOTIFICATIES_ORGANIZATION="ACME", - AUTHORIZATION_CONFIG_ENABLE=True, - AUTORISATIES_API_ROOT="https://oz.example.com/autorisaties/api/v1/", - NOTIF_OPENZAAK_CLIENT_ID="notif-client-id", - NOTIF_OPENZAAK_SECRET="notif-secret", - OPENZAAK_NOTIF_CONFIG_ENABLE=True, - OPENZAAK_NOTIF_CLIENT_ID="oz-client-id", - OPENZAAK_NOTIF_SECRET="oz-secret", - NOTIFICATION_RETRY_CONFIG_ENABLE=True, -) class SetupConfigurationTests(TestCase): maxDiff = None @@ -44,15 +38,15 @@ def test_setup_configuration(self, m): stdout = StringIO() # mocks _uuid = uuid.uuid4() - m.get("http://open-notificaties.example.com/", status_code=200) - m.get("http://open-notificaties.example.com/api/v1/kanaal", json=[]) + m.get("http://opennotificaties.local:8000/", status_code=200) + m.get("http://opennotificaties.local:8000/api/v1/kanaal", json=[]) m.get( - "https://oz.example.com/autorisaties/api/v1/applicaties", + "http://localhost:8001/autorisaties/api/v1/applicaties", json={ "count": 1, "results": [ { - "url": f"https://oz.example.com/autorisaties/api/v1/applicaties/{_uuid}", + "url": f"http://localhost:8001/autorisaties/api/v1/applicaties/{_uuid}", "clientIds": ["oz-client-id"], "label": "OZ for ON", "heeftAlleAutorisaties": True, @@ -62,31 +56,34 @@ def test_setup_configuration(self, m): }, ) - call_command("setup_configuration", stdout=stdout, no_color=True) + call_command( + "setup_configuration", + yaml_file=CONFIG_FILE_PATH, + stdout=stdout, + no_color=True, + ) with self.subTest("Command output"): command_output = stdout.getvalue().splitlines() expected_output = [ - f"Configuration will be set up with following steps: [{SiteConfigurationStep()}, " - f"{AuthorizationStep()}, {OpenZaakAuthStep()}, {NotificationRetryConfigurationStep()}]", - f"Configuring {SiteConfigurationStep()}...", - f"{SiteConfigurationStep()} is successfully configured", - f"Configuring {AuthorizationStep()}...", - f"{AuthorizationStep()} is successfully configured", - f"Configuring {OpenZaakAuthStep()}...", - f"{OpenZaakAuthStep()} is successfully configured", - f"Configuring {NotificationRetryConfigurationStep()}...", - f"{NotificationRetryConfigurationStep()} is successfully configured", + f"Loading config settings from {CONFIG_FILE_PATH}", + "The following steps are configured:", + f"{ServiceConfigurationStep()}", + f"{JWTSecretsConfigurationStep()}", + f"{AuthorizationStep()}", + f"{NotificationConfigurationStep()}", + f"{SiteConfigurationStep()}", + "Executing steps...", + f"Successfully executed step: {ServiceConfigurationStep()}", + f"Successfully executed step: {JWTSecretsConfigurationStep()}", + f"Successfully executed step: {AuthorizationStep()}", + f"Successfully executed step: {NotificationConfigurationStep()}", + f"Successfully executed step: {SiteConfigurationStep()}", "Instance configuration completed.", ] self.assertEqual(command_output, expected_output) - with self.subTest("Site configured correctly"): - site = Site.objects.get_current() - self.assertEqual(site.domain, "open-notificaties.example.com") - self.assertEqual(site.name, "Open Notificaties ACME") - with self.subTest("Authorization API client configured correctly"): ac_client = AuthorizationsConfig.get_client() self.assertIsNotNone(ac_client) @@ -96,17 +93,17 @@ def test_setup_configuration(self, m): create_call = m.last_request self.assertEqual( create_call.url, - "https://oz.example.com/autorisaties/api/v1/applicaties", + "http://localhost:8001/autorisaties/api/v1/applicaties", ) self.assertIn("Authorization", create_call.headers) header_jwt = create_call.headers["Authorization"].split(" ")[1] decoded_jwt = decode(header_jwt, options={"verify_signature": False}) - self.assertEqual(decoded_jwt["client_id"], "notif-client-id") + self.assertEqual(decoded_jwt["client_id"], "open-notificaties") with self.subTest("Open Zaak can query Notification API"): - token = generate_jwt("oz-client-id", "oz-secret", "", "") + token = generate_jwt("open-zaak", "G2LIVfXal1J93puQkV3O", "", "") response = self.client.get( reverse("kanaal-list", kwargs={"version": 1}), @@ -115,24 +112,14 @@ def test_setup_configuration(self, m): self.assertEqual(response.status_code, status.HTTP_200_OK) - @requests_mock.Mocker() - def test_setup_configuration_selftest_fails(self, m): - m.get("http://open-notificaties.example.com/", exc=requests.ConnectionError) - m.get("http://open-notificaties.example.com/api/v1/kanaal", json=[]) - m.get("https://oz.example.com/autorisaties/api/v1/applicaties", json=[]) + with self.subTest("Notifications configured correctly"): + config = NotificationsConfig.get_solo() + self.assertEqual(config.notifications_api_service, None) + self.assertEqual(config.notification_delivery_max_retries, 5) + self.assertEqual(config.notification_delivery_retry_backoff, 3) + self.assertEqual(config.notification_delivery_retry_backoff_max, 30) - with self.assertRaisesMessage( - CommandError, - "Could not access home page at 'http://open-notificaties.example.com/'", - ): - call_command("setup_configuration") - - @requests_mock.Mocker() - def test_setup_configuration_without_selftest(self, m): - stdout = StringIO() - - call_command("setup_configuration", no_selftest=True, stdout=stdout) - command_output = stdout.getvalue() - - self.assertEqual(len(m.request_history), 0) - self.assertTrue("Selftest is skipped" in command_output) + with self.subTest("Site configured correctly"): + site = Site.objects.get_current() + self.assertEqual(site.domain, "opennotificaties.local:8000") + self.assertEqual(site.name, "Open Notificaties Demodam") diff --git a/src/nrc/tests/config/files/setup_config_auth_config.yaml b/src/nrc/tests/config/files/setup_config_auth_config.yaml new file mode 100644 index 00000000..c8803933 --- /dev/null +++ b/src/nrc/tests/config/files/setup_config_auth_config.yaml @@ -0,0 +1,3 @@ +autorisaties_api_config_enable: True +autorisaties_api: + authorizations_api_service_identifier: autorisaties-api diff --git a/src/nrc/tests/config/files/setup_config_sites.yaml b/src/nrc/tests/config/files/setup_config_sites.yaml new file mode 100644 index 00000000..32ab4db5 --- /dev/null +++ b/src/nrc/tests/config/files/setup_config_sites.yaml @@ -0,0 +1,4 @@ +site_config_enable: True +site_config: + domain: opennotificaties.local:8000 + organization: Demodam diff --git a/src/nrc/tests/config/test_authorization_configuration.py b/src/nrc/tests/config/test_authorization_configuration.py index dfa4fd48..9bcbd146 100644 --- a/src/nrc/tests/config/test_authorization_configuration.py +++ b/src/nrc/tests/config/test_authorization_configuration.py @@ -1,129 +1,58 @@ -from unittest.mock import patch +from django.test import TestCase -from django.test import TestCase, override_settings - -import requests -import requests_mock -from django_setup_configuration.exceptions import SelfTestFailed +from django_setup_configuration.test_utils import execute_single_step from vng_api_common.authorizations.models import AuthorizationsConfig, ComponentTypes -from vng_api_common.models import JWTSecret - -from nrc.config.authorization import AuthorizationStep, OpenZaakAuthStep +from zgw_consumers.test.factories import ServiceFactory +from nrc.config.authorization import AuthorizationStep -@override_settings( - AUTORISATIES_API_ROOT="https://oz.example.com/autorisaties/api/v1/", - NOTIF_OPENZAAK_CLIENT_ID="notif-client-id", - NOTIF_OPENZAAK_SECRET="notif-secret", -) -class AuthorizationConfigurationTests(TestCase): - def test_configure(self): - configuration = AuthorizationStep() +CONFIG_FILE_PATH = "src/nrc/tests/config/files/setup_config_auth_config.yaml" - configuration.configure() - config = AuthorizationsConfig.get_solo() - service = config.authorizations_api_service +class AuthorizationConfigurationTests(TestCase): + @classmethod + def setUpTestData(cls): + super().setUpTestData() - self.assertEqual(config.component, ComponentTypes.nrc) - self.assertEqual( - service.api_root, "https://oz.example.com/autorisaties/api/v1/" + cls.service = ServiceFactory.create( + slug="autorisaties-api", + api_root="http://openzaak.local/autorisaties/api/v1/", ) - self.assertEqual(service.client_id, "notif-client-id") - self.assertEqual(service.secret, "notif-secret") + def test_execute_configuration_step_success(self): + execute_single_step(AuthorizationStep, yaml_source=CONFIG_FILE_PATH) - @requests_mock.Mocker() - def test_selftest_ok(self, m): - configuration = AuthorizationStep() - configuration.configure() - - m.get("https://oz.example.com/autorisaties/api/v1/applicaties", json=[]) + config = AuthorizationsConfig.get_solo() - configuration.test_configuration() + self.assertEqual(config.component, ComponentTypes.nrc) + self.assertEqual(config.authorizations_api_service, self.service) - self.assertEqual( - m.last_request.url, "https://oz.example.com/autorisaties/api/v1/applicaties" - ) + def test_execute_configuration_step_update_existing(self): + config = AuthorizationsConfig.get_solo() + config.component = ComponentTypes.zrc + config.authorizations_api_service = ServiceFactory.create(slug="other-api") + config.save() - @requests_mock.Mocker() - def test_selftest_fail(self, m): - configuration = AuthorizationStep() - configuration.configure() + execute_single_step(AuthorizationStep, yaml_source=CONFIG_FILE_PATH) - m.get("https://oz.example.com/autorisaties/api/v1/applicaties", status_code=403) + config = AuthorizationsConfig.get_solo() + service = config.authorizations_api_service - with self.assertRaises(SelfTestFailed): - configuration.test_configuration() + self.assertEqual(config.component, ComponentTypes.nrc) + self.assertEqual(service, self.service) - self.assertEqual( - m.last_request.url, "https://oz.example.com/autorisaties/api/v1/applicaties" - ) + def test_execute_configuration_step_idempotent(self): + def make_assertions(): + config = AuthorizationsConfig.get_solo() + service = config.authorizations_api_service - def test_is_configured(self): - configuration = AuthorizationStep() - self.assertFalse(configuration.is_configured()) - - configuration.configure() - - self.assertTrue(configuration.is_configured()) - - -@override_settings( - OPENZAAK_NOTIF_CLIENT_ID="oz-client-id", - OPENZAAK_NOTIF_SECRET="oz-secret", -) -class OpenZaakConfigurationTests(TestCase): - def test_configure(self): - configuration = OpenZaakAuthStep() - - configuration.configure() - - jwt_secret = JWTSecret.objects.get(identifier="oz-client-id") - self.assertEqual(jwt_secret.secret, "oz-secret") - - @requests_mock.Mocker() - @patch( - "nrc.config.authorization.build_absolute_url", - return_value="http://testserver/kanaal", - ) - def test_selftest_ok(self, m, *mocks): - configuration = OpenZaakAuthStep() - configuration.configure() - m.get("http://testserver/kanaal", json=[]) - - configuration.test_configuration() - - self.assertEqual(m.last_request.url, "http://testserver/kanaal") - self.assertEqual(m.last_request.method, "GET") - - @requests_mock.Mocker() - @patch( - "nrc.config.authorization.build_absolute_url", - return_value="http://testserver/kanaal", - ) - def test_selftest_fail(self, m, *mocks): - configuration = OpenZaakAuthStep() - configuration.configure() - - mock_kwargs = ( - {"exc": requests.ConnectTimeout}, - {"exc": requests.ConnectionError}, - {"status_code": 404}, - {"status_code": 403}, - {"status_code": 500}, - ) - for mock_config in mock_kwargs: - with self.subTest(mock=mock_config): - m.get("http://testserver/kanaal", **mock_config) + self.assertEqual(config.component, ComponentTypes.nrc) + self.assertEqual(service, self.service) - with self.assertRaises(SelfTestFailed): - configuration.test_configuration() + execute_single_step(AuthorizationStep, yaml_source=CONFIG_FILE_PATH) - def test_is_configured(self): - configuration = OpenZaakAuthStep() - self.assertFalse(configuration.is_configured()) + make_assertions() - configuration.configure() + execute_single_step(AuthorizationStep, yaml_source=CONFIG_FILE_PATH) - self.assertTrue(configuration.is_configured()) + make_assertions() diff --git a/src/nrc/tests/config/test_notification_retry_configuration.py b/src/nrc/tests/config/test_notification_retry_configuration.py deleted file mode 100644 index 6185bc11..00000000 --- a/src/nrc/tests/config/test_notification_retry_configuration.py +++ /dev/null @@ -1,31 +0,0 @@ -from django.test import TestCase, override_settings - -from notifications_api_common.models import NotificationsConfig - -from nrc.config.notification_retry import NotificationRetryConfigurationStep - - -@override_settings( - NOTIFICATION_DELIVERY_MAX_RETRIES=4, - NOTIFICATION_DELIVERY_RETRY_BACKOFF=5, - NOTIFICATION_DELIVERY_RETRY_BACKOFF_MAX=6, -) -class NotificationRetryConfigurationTests(TestCase): - def test_configure(self): - configuration = NotificationRetryConfigurationStep() - configuration.configure() - - config = NotificationsConfig.get_solo() - - self.assertEqual(config.notification_delivery_max_retries, 4) - self.assertEqual(config.notification_delivery_retry_backoff, 5) - self.assertEqual(config.notification_delivery_retry_backoff_max, 6) - - def test_is_configured(self): - configuration = NotificationRetryConfigurationStep() - - self.assertFalse(configuration.is_configured()) - - configuration.configure() - - self.assertTrue(configuration.is_configured()) diff --git a/src/nrc/tests/config/test_site_configuration.py b/src/nrc/tests/config/test_site_configuration.py index fb0702e1..f4e32aa5 100644 --- a/src/nrc/tests/config/test_site_configuration.py +++ b/src/nrc/tests/config/test_site_configuration.py @@ -1,66 +1,51 @@ from django.contrib.sites.models import Site -from django.test import TestCase, override_settings +from django.test import TestCase -import requests -import requests_mock -from django_setup_configuration.exceptions import SelfTestFailed +from django_setup_configuration.test_utils import execute_single_step from nrc.config.site import SiteConfigurationStep +CONFIG_FILE_PATH = "src/nrc/tests/config/files/setup_config_sites.yaml" + -@override_settings( - OPENNOTIFICATIES_DOMAIN="localhost:8000", - OPENNOTIFICATIES_ORGANIZATION="ACME", -) class SiteConfigurationTests(TestCase): def setUp(self): super().setUp() self.addCleanup(Site.objects.clear_cache) - def test_set_domain(self): - configuration = SiteConfigurationStep() - configuration.configure() + def test_execute_configuration_step_success(self): + execute_single_step(SiteConfigurationStep, yaml_source=CONFIG_FILE_PATH) site = Site.objects.get_current() - self.assertEqual(site.domain, "localhost:8000") - self.assertEqual(site.name, "Open Notificaties ACME") - @requests_mock.Mocker() - def test_configuration_check_ok(self, m): - m.get("http://localhost:8000/", status_code=200) - configuration = SiteConfigurationStep() - configuration.configure() + self.assertEqual(site.domain, "opennotificaties.local:8000") + self.assertEqual(site.name, "Open Notificaties Demodam") + + def test_execute_configuration_step_update_existing(self): + site = Site.objects.get_current() + site.domain = "other-domain.local:8000" + site.name = "some other names" + site.save() - configuration.test_configuration() + execute_single_step(SiteConfigurationStep, yaml_source=CONFIG_FILE_PATH) - self.assertEqual(m.last_request.url, "http://localhost:8000/") - self.assertEqual(m.last_request.method, "GET") + site = Site.objects.get_current() - @requests_mock.Mocker() - def test_configuration_check_failures(self, m): - configuration = SiteConfigurationStep() - configuration.configure() + self.assertEqual(site.domain, "opennotificaties.local:8000") + self.assertEqual(site.name, "Open Notificaties Demodam") - mock_kwargs = ( - {"exc": requests.ConnectTimeout}, - {"exc": requests.ConnectionError}, - {"status_code": 404}, - {"status_code": 403}, - {"status_code": 500}, - ) - for mock_config in mock_kwargs: - with self.subTest(mock=mock_config): - m.get("http://localhost:8000/", **mock_config) + def test_execute_configuration_step_idempotent(self): + def make_assertions(): + site = Site.objects.get_current() - with self.assertRaises(SelfTestFailed): - configuration.test_configuration() + self.assertEqual(site.domain, "opennotificaties.local:8000") + self.assertEqual(site.name, "Open Notificaties Demodam") - def test_is_configured(self): - configuration = SiteConfigurationStep() + execute_single_step(SiteConfigurationStep, yaml_source=CONFIG_FILE_PATH) - self.assertFalse(configuration.is_configured()) + make_assertions() - configuration.configure() + execute_single_step(SiteConfigurationStep, yaml_source=CONFIG_FILE_PATH) - self.assertTrue(configuration.is_configured()) + make_assertions()