From 4f0d08089006e97d63ba7b7180d0b7b429112051 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 28 Jul 2022 18:05:06 +0200
Subject: [PATCH] fields: restrict computed field datasource to carddefs
 (#64499)

---
 tests/admin_pages/test_form.py | 16 +++++++++---
 wcs/data_sources.py            | 45 ++++++++++++++++++++++------------
 wcs/fields.py                  |  2 +-
 3 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/tests/admin_pages/test_form.py b/tests/admin_pages/test_form.py
index 50d6e99f0..591fd7a6a 100644
--- a/tests/admin_pages/test_form.py
+++ b/tests/admin_pages/test_form.py
@@ -3241,9 +3241,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/data_sources.py b/wcs/data_sources.py
index 8fec665a6..3bb471857 100644
--- a/wcs/data_sources.py
+++ b/wcs/data_sources.py
@@ -55,16 +55,21 @@ 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
+        self,
+        name,
+        value=None,
+        allow_jsonp=True,
+        allow_geojson=False,
+        allow_named_sources=True,
+        restrict_to_card_sources=False,
+        **kwargs,
     ):
         CompositeWidget.__init__(self, name, value, **kwargs)
 
         if not value:
             value = {}
 
-        options = [(None, _('None'), None)]
-
-        if allow_named_sources:
+        def _add_card_options(options):
             from wcs.carddef import CardDef
 
             cards_options = [
@@ -78,6 +83,7 @@ class DataSourceSelectionWidget(CompositeWidget):
                 options.append(OptGroup(_('Cards')))
                 options.extend(cards_options)
 
+        def _add_nameddatasource_options(options):
             admin_accessible = NamedDataSource.is_admin_accessible()
             nds_options = []
             nds_agenda_options = []
@@ -136,17 +142,26 @@ class DataSourceSelectionWidget(CompositeWidget):
                         options.append(OptGroup(name or _('Without category')))
                         options.extend(nds_by_category_names[name])
 
-        if len(options) > 1:
-            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'))
+        def _add_generic_options(options):
+            if len(options) > 1:
+                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 = [(None, _('None'), None)]
+        if allow_named_sources:
+            _add_card_options(options)
+            if not restrict_to_card_sources:
+                _add_nameddatasource_options(options)
+        if not restrict_to_card_sources:
+            _add_generic_options(options)
 
         self.add(
             SingleSelectWidget,
diff --git a/wcs/fields.py b/wcs/fields.py
index bd0f1924e..adc6d614f 100644
--- a/wcs/fields.py
+++ b/wcs/fields.py
@@ -3932,7 +3932,7 @@ class ComputedField(Field):
             data_sources.DataSourceSelectionWidget,
             'data_source',
             value=self.data_source,
-            allow_jsonp=False,
+            restrict_to_card_sources=True,
             title=_('Data Source'),
             hint=_('This will make linked card data available for expressions.'),
             required=False,
-- 
2.35.1

