From 9a2e262ca4492d581d95cbe817c52502f6a700c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 3 May 2022 08:26:51 +0200 Subject: [PATCH] misc: limit computed field data source selection to cards (#64499) --- tests/admin_pages/test_datasource.py | 30 ++++++++++++++++++++ tests/admin_pages/test_form.py | 16 +++++++++-- wcs/admin/data_sources.py | 3 +- wcs/data_sources.py | 42 ++++++++++++++++++---------- wcs/fields.py | 6 ++-- 5 files changed, 76 insertions(+), 21 deletions(-) diff --git a/tests/admin_pages/test_datasource.py b/tests/admin_pages/test_datasource.py index 5a222c3a1..e56141cdf 100644 --- a/tests/admin_pages/test_datasource.py +++ b/tests/admin_pages/test_datasource.py @@ -280,6 +280,36 @@ def test_data_sources_type_options_jsonp(pub): assert 'jsonp' in [x[0] for x in resp.form['data_source$type'].options] +def test_data_sources_type_options_python(pub): + create_superuser(pub) + + data_source = NamedDataSource(name='foobar') + data_source.store() + + if not pub.site_options.has_section('options'): + pub.site_options.add_section('options') + pub.site_options.set('options', 'disable-python-expressions', 'false') + with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: + pub.site_options.write(fd) + + app = login(get_app(pub)) + resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) + assert 'python' in [x[0] for x in resp.form['data_source$type'].options] + + pub.site_options.set('options', 'disable-python-expressions', 'true') + with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: + pub.site_options.write(fd) + + resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) + assert 'python' not in [x[0] for x in resp.form['data_source$type'].options] + + # make sure it's still displayed for sources using it. + data_source.data_source = {'type': 'formula', 'value': '[]'} + data_source.store() + resp = app.get('/backoffice/settings/data-sources/%s/edit' % data_source.id) + assert 'python' in [x[0] for x in resp.form['data_source$type'].options] + + def test_data_sources_agenda_manual_qs_data_type_options(pub): create_superuser(pub) diff --git a/tests/admin_pages/test_form.py b/tests/admin_pages/test_form.py index 7dce77de7..62aba857d 100644 --- a/tests/admin_pages/test_form.py +++ b/tests/admin_pages/test_form.py @@ -3248,9 +3248,19 @@ def test_form_new_computed_field(pub): resp = resp.forms[0].submit().follow() assert len(FormDef.get(1).fields) == 1 - assert FormDef.get(1).fields[0].key == 'computed' - assert FormDef.get(1).fields[0].label == 'foobar' - assert FormDef.get(1).fields[0].varname == 'foobar' + field = FormDef.get(1).fields[0] + assert field.key == 'computed' + assert field.label == 'foobar' + assert field.varname == 'foobar' + + CardDef.wipe() + carddef = CardDef() + carddef.name = 'Baz' + carddef.digest_templates = {'default': 'plop'} + carddef.store() + resp = app.get('/backoffice/forms/%s/fields/%s/' % (formdef.id, field.id)) + # only cards + assert resp.form['data_source$type'].options == [('None', True, 'None'), ('carddef:baz', False, 'Baz')] def test_form_category_management_roles(pub, backoffice_user, backoffice_role): diff --git a/wcs/admin/data_sources.py b/wcs/admin/data_sources.py index d61694f3b..05fff8827 100644 --- a/wcs/admin/data_sources.py +++ b/wcs/admin/data_sources.py @@ -88,8 +88,7 @@ class NamedDataSourceUI: 'data_source', value=self.datasource.data_source, title=_('Data Source'), - allow_geojson=True, - allow_named_sources=False, + allowed_source_types={'json', 'jsonp', 'geojson', 'python'}, required=True, ) form.add( diff --git a/wcs/data_sources.py b/wcs/data_sources.py index 64c0afcad..5d6bb708b 100644 --- a/wcs/data_sources.py +++ b/wcs/data_sources.py @@ -54,9 +54,16 @@ def register_data_source_function(function, function_name=None): class DataSourceSelectionWidget(CompositeWidget): - def __init__( - self, name, value=None, allow_jsonp=True, allow_geojson=False, allow_named_sources=True, **kwargs - ): + def __init__(self, name, value=None, allowed_source_types=None, disallowed_source_types=None, **kwargs): + if allowed_source_types is None: + allowed_source_types = {'json', 'jsonp', 'geojson', 'named', 'cards', 'python'} + if get_publisher().has_site_option('disable-python-expressions'): + allowed_source_types.remove('python') + if get_publisher().has_site_option('disable-jsonp-sources'): + allowed_source_types.remove('jsonp') + if disallowed_source_types: + allowed_source_types = allowed_source_types.difference(disallowed_source_types) + CompositeWidget.__init__(self, name, value, **kwargs) if not value: @@ -64,7 +71,7 @@ class DataSourceSelectionWidget(CompositeWidget): options = [(None, _('None'), None)] - if allow_named_sources: + if 'cards' in allowed_source_types: from wcs.carddef import CardDef cards_options = [ @@ -78,6 +85,7 @@ class DataSourceSelectionWidget(CompositeWidget): options.append(OptGroup(_('Cards'))) options.extend(cards_options) + if 'named' in allowed_source_types: admin_accessible = NamedDataSource.is_admin_accessible() nds_options = [] nds_agenda_options = [] @@ -136,17 +144,23 @@ class DataSourceSelectionWidget(CompositeWidget): options.append(OptGroup(name or _('Without category'))) options.extend(nds_by_category_names[name]) - if len(options) > 1: + generic_options = [] + if 'json' in allowed_source_types: + generic_options.append(('json', _('JSON URL'), 'json', {'data-maybe-datetimes': 'true'})) + if 'jsonp' in allowed_source_types: + generic_options.append(('jsonp', _('JSONP URL'), 'jsonp')) + elif value.get('type') == 'jsonp': + generic_options.append(('jsonp', _('JSONP URL (deprecated)'), 'jsonp')) + if 'geojson' in allowed_source_types: + generic_options.append(('geojson', _('GeoJSON URL'), 'geojson')) + if 'python' in allowed_source_types: + generic_options.append(('formula', _('Python Expression'), 'python')) + elif value.get('type') == 'formula': + generic_options.append(('formula', _('Python Expression (deprecated)'), 'python')) + + if len(options) > 1 and generic_options: options.append(OptGroup(_('Generic Data Sources'))) - options.append(('json', _('JSON URL'), 'json', {'data-maybe-datetimes': 'true'})) - if allow_jsonp and ( - value.get('type') == 'jsonp' or not get_publisher().has_site_option('disable-jsonp-sources') - ): - options.append(('jsonp', _('JSONP URL'), 'jsonp')) - if allow_geojson: - options.append(('geojson', _('GeoJSON URL'), 'geojson')) - if not get_publisher().has_site_option('disable-python-expressions'): - options.append(('formula', _('Python Expression'), 'python')) + options.extend(generic_options) self.add( SingleSelectWidget, diff --git a/wcs/fields.py b/wcs/fields.py index bd0f1924e..218d27a37 100644 --- a/wcs/fields.py +++ b/wcs/fields.py @@ -1241,6 +1241,7 @@ class StringField(WidgetField): value=self.data_source, title=_('Data Source'), hint=_('This will allow autocompletion from an external source.'), + disallowed_source_types={'geojson'}, advanced=True, required=False, ) @@ -2025,6 +2026,7 @@ class ItemFieldMixin: value=self.data_source, required=False, hint=_('This will get the available items from an external source.'), + disallowed_source_types={'geojson'}, attrs={'data-dynamic-display-child-of': 'data_mode', 'data-dynamic-display-value': 'data-source'}, ) @@ -3932,8 +3934,8 @@ class ComputedField(Field): data_sources.DataSourceSelectionWidget, 'data_source', value=self.data_source, - allow_jsonp=False, - title=_('Data Source'), + allowed_source_types={'cards'}, + title=_('Data Source (cards only)'), hint=_('This will make linked card data available for expressions.'), required=False, )