formdef: new digest_templates field (#45633)

This commit is contained in:
Lauréline Guérin 2021-06-22 14:48:47 +02:00
parent 648140c7bb
commit 32826ca8a2
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
21 changed files with 96 additions and 54 deletions

View File

@ -213,7 +213,7 @@ def test_card_templates(pub):
resp = resp.follow()
assert_option_display(resp, 'Templates', 'Custom')
carddef = CardDef.get(carddef.id)
assert carddef.digest_template == 'X{{form_var_test}}Y'
assert carddef.digest_templates['default'] == 'X{{form_var_test}}Y'
assert carddef.lateral_template is None
assert carddef.submission_lateral_template is None
assert 'Existing cards will be updated in the background.' in resp.text
@ -224,7 +224,7 @@ def test_card_templates(pub):
resp = resp.form.submit().follow()
assert_option_display(resp, 'Templates', 'Custom')
carddef = CardDef.get(carddef.id)
assert carddef.digest_template == 'X{{form_var_test}}Y'
assert carddef.digest_templates['default'] == 'X{{form_var_test}}Y'
assert carddef.lateral_template == 'X{{form_var_test}}Y'
assert carddef.submission_lateral_template == 'X{{form_var_test}}YZ'
assert 'Existing cards will be updated in the background.' not in resp.text
@ -239,7 +239,7 @@ def test_card_digest_template(pub):
carddef.fields = [
fields.StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_template = 'X{{ form_var_foo }}Y'
carddef.digest_templates = {'default': 'X{{ form_var_foo }}Y'}
carddef.store()
carddata = carddef.data_class()()
carddata.data = {'1': 'bar'}
@ -261,14 +261,14 @@ def test_card_digest_template(pub):
resp.form['digest_template'] = ''
resp = resp.form.submit().follow()
carddef = CardDef.get(carddef.id)
assert carddef.digest_template is None
assert carddef.digest_templates['default'] is None
assert 'Existing cards will be updated in the background.' in resp.text
# afterjobs are actually run synchronously during tests; we don't have
# to wait to check the digest has been updated:
assert carddef.data_class().get(carddata.id).digest == 'XbarY'
carddef.digest_template = '{{ form_var_foo }}'
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
# a formdef using the carddef as datasource
@ -284,7 +284,7 @@ def test_card_digest_template(pub):
resp = resp.form.submit()
assert 'Can not empty digest template: this card model is used as data source in some forms.' in resp.text
carddef = CardDef.get(carddef.id)
assert carddef.digest_template is not None
assert carddef.digest_templates['default'] is not None
# error: not stored, and no after jobs
resp = app.get('/backoffice/cards/%s/' % carddef.id)
@ -367,7 +367,7 @@ def test_card_custom_view_data_source(pub):
]
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_template = '{{ form_var_foo }}'
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()

View File

@ -70,7 +70,7 @@ def test_data_sources_from_carddefs(pub):
carddef = CardDef()
carddef.name = 'foo'
carddef.fields = []
carddef.digest_template = 'foo bar'
carddef.digest_templates = {'default': 'foo bar'}
carddef.store()
custom_view = pub.custom_view_class()

View File

@ -898,7 +898,7 @@ def test_form_templates(pub):
resp = resp.follow()
assert_option_display(resp, 'Templates', 'Custom')
formdef = FormDef.get(formdef.id)
assert formdef.digest_template == 'X{{form_var_test}}Y'
assert formdef.digest_templates['default'] == 'X{{form_var_test}}Y'
assert formdef.lateral_template is None
assert formdef.submission_lateral_template is None
@ -913,7 +913,7 @@ def test_form_templates(pub):
resp = resp.form.submit().follow()
assert_option_display(resp, 'Templates', 'Custom')
formdef = FormDef.get(formdef.id)
assert formdef.digest_template == 'X{{form_var_test}}Y'
assert formdef.digest_templates['default'] == 'X{{form_var_test}}Y'
assert formdef.lateral_template == 'X{{form_var_test}}Y'
assert formdef.submission_lateral_template == 'X{{form_var_test}}YZ'
assert 'Existing forms will be updated in the background.' not in resp.text
@ -1696,7 +1696,7 @@ def test_form_edit_item_field_data_source(pub):
('python', False, 'Python Expression'),
]
carddef.digest_template = 'plop'
carddef.digest_templates = {'default': 'plop'}
carddef.store()
resp = app.get('/backoffice/forms/1/fields/1/')

