From 03717dc521d7e03335cfca8c87f7b5bb1fc9d9a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 11 Jan 2022 15:27:47 +0100
Subject: [PATCH 4/4] custom-views: record error on unknown filter (#59224)

---
 tests/test_carddef.py        | 38 ++++++++++++++++++++++++++++++++++++
 tests/test_formdata.py       | 18 ++++++++++++++++-
 wcs/backoffice/management.py |  7 ++++++-
 wcs/custom_views.py          |  2 +-
 4 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/tests/test_carddef.py b/tests/test_carddef.py
index 33791b83..e1fe7973 100644
--- a/tests/test_carddef.py
+++ b/tests/test_carddef.py
@@ -422,6 +422,43 @@ def test_get_data_source_custom_view(pub):
     assert CardDef.get_data_source_custom_view('carddef:foo-2:view', carddef=carddef1) is None
 
 
+def test_data_source_custom_view_unknown_filter(pub):
+    CardDef.wipe()
+    carddef = CardDef()
+    carddef.name = 'foo'
+    carddef.fields = [
+        StringField(id='1', label='Test', type='string', varname='foo'),
+    ]
+    carddef.digest_templates = {'default': '{{ form_var_foo }}'}
+    carddef.store()
+    carddef.data_class().wipe()
+
+    carddata = carddef.data_class()()
+    carddata.data = {'1': 'Hello'}
+    carddata.just_created()
+    carddata.store()
+
+    pub.custom_view_class.wipe()
+    custom_view = pub.custom_view_class()
+    custom_view.title = 'view'
+    custom_view.formdef = carddef
+    custom_view.columns = {'list': [{'id': 'id'}]}
+    custom_view.filters = {'filter-42': 'on', 'filter-42-value': 'Hello', 'filter-foobar': 'baz'}
+    custom_view.visibility = 'datasource'
+    custom_view.store()
+
+    assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Hello']
+    assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == []
+    if pub.is_using_postgresql():
+        assert pub.loggederror_class.count() == 2
+        logged_error = pub.loggederror_class.select(order_by='id')[0]
+        assert logged_error.summary == 'Invalid filter "42"'
+        assert logged_error.formdef_id == str(carddef.id)
+        logged_error = pub.loggederror_class.select(order_by='id')[1]
+        assert logged_error.summary == 'Invalid filter "foobar"'
+        assert logged_error.formdef_id == str(carddef.id)
+
+
 def test_data_source_custom_view_digest(pub):
     CardDef.wipe()
     carddef = CardDef()
@@ -443,6 +480,7 @@ def test_data_source_custom_view_digest(pub):
     carddata2.just_created()
     carddata2.store()
 
+    pub.custom_view_class.wipe()
     custom_view = pub.custom_view_class()
     custom_view.title = 'view'
     custom_view.formdef = carddef
diff --git a/tests/test_formdata.py b/tests/test_formdata.py
index 837fee72..4d707239 100644
--- a/tests/test_formdata.py
+++ b/tests/test_formdata.py
@@ -1763,7 +1763,23 @@ def test_lazy_global_forms(pub):
     tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"unknown"|count}}')
     assert tmpl.render(context) == '0'
 
-    pub.custom_view_class.wipe()
+    custom_view4 = pub.custom_view_class()
+    custom_view4.title = 'unknown filter'
+    custom_view4.formdef = formdef
+    custom_view4.columns = {'list': [{'id': 'id'}]}
+    custom_view4.filters = {'filter-42': 'on', 'filter-42-value': 'foo', 'filter-foobar': 'baz'}
+    custom_view4.visibility = 'any'
+    custom_view4.store()
+    tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"unknown-filter"|count}}')
+    assert tmpl.render(context) == '0'
+    if pub.is_using_postgresql():
+        assert pub.loggederror_class.count() == 2
+        logged_error = pub.loggederror_class.select(order_by='id')[0]
+        assert logged_error.summary == 'Invalid filter "42"'
+        assert logged_error.formdef_id == str(formdef.id)
+        logged_error = pub.loggederror_class.select(order_by='id')[1]
+        assert logged_error.summary == 'Invalid filter "foobar"'
+        assert logged_error.formdef_id == str(formdef.id)
 
 
 def test_lazy_variables(pub, variable_test_data):
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index be66bf6e..581aef43 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -1639,7 +1639,7 @@ class FormPage(Directory):
         query_overrides = get_request().form
         return self.get_view_criterias(query_overrides, request=get_request())
 
-    def get_view_criterias(self, query_overrides=None, request=None):
+    def get_view_criterias(self, query_overrides=None, request=None, record_errors=False):
         from wcs import sql
 
         fake_fields = [
@@ -1829,6 +1829,11 @@ class FormPage(Directory):
                 raise RequestError(error_message)
             if self.view_type == 'table':
                 get_session().message = ('warning', error_message)
+            if record_errors:
+                for unknown_filter in unknown_filters:
+                    get_publisher().record_error(
+                        _('Invalid filter "%s"') % unknown_filter, formdef=self.formdef
+                    )
             criterias.append(Equal('status', '_none'))
 
         return criterias
diff --git a/wcs/custom_views.py b/wcs/custom_views.py
index 49ea39c6..59d6b23c 100644
--- a/wcs/custom_views.py
+++ b/wcs/custom_views.py
@@ -159,7 +159,7 @@ class CustomView(StorableObject):
             formdef = self.formdef
 
         form_page = FormPage(formdef=formdef, view=self, update_breadcrumbs=False)
-        criterias = form_page.get_view_criterias()
+        criterias = form_page.get_view_criterias(record_errors=True)
 
         selected_filter = self.get_filter()
         if selected_filter and selected_filter != 'all':
-- 
2.34.1

