From b1630a9994c29360537b3196d361b472706bb58e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Fri, 1 Jul 2022 14:02:09 +0200
Subject: [PATCH] backoffice: apply form user as "current user" filter on card
 sources (#66870)

---
 tests/backoffice_pages/test_submission.py | 100 ++++++++++++++++++++++
 wcs/backoffice/management.py              |  12 ++-
 2 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/tests/backoffice_pages/test_submission.py b/tests/backoffice_pages/test_submission.py
index 8061bc5ad..0b0b7c824 100644
--- a/tests/backoffice_pages/test_submission.py
+++ b/tests/backoffice_pages/test_submission.py
@@ -8,6 +8,7 @@ import pytest
 
 from wcs import fields
 from wcs.api_utils import sign_url
+from wcs.carddef import CardDef
 from wcs.formdef import FormDef
 from wcs.qommon.http_request import HTTPRequest
 from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef
@@ -1632,6 +1633,105 @@ def test_backoffice_submission_user_selection_then_live_prefill(pub):
     assert live_resp.json == {'result': {'3': {'visible': True, 'content': 'test9@invalid'}}}
 
 
+def test_backoffice_submission_user_selection_then_card_data_source(pub):
+    pub.session_manager.session_class.wipe()
+
+    user = create_user(pub)
+
+    for i in range(10):
+        random_user = pub.user_class()
+        random_user.name = 'random user %s' % i
+        random_user.email = 'test%s@invalid' % i
+        random_user.store()
+
+    CardDef.wipe()
+    carddef = CardDef()
+    carddef.name = 'foo'
+    carddef.fields = []
+    carddef.digest_templates = {'default': 'card {{ form_number }}'}
+    carddef.backoffice_submission_roles = user.roles
+    carddef.workflow_roles = {'_editor': user.roles[0]}
+    carddef.user_support = 'optional'
+    carddef.store()
+
+    carddata = carddef.data_class()()
+    carddata.data = {}
+    carddata.user_id = user.id
+    carddata.just_created()
+    carddata.store()
+
+    for i in range(3):
+        carddata = carddef.data_class()()
+        carddata.data = {}
+        carddata.user_id = random_user.id
+        carddata.just_created()
+        carddata.store()
+
+    pub.custom_view_class.wipe()
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'shared custom test view'
+    custom_view.formdef = carddef
+    custom_view.visibility = 'datasource'
+    custom_view.columns = {'list': [{'id': 'id'}]}
+    custom_view.filters = {
+        'filter-user': 'on',
+        'filter-user-value': '__current__',
+    }
+    custom_view.store()
+
+    Workflow.wipe()
+    workflow = Workflow(name='wfedit')
+    st1 = workflow.add_status('Status1')
+    wfedit = st1.add_action('editable', id='_wfedit')
+    wfedit.by = [user.roles[0]]
+    workflow.store()
+
+    FormDef.wipe()
+    formdef = FormDef()
+    formdef.name = 'form title'
+    formdef.fields = [
+        fields.PageField(id='1', label='1st page', type='page'),
+        fields.PageField(id='2', label='2nd page', type='page'),
+        fields.ItemField(
+            id='3',
+            label='Test',
+            type='item',
+            data_source={'type': 'carddef:foo:%s' % custom_view.slug, 'value': ''},
+        ),
+    ]
+    formdef.backoffice_submission_roles = user.roles[:]
+    formdef.workflow_roles = {'_receiver': 1}
+    formdef.workflow_id = workflow.id
+    formdef.store()
+    formdef.data_class().wipe()
+
+    app = login(get_app(pub))
+    resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
+
+    resp = resp.form.submit('submit')  # -> 2nd page
+    # check the field doesn't propose cards linked to agent
+    assert resp.form['f3'].options == [('', False, '---')]
+
+    formdef.data_class().wipe()
+    resp = app.get('/backoffice/submission/%s/' % formdef.url_name)
+    resp.form['user_id'] = str(random_user.id)  # happens via javascript
+    resp = resp.form.submit('submit')  # -> 2nd page
+    # check three cards are proposed
+    assert len(resp.form['f3'].options) == 3
+    resp = resp.form.submit('submit')  # -> validation page
+    resp = resp.form.submit('submit')  # -> submit
+    assert formdef.data_class().count() == 1
+    formdata = formdef.data_class().select()[0]
+    assert formdata.data['3_display'] == 'card 2'
+
+    # check it's also ok during edition
+    resp = app.get(formdata.get_backoffice_url())
+    resp = resp.form.submit('button_wfedit')
+    resp = resp.follow()
+    resp = resp.form.submit('submit')  # page 2
+    assert len(resp.form['f3'].options) == 3
+
+
 def test_backoffice_submission_sidebar_lateral_block(pub):
     user = create_user(pub)
 
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index b73a4866d..ad663ea6a 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -2047,8 +2047,16 @@ class FormPage(Directory):
                     criterias.append(LessOrEqual('last_update_time', filter_date_value))
                 criterias[-1]._label = '%s: %s' % (filter_field.label, filter_field_value)
             elif filter_field.type == 'user-id':
-                if filter_field_value == '__current__' and get_request().user:
-                    filter_field_value = str(get_request().user.id)
+                if filter_field_value == '__current__':
+                    context_vars = get_publisher().substitutions.get_context_variables(mode='lazy')
+                    if get_request().is_in_backoffice() and context_vars.get('form'):
+                        # in case of backoffice submission/edition, take user associated
+                        # with the form being submitted/edited, if any.
+                        form_user = context_vars.get('form_user')
+                        if form_user:
+                            filter_field_value = str(form_user.id)
+                    elif get_request().user:
+                        filter_field_value = str(get_request().user.id)
                 criterias.append(Equal('user_id', filter_field_value))
             elif filter_field.type == 'submission-agent-id':
                 criterias.append(Equal('submission_agent_id', filter_field_value))
-- 
2.36.1

