From 962e49c7efc086f6e84a896044d5336bce05c651 Mon Sep 17 00:00:00 2001 From: daniel Date: Mon, 15 Apr 2024 13:56:21 +0200 Subject: [PATCH] :sparkles: Add zac user logs mail task --- src/bptl/work_units/clients.py | 4 +- src/bptl/work_units/zgw/zac/serializers.py | 9 ++ src/bptl/work_units/zgw/zac/tasks.py | 46 +++++++- .../zgw/zac/tests/test_zac_email_user_logs.py | 107 ++++++++++++++++++ 4 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 src/bptl/work_units/zgw/zac/tests/test_zac_email_user_logs.py diff --git a/src/bptl/work_units/clients.py b/src/bptl/work_units/clients.py index 349d7e98..a004748d 100644 --- a/src/bptl/work_units/clients.py +++ b/src/bptl/work_units/clients.py @@ -82,7 +82,7 @@ def request( operation: str = "", request_kwargs: Optional[Dict] = None, **kwargs, - ): + ) -> Optional[Dict]: assert not path.startswith("/"), "Only relative paths are supported." url = urljoin(self.api_root, path) @@ -104,7 +104,7 @@ def request( response = self.session.request(method=method, url=url, **kwargs) response.raise_for_status() - return response.json() + return response.json() if response.content else None def get(self, path: str, params=None, **kwargs): kwargs.setdefault("allow_redirects", True) diff --git a/src/bptl/work_units/zgw/zac/serializers.py b/src/bptl/work_units/zgw/zac/serializers.py index aa40132b..1b9ef7e4 100644 --- a/src/bptl/work_units/zgw/zac/serializers.py +++ b/src/bptl/work_units/zgw/zac/serializers.py @@ -38,3 +38,12 @@ class CreatedProcessInstanceSerializer(serializers.Serializer): instanceUrl = serializers.URLField( help_text=_("The URL of the process instance."), required=True ) + + +class RecipientListSerializer(serializers.Serializer): + recipientList = serializers.ListField( + child=serializers.EmailField( + help_text=_("Email address of recipient."), allow_blank=False + ), + help_text=_("List of recipients."), + ) diff --git a/src/bptl/work_units/zgw/zac/tasks.py b/src/bptl/work_units/zgw/zac/tasks.py index aa555e53..40221c00 100644 --- a/src/bptl/work_units/zgw/zac/tasks.py +++ b/src/bptl/work_units/zgw/zac/tasks.py @@ -10,7 +10,11 @@ from bptl.work_units.zgw.tasks.base import ZGWWorkUnit, require_zrc from .client import get_client, require_zac_service -from .serializers import ZaakDetailURLSerializer, ZacUserDetailSerializer +from .serializers import ( + RecipientListSerializer, + ZaakDetailURLSerializer, + ZacUserDetailSerializer, +) logger = logging.getLogger(__name__) @@ -203,3 +207,43 @@ def perform(self) -> dict: zaak_detail_url = self.get_client_response() validated_data = self.validate_data(zaak_detail_url) return validated_data + + +@register +@require_zac_service +class ZacEmailUserLogs(ZGWWorkUnit): + """ + Requests the URL to the zaak detail page of a ZAAK in open zaak. + + **Required process variables** + * ``recipientList`` List[str]: List of email adresses to sent email to. + + """ + + def validate_data(self, data: dict) -> dict: + check_variable(data, "recipientList", empty_allowed=False) + serializer = RecipientListSerializer(data=data) + codes_to_catch = ( + "code='required'", + "code='blank'", + ) + + try: + serializer.is_valid(raise_exception=True) + return serializer.data + except Exception as e: + if isinstance(e, exceptions.ValidationError): + error_codes = str(e.detail) + if any(code in error_codes for code in codes_to_catch): + raise MissingVariable(e.detail) + raise e + + def perform(self) -> None: + variables = self.task.get_variables() + data = self.validate_data(variables) + with get_client(self.task) as client: + client.post( + f"api/accounts/management/axes/logs", + json=data, + ) + return None diff --git a/src/bptl/work_units/zgw/zac/tests/test_zac_email_user_logs.py b/src/bptl/work_units/zgw/zac/tests/test_zac_email_user_logs.py new file mode 100644 index 00000000..428a3d88 --- /dev/null +++ b/src/bptl/work_units/zgw/zac/tests/test_zac_email_user_logs.py @@ -0,0 +1,107 @@ +from django.test import TestCase + +import requests_mock +from django_camunda.utils import serialize_variable +from rest_framework.serializers import ValidationError +from zgw_consumers.constants import APITypes, AuthTypes + +from bptl.camunda.models import ExternalTask +from bptl.tasks.base import MissingVariable +from bptl.tasks.tests.factories import DefaultServiceFactory, TaskMappingFactory + +from ..tasks import ZacEmailUserLogs + +ZAC_ROOT = "https://zac.example.com/" +ZAC_LOG_URL = f"{ZAC_ROOT}api/accounts/management/axes/logs" + + +class ZacEmailUserLogsTests(TestCase): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + cls.task_dict = { + "topic_name": "some-topic-name", + "worker_id": "test-worker-id", + "task_id": "test-task-id", + "variables": { + "recipientList": serialize_variable(["user@bptl.com"]), + }, + } + cls.task_url = ExternalTask.objects.create( + **cls.task_dict, + ) + + mapping = TaskMappingFactory.create(topic_name="some-topic-name") + DefaultServiceFactory.create( + task_mapping=mapping, + service__api_root=ZAC_ROOT, + service__api_type=APITypes.orc, + service__auth_type=AuthTypes.no_auth, + alias="zac", + ) + + @requests_mock.Mocker() + def test_post_recipient_list_to_zac_endpoint(self, m): + m.post(ZAC_LOG_URL, status_code=204) + + task = ZacEmailUserLogs(self.task_url) + response = task.perform() + self.assertEqual(response, None) + + self.assertEqual( + m.last_request.url, + ZAC_LOG_URL, + ) + self.assertEqual(m.last_request.method, "POST") + self.assertEqual(m.last_request.json(), {"recipientList": ["user@bptl.com"]}) + + def test_post_recipient_list_to_zac_endpoint_missing_variable(self): + task_dict = {**self.task_dict} + task_dict["variables"] = {} + task_url = ExternalTask.objects.create( + **task_dict, + ) + task = ZacEmailUserLogs(task_url) + with self.assertRaises(Exception) as e: + task.perform() + + self.assertEqual(type(e.exception), MissingVariable) + self.assertEqual( + e.exception.args[0], "The variable recipientList is missing or empty." + ) + + def test_post_recipient_list_to_zac_endpoint_empty_variable(self): + task_dict = {**self.task_dict} + task_dict["variables"] = { + "recipientList": serialize_variable([]), + } + task_url = ExternalTask.objects.create( + **task_dict, + ) + task = ZacEmailUserLogs(task_url) + with self.assertRaises(Exception) as e: + task.perform() + + self.assertEqual(type(e.exception), MissingVariable) + self.assertEqual( + e.exception.args[0], "The variable recipientList is missing or empty." + ) + + def test_post_recipient_list_to_zac_endpoint_wrong_format_email(self): + task_dict = {**self.task_dict} + task_dict["variables"] = { + "recipientList": serialize_variable(["asdsdss"]), + } + task_url = ExternalTask.objects.create( + **task_dict, + ) + task = ZacEmailUserLogs(task_url) + with self.assertRaises(Exception) as e: + task.perform() + + self.assertEqual(type(e.exception), ValidationError) + self.assertEqual( + e.exception.args[0]["recipientList"][0][0], + "Voer een geldig e-mailadres in.", + )