View File

@ -83,7 +83,7 @@ def test_cards(pub, local_user):
carddef.name = 'test'
carddef.fields = [fields.StringField(id='0', label='foobar', varname='foo')]
carddef.workflow_roles = {'_viewer': role.id}
carddef.digest_template = 'bla {{ form_var_foo }} xxx'
carddef.digest_templates = {'default': 'bla {{ form_var_foo }} xxx'}
carddef.store()
carddef.data_class().wipe()
@ -176,6 +176,7 @@ def test_cards_import_csv(pub, local_user, auth):
local_user.roles = [role.id]
local_user.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
@ -217,7 +218,7 @@ def test_cards_import_csv(pub, local_user, auth):
]
carddef.workflow_roles = {'_viewer': role.id}
carddef.backoffice_submission_roles = [role.id]
carddef.digest_template = 'bla {{ form_var_foo }} xxx'
carddef.digest_templates = {'default': 'bla {{ form_var_foo }} xxx'}
carddef.store()
carddef.data_class().wipe()
@ -274,6 +275,7 @@ def test_cards_restricted_api(pub, local_user):
formdata.just_created()
formdata.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
@ -325,6 +327,7 @@ def test_cards_http_auth_access(pub, local_user):
formdata.just_created()
formdata.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
@ -368,6 +371,7 @@ def test_card_submit(pub, local_user, auth):
local_user.roles = [role.id]
local_user.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'

View File

@ -77,7 +77,7 @@ def test_api_custom_view_access(pub, local_user):
carddef.name = 'test'
carddef.fields = [fields.StringField(id='0', label='foobar', varname='foo')]
carddef.workflow_roles = {'_viewer': role.id}
carddef.digest_template = 'bla {{ form_var_foo }} xxx'
carddef.digest_templates = {'default': 'bla {{ form_var_foo }} xxx'}
carddef.geolocations = {'base': 'Location'}
carddef.store()

View File

@ -109,7 +109,7 @@ def ics_data(local_user):
fields.StringField(id='0', label='foobar', varname='foobar'),
fields.StringField(id='1', label='foobar2', varname='foobar2'),
]
formdef.digest_template = 'plöp {{ form_var_foobar }} plÔp'
formdef.digest_templates = {'default': 'plöp {{ form_var_foobar }} plÔp'}
formdef.store()
data_class = formdef.data_class()
@ -920,6 +920,7 @@ def test_api_access_restrict_to_anonymised_data(pub, local_user, auth):
formdata.store()
# check normal API behaviour: get all data
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
@ -1231,6 +1232,7 @@ def test_api_global_listing(pub, local_user, user, auth):
app = get_app(pub)
if user == 'api-access':
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'

View File

@ -288,7 +288,7 @@ def test_user_forms(pub, local_user):
assert len(resp.json['data']) == 1
# check digest is part of contents
formdef.digest_template = 'XYZ'
formdef.digest_templates = {'default': 'XYZ'}
formdef.data_class().get(formdata.id).store()
assert formdef.data_class().get(formdata.id).digest == 'XYZ'
resp = get_app(pub).get(sign_uri('/api/user/forms', user=local_user))

View File

