From 46c5c06755ecb628693bdc1a801cc990f1f7f0a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sat, 14 May 2022 10:47:27 +0200
Subject: [PATCH] workflows: add option to configure notification target URL
 (#64584)

---
 tests/workflow/test_notification.py | 44 +++++++++++++++++++++++++++++
 wcs/wf/notification.py              | 24 ++++++++++++++--
 2 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/tests/workflow/test_notification.py b/tests/workflow/test_notification.py
index a0605f26d..7fab5667d 100644
--- a/tests/workflow/test_notification.py
+++ b/tests/workflow/test_notification.py
@@ -278,3 +278,47 @@ def test_notifications_to_users_template(sql_pub, http_requests):
     logged_error = sql_pub.loggederror_class.select()[2]
     assert logged_error.summary == 'Failed to compute template'
     assert logged_error.formdata_id == str(formdata.id)
+
+
+def test_notifications_target_url(sql_pub, http_requests):
+    pub = sql_pub
+    pub.substitutions.feed(pub)
+    pub.user_class.wipe()
+    user = pub.user_class()
+    user.name_identifiers = ['xxx']
+    user.store()
+
+    FormDef.wipe()
+
+    formdef = FormDef()
+    formdef.name = 'baz'
+    formdef.fields = []
+    formdef.store()
+    formdef.data_class().wipe()
+
+    formdata = formdef.data_class()()
+    formdata.user_id = user.id
+    formdata.just_created()
+    formdata.store()
+
+    if not pub.site_options.has_section('variables'):
+        pub.site_options.add_section('variables')
+    pub.site_options.set('variables', 'portal_url', 'https://portal/')
+
+    item = SendNotificationWorkflowStatusItem()
+    item.title = 'xxx'
+    item.body = 'XXX'
+    item.target_url = '{{ portal_url }}plop'
+
+    http_requests.empty()
+    item.perform(formdata)
+    assert http_requests.count() == 1
+    assert http_requests.get_last('url') == 'https://portal/api/notification/add/'
+    assert json.loads(http_requests.get_last('body')) == {
+        'body': 'XXX',
+        'url': 'https://portal/plop',
+        'id': 'formdata:%s' % formdata.get_display_id(),
+        'origin': '',
+        'summary': 'xxx',
+        'name_ids': ['xxx'],
+    }
diff --git a/wcs/wf/notification.py b/wcs/wf/notification.py
index 9e9a53ad8..7f722b4f4 100644
--- a/wcs/wf/notification.py
+++ b/wcs/wf/notification.py
@@ -39,6 +39,7 @@ class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
     title = None
     body = None
     origin = None
+    target_url = None
 
     # webservice parameters
     varname = 'notification'
@@ -70,7 +71,7 @@ class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
         return _(self.description)
 
     def get_parameters(self):
-        return ('to', 'users_template', 'title', 'body', 'origin', 'condition')
+        return ('to', 'users_template', 'title', 'body', 'target_url', 'origin', 'condition')
 
     def add_parameters_widgets(self, form, parameters, prefix='', formdef=None, **kwargs):
         if 'to' in parameters:
@@ -116,6 +117,18 @@ class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
                 rows=5,
                 validation_function=ComputedExpressionWidget.validate_template,
             )
+        if 'target_url' in parameters:
+            form.add(
+                StringWidget,
+                '%surl' % prefix,
+                title=_('URL'),
+                value=self.url,
+                required=False,
+                advanced=True,
+                hint=_(
+                    'Defaults to card/form URL. Common variables are available with the {{variable}} syntax.'
+                ),
+            )
         if 'origin' in parameters:
             form.add(
                 StringWidget,
@@ -140,7 +153,7 @@ class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
 
     def get_computed_strings(self):
         yield from super().get_computed_strings()
-        yield from [self.title, self.body, self.users_template]
+        yield from [self.title, self.body, self.users_template, self.target_url]
 
     def perform(self, formdata):
         if not (self.is_available() and (self.to or self.users_template) and self.title and self.body):
@@ -222,10 +235,15 @@ class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
         if not name_ids:
             return
 
+        if self.target_url:
+            target_url = self.compute(self.target_url, allow_python=False, allow_ezt=False)
+        else:
+            target_url = formdata.get_url()
+
         self.post_data = {
             'summary': title,
             'body': body,
-            'url': formdata.get_url(),
+            'url': target_url,
             'origin': self.origin or '',
             'id': 'formdata:%s' % formdata.get_display_id(),
             'name_ids': list(name_ids),
-- 
2.36.1

