From 89da45a91ef8cbd2ae36ff0a33e21c912d52c061 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sat, 27 Aug 2022 17:58:02 +0200
Subject: [PATCH] backoffice: allow {{form_user}} usage in live prefills during
 edition (#68379)

---
 tests/backoffice_pages/test_all.py | 46 ++++++++++++++++++++++++++++++
 wcs/backoffice/management.py       |  4 +++
 wcs/forms/root.py                  |  6 ++++
 3 files changed, 56 insertions(+)

diff --git a/tests/backoffice_pages/test_all.py b/tests/backoffice_pages/test_all.py
index 97d60a417..b389e04d9 100644
--- a/tests/backoffice_pages/test_all.py
+++ b/tests/backoffice_pages/test_all.py
@@ -1999,6 +1999,52 @@ def test_backoffice_wfedit_and_live_condition(pub):
     assert live_resp.json['result']['2']['visible']
 
 
+def test_backoffice_wfedit_and_prefill_with_user_variable(pub):
+    user = create_user(pub)
+    create_environment(pub)
+    formdef = FormDef.get_by_urlname('form-title')
+    formdef.fields[0].varname = 'foo'
+    formdef.fields[1].condition = {'type': 'django', 'value': 'form_var_foo == "test"'}
+    formdef.fields.append(
+        fields.StringField(
+            id='100',
+            label='user name',
+            type='string',
+            prefill={'type': 'string', 'value': 'a{{form_user_name}}b'},
+        )
+    )
+    formdef.store()
+
+    form_class = formdef.data_class()
+
+    second_user = pub.user_class(name='foobar')
+    second_user.store()
+    number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
+    number31.user_id = second_user.id
+    number31.store()
+
+    # attach a custom workflow
+    workflow = Workflow(name='wfedit')
+    st1 = workflow.add_status('Status1', number31.status.split('-')[1])
+
+    wfedit = st1.add_action('editable', id='_wfedit')
+    wfedit.by = [user.roles[0]]
+    workflow.store()
+
+    formdef.workflow_id = workflow.id
+    formdef.store()
+
+    app = login(get_app(pub))
+
+    resp = app.get('/backoffice/management/form-title/%s/' % number31.id)
+    resp = resp.form.submit('button_wfedit').follow()
+    assert resp.form['f100'].value == 'afoobarb'
+
+    live_url = resp.html.find('form').attrs['data-live-url']
+    live_resp = app.post(live_url + '?prefilled_100=on', params=resp.form.submit_fields())
+    assert live_resp.json['result']['100']['content'] == 'afoobarb'
+
+
 def test_global_listing(pub):
     create_user(pub)
     create_environment(pub)
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index fbe52eb32..9cd5cbdba 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -2907,6 +2907,10 @@ class FormPage(Directory):
 
 
 class FormBackofficeEditPage(FormFillPage):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.edit_mode = True
+
     def create_form(self, *args, **kwargs):
         form = super().create_form(*args, **kwargs)
         form.attrs['data-live-url'] = self.formdef.get_url(backoffice=True) + 'live'
diff --git a/wcs/forms/root.py b/wcs/forms/root.py
index e7bccb4e1..653fb04fa 100644
--- a/wcs/forms/root.py
+++ b/wcs/forms/root.py
@@ -834,6 +834,11 @@ class FormPage(Directory, FormTemplateMixin):
         computed_values = get_session().get_by_magictoken('%s-computed' % magictoken) or {}
         formdata.data.update(computed_values)
 
+        if formdata.data.get('edited_formdata_id'):
+            # during editing (edited_formdata_id is set when starting edition,
+            # when there's no magictoken yet)
+            self.edited_data = self.formdef.data_class().get(formdata.data.get('edited_formdata_id'))
+
         if self.edit_mode:
             if magictoken is None:
                 # restore edited data early on as it may be required to
@@ -1002,6 +1007,7 @@ class FormPage(Directory, FormTemplateMixin):
                 self.edited_data.feed_session()
                 token = randbytes(8)
                 get_request().form['magictoken'] = token
+                self.edited_data.data['edited_formdata_id'] = self.edited_data.id
                 session.add_magictoken(token, self.edited_data.data)
 
                 # and restore computed data
-- 
2.37.2