@ -764,7 +764,7 @@ def test_backoffice_card_field_columns(pub):
]
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_template = 'card {{form_var_foo}}'
carddef.digest_templates = {'default': 'card {{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
@ -3098,7 +3098,7 @@ def test_global_listing(pub):
formdata = formdef.data_class().get(
re.findall(r'data-link="(.*?)"', app.get('/backoffice/management/listing').text)[0].split('/')[-2]
)
formdata.formdef.digest_template = 'digest of number <{{form_number}}>'
formdata.formdef.digest_templates = {'default': 'digest of number <{{form_number}}>'}
formdata.store()
assert formdata.get(formdata.id).digest
resp = app.get('/backoffice/management/listing')
@ -3564,7 +3564,7 @@ def test_backoffice_sidebar_user_context(pub):
# check there's nothing in the sidebar
assert '/user-pending-forms' not in resp.text
number31.formdef.digest_template = 'digest of number {{form_number}}'
number31.formdef.digest_templates = {'default': 'digest of number {{form_number}}'}
number31.user_id = user.id
number31.store()
resp = app.get('/backoffice/management/form-title/%s/' % number31.id)

View File

@ -216,7 +216,7 @@ def test_studio_card_item_link(pub):
]
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_template = 'card {{form_var_foo}}'
carddef.digest_templates = {'default': 'card {{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
@ -522,7 +522,7 @@ def test_backoffice_cards_wscall_failure_display(http_requests, pub):
carddef.backoffice_submission_roles = user.roles
carddef.workflow_id = workflow.id
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_template = 'card {{form_var_foo}}'
carddef.digest_templates = {'default': 'card {{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()
@ -553,7 +553,7 @@ def test_block_card_item_link(pub, blocks_feature):
]
carddef.backoffice_submission_roles = user.roles
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.digest_template = 'card {{form_var_foo}}'
carddef.digest_templates = {'default': 'card {{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()

View File

@ -768,7 +768,7 @@ def test_carddata_custom_view_is_default(pub):
fields.StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.backoffice_submission_roles = user.roles
carddef.digest_template = '{{ form_var_foo }}'
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()

View File

@ -5325,7 +5325,7 @@ def test_item_field_from_cards(pub):
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
fields.StringField(id='0', label='string', varname='name'),
fields.StringField(id='1', label='string', varname='attr'),
@ -5377,7 +5377,7 @@ def test_item_field_from_custom_view_on_cards(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_attr}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.fields = [
fields.ItemField(id='0', type='item', label='item', varname='item', items=['foo', 'bar', 'baz']),
@ -5456,7 +5456,7 @@ def test_dynamic_item_field_from_custom_view_on_cards(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_attr}}'
carddef.digest_templates = {'default': '{{form_var_attr}}'}
carddef.workflow_roles = {'_editor': user.roles[0]}
carddef.fields = [
fields.ItemField(id='0', type='item', label='item', varname='item', items=['foo', 'bar', 'baz']),
@ -5570,7 +5570,7 @@ def test_item_field_from_cards_check_lazy_live(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
fields.StringField(id='0', label='string', varname='name'),
fields.StringField(id='1', label='string', varname='attr'),
@ -6159,7 +6159,7 @@ def test_item_field_autocomplete_cards_source(pub):
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
fields.StringField(id='0', label='string', varname='name'),
fields.StringField(id='1', label='string', varname='attr'),
@ -8050,7 +8050,7 @@ def test_backoffice_fields_just_after_conditional_form_edit_action(pub):
def test_backoffice_fields_set_from_live(pub):
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
fields.StringField(id='0', label='string', varname='name'),
fields.StringField(id='1', label='string', varname='attr'),

View File

@ -338,7 +338,7 @@ def test_data_source_access_by_id(pub):
carddef.fields = [
StringField(id='1', label='Test', type='string', varname='foo'),
]
carddef.digest_template = '{{ form_var_foo }}'
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
carddef.store()
carddef.data_class().wipe()

View File

@ -932,7 +932,7 @@ def test_lazy_formdata_live_item(pub):
CardDef.wipe()
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
fields.StringField(id='0', label='string', varname='name'),
fields.StringField(id='1', label='string', varname='attr'),
@ -2302,7 +2302,7 @@ def test_form_digest_date(pub):
formdef.name = 'foobar'
formdef.url_name = 'foobar'
formdef.fields = [fields.DateField(id='0', label='date', varname='date')]
formdef.digest_template = 'plop {{ form_var_date }} plop'
formdef.digest_templates = {'default': 'plop {{ form_var_date }} plop'}
formdef.store()
formdata = formdef.data_class()()
@ -2317,21 +2317,21 @@ def test_form_digest_date(pub):
formdata.store()
assert formdef.data_class().get(formdata.id).digest == 'plop 12/05/2015 plop'
formdef.digest_template = 'plop {{ form_var_date|date:"Y" }} plop'
formdef.digest_templates = {'default': 'plop {{ form_var_date|date:"Y" }} plop'}
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'0': time.strptime('2015-05-12', '%Y-%m-%d')}
formdata.store()
assert formdef.data_class().get(formdata.id).digest == 'plop 2015 plop'
formdef.digest_template = 'plop {{ form_var_date_raw|date:"Y" }} plop'
formdef.digest_templates = {'default': 'plop {{ form_var_date_raw|date:"Y" }} plop'}
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'0': time.strptime('2015-05-12', '%Y-%m-%d')}
formdata.store()
assert formdef.data_class().get(formdata.id).digest == 'plop 2015 plop'
formdef.digest_template = 'plop {{ form_var_date|date:"Y" }} plop'
formdef.digest_templates = {'default': 'plop {{ form_var_date|date:"Y" }} plop'}
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'0': None}
@ -2339,7 +2339,7 @@ def test_form_digest_date(pub):
assert formdef.data_class().get(formdata.id).digest == 'plop plop'
# check there's no crash when an invaliad variable is given
formdef.digest_template = 'plop {{ blah|date:"Y" }} plop'
formdef.digest_templates = {'default': 'plop {{ blah|date:"Y" }} plop'}
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'0': time.strptime('2015-05-12', '%Y-%m-%d')}

