From 2f159191c17254582585f1ef0c7d910ed8b8b5ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Mon, 15 Aug 2022 19:56:08 +0200
Subject: [PATCH] fields: add check for value given as block field (#63437)

---
 tests/workflow/test_all.py  | 46 +++++++++++++++++++++++++++++++++++++
 wcs/fields.py               |  2 ++
 wcs/wf/backoffice_fields.py |  4 ++--
 3 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/tests/workflow/test_all.py b/tests/workflow/test_all.py
index c60503ed5..d6aa7cbf6 100644
--- a/tests/workflow/test_all.py
+++ b/tests/workflow/test_all.py
@@ -5749,6 +5749,52 @@ def test_set_backoffice_field_block_template_tag(pub):
     assert formdata.data['bo1_display'] == 'XNoneY'
 
 
+def test_set_backoffice_field_invalid_block_value(pub):
+    BlockDef.wipe()
+    Workflow.wipe()
+    FormDef.wipe()
+
+    block = BlockDef()
+    block.name = 'foobar'
+    block.fields = [StringField(id='123', required=True, label='Test', type='string', varname='foo')]
+    block.store()
+
+    wf = Workflow(name='xxx')
+    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
+    st1 = wf.add_status('Status1')
+    wf.backoffice_fields_formdef.fields = [
+        BlockField(id='bo1', label='1st backoffice field', max_items=3, type='block:foobar'),
+    ]
+    wf.store()
+
+    formdef = FormDef()
+    formdef.name = 'baz'
+    formdef.fields = []
+    formdef.workflow_id = wf.id
+    formdef.store()
+
+    formdata = formdef.data_class()()
+    formdata.just_created()
+    formdata.store()
+    get_publisher().substitutions.feed(formdata)
+
+    item = SetBackofficeFieldsWorkflowStatusItem()
+    item.parent = st1
+    item.fields = [{'field_id': 'bo1', 'value': 'xxx'}]
+
+    pub.loggederror_class.wipe()
+    item.perform(formdata)
+    assert pub.loggederror_class.count() == 1
+    logged_error = pub.loggederror_class.select()[0]
+    assert (
+        logged_error.summary
+        == 'Failed to set Field Block (foobar) field (bo1), error: invalid value for block'
+    )
+
+    formdata = formdef.data_class().get(formdata.id)
+    assert not formdata.data.get('bo1')
+
+
 def test_set_backoffice_field_immediate_use(http_requests, pub):
     Workflow.wipe()
     FormDef.wipe()
diff --git a/wcs/fields.py b/wcs/fields.py
index e5a7a05dc..f63b5c903 100644
--- a/wcs/fields.py
+++ b/wcs/fields.py
@@ -3855,6 +3855,8 @@ class BlockField(WidgetField):
             value = None
         if isinstance(value, BlockRowValue):
             value = value.make_value(block=self.block, field=self, data=data)
+        elif value and not (isinstance(value, dict) and 'data' in value and 'schema' in value):
+            raise SetValueError('invalid value for block')
         super().set_value(data, value, **kwargs)
 
     def get_json_value(self, value, **kwargs):
diff --git a/wcs/wf/backoffice_fields.py b/wcs/wf/backoffice_fields.py
index 80e20ac7b..86c5f1b09 100644
--- a/wcs/wf/backoffice_fields.py
+++ b/wcs/wf/backoffice_fields.py
@@ -169,7 +169,7 @@ class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem):
                 except ValueError as e:
                     summary = _('Failed to convert %(class)s value to %(kind)s field (%(id)s)') % {
                         'class': type(new_value),
-                        'kind': getattr(formdef_field, 'description', _('unknown')),
+                        'kind': formdef_field.get_type_label(),
                         'id': field['field_id'],
                     }
                     expression_dict = self.get_expression(field['value'])
@@ -187,7 +187,7 @@ class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem):
                 formdef_field.set_value(formdata.data, new_value)
             except SetValueError as e:
                 summary = _('Failed to set %(kind)s field (%(id)s), error: %(exc)s') % {
-                    'kind': getattr(formdef_field, 'description', _('unknown')),
+                    'kind': formdef_field.get_type_label(),
                     'id': field['field_id'],
                     'exc': e,
                 }
-- 
2.37.2