View File

@ -669,13 +669,13 @@ def test_field_validation():
assert f2.fields[0].validation == {'type': 'regex', 'value': '\\d'}
def test_digest_template():
def test_digest_templates():
formdef = FormDef()
formdef.name = 'Foo'
formdef.fields = []
formdef.digest_template = '{{form_number}}'
formdef.digest_templates = {'default': '{{form_number}}', 'custom-view:foo-bar': 'plop'}
f2 = assert_xml_import_export_works(formdef)
assert f2.digest_template == formdef.digest_template
assert f2.digest_templates == formdef.digest_templates
def test_field_prefill():

View File

@ -5035,7 +5035,7 @@ def test_set_backoffice_field_card_item(two_pubs):
carddef = CardDef()
carddef.name = 'items'
carddef.digest_template = '{{form_var_name}}'
carddef.digest_templates = {'default': '{{form_var_name}}'}
carddef.fields = [
StringField(id='0', label='string', varname='name'),
StringField(id='1', label='string', varname='attr'),
@ -6539,7 +6539,7 @@ def test_call_external_workflow_with_data_sourced_object(two_pubs):
carddef.fields = [
StringField(id='0', label='string', varname='card_string'),
]
carddef.digest_template = '{{ form_var_card_string }}'
carddef.digest_templates = {'default': '{{ form_var_card_string }}'}
carddef.workflow = carddef_wf
carddef.store()
@ -6929,7 +6929,7 @@ def test_edit_carddata_with_data_sourced_object(pub):
StringField(id='1', label='Last Name', varname='last_name'),
ItemField(id='2', label='Profession', type='item', varname='profession', data_source=datasource),
]
carddef.digest_template = '{{ form_var_first_name }} {{ form_var_last_name }}'
carddef.digest_templates = {'default': '{{ form_var_first_name }} {{ form_var_last_name }}'}
carddef.store()
carddata = carddef.data_class()()

View File

@ -380,7 +380,11 @@ class OptionsDirectory(Directory):
def templates(self):
form = Form(enctype='multipart/form-data')
form.add(
StringWidget, 'digest_template', title=_('Digest'), value=self.formdef.digest_template, size=50
StringWidget,
'digest_template',
title=_('Digest'),
value=self.formdef.default_digest_template,
size=50,
)
form.add(
WysiwygTextWidget,
@ -462,10 +466,15 @@ class OptionsDirectory(Directory):
self.formdef.geolocations = None
else:
new_value = widget.parse()
if getattr(self.formdef, attr, None) != new_value:
if attr == 'digest_template':
if attr == 'digest_template':
if self.formdef.default_digest_template != new_value:
self.changed = True
setattr(self.formdef, attr, new_value)
if not self.formdef.digest_templates:
self.formdef.digest_templates = {}
self.formdef.digest_templates['default'] = new_value
else:
if getattr(self.formdef, attr, None) != new_value:
setattr(self.formdef, attr, new_value)
if not form.has_errors():
self.formdef.store(comment=_('Changed "%s" parameters') % title)
return redirect('..')
@ -787,7 +796,7 @@ class FormDefPage(Directory):
)
if (
self.formdef.digest_template
self.formdef.default_digest_template
or self.formdef.lateral_template
or self.formdef.submission_lateral_template
):
@ -1835,7 +1844,7 @@ class FormsDirectory(AccessControlled, Directory):
try:
formdef = self.formdef_class.import_from_xml(fp)
get_session().message = ('info', str(self.import_success_message))
except FormdefImportRecoverableError as e:
except FormdefImportRecoverableError:
fp.seek(0)
formdef = self.formdef_class.import_from_xml(fp, fix_on_error=True)
get_session().message = ('info', str(self.import_error_message))

View File

@ -165,7 +165,7 @@ class CardDefPage(FormDefPage):
)
if (
self.formdef.digest_template
self.formdef.default_digest_template
or self.formdef.lateral_template
or self.formdef.submission_lateral_template
):

View File

@ -1699,7 +1699,7 @@ class FormPage(Directory):
('any', _('to any users'), 'any'),
]
if isinstance(self.formdef, CardDef) and self.formdef.digest_template:
if isinstance(self.formdef, CardDef) and self.formdef.default_digest_template:
options.append(('datasource', _('as data source'), 'datasource'))
form.add(

View File

@ -158,7 +158,7 @@ class CardDef(FormDef):
def get_carddefs_as_data_source(cls):
carddefs_by_id = {}
for carddef in cls.select(lightweight=True, ignore_errors=True, order_by='name'):
if not carddef.digest_template:
if not carddef.default_digest_template:
continue
data_source_id = 'carddef:%s' % carddef.url_name
carddefs_by_id[carddef.id] = carddef

View File

@ -424,7 +424,7 @@ class FormData(StorableObject):
self.evolution = [evo]
def set_auto_fields(self, *args, **kwargs):
fields = {'digest': self.formdef.digest_template}
fields = {'digest': self.formdef.default_digest_template}
if not self.id_display:
# only set id_display once as it may have been set automatically
# by interpreting a webservice response.

View File

@ -116,7 +116,7 @@ class FormDef(StorableObject):
skip_from_360_view = False
include_download_all_button = False
appearance_keywords = None
digest_template = None
digest_templates = None
lateral_template = None
submission_lateral_template = None
drafts_lifespan = None
@ -143,7 +143,6 @@ class FormDef(StorableObject):
'internal_identifier',
'disabled_redirection',
'appearance_keywords',
'digest_template',
'lateral_template',
'submission_lateral_template',
'drafts_lifespan',
@ -228,6 +227,14 @@ class FormDef(StorableObject):
del self.__dict__['receiver_id']
changed = True
if 'digest_template' in self.__dict__:
# migration from a simple template to templates
if not self.digest_templates:
self.digest_templates = {}
self.digest_templates['default'] = self.__dict__['digest_template']
del self.__dict__['digest_template']
changed = True
if not self.table_name and get_publisher().has_site_option('postgresql'):
from . import sql
@ -432,6 +439,10 @@ class FormDef(StorableObject):
sql.do_formdef_tables(self, rebuild_views=True, rebuild_global_views=True)
@property
def default_digest_template(self):
return (self.digest_templates or {}).get('default')
def get_category(self):
if self.category_id:
try:
@ -1067,6 +1078,14 @@ class FormDef(StorableObject):
for auth_context in self.required_authentication_contexts:
ET.SubElement(element, 'method').text = force_text(auth_context)
if self.digest_templates:
digest_templates = ET.SubElement(root, 'digest_templates')
for key, value in self.digest_templates.items():
if not value:
continue
sub = ET.SubElement(digest_templates, 'template')
sub.attrib['key'] = key
sub.text = value
return root
@classmethod
@ -1262,6 +1281,14 @@ class FormDef(StorableObject):
for child in node:
formdef.required_authentication_contexts.append(str(child.text))
if tree.find('digest_templates') is not None:
digest_templates_node = tree.find('digest_templates')
formdef.digest_templates = {}
for child in digest_templates_node:
key = child.attrib['key']
value = xml_node_text(child)
formdef.digest_templates[key] = value
if check_datasources:
# check if datasources are defined
unknown_datasources = set()