From 1869bf3671d1a403fbbf7adb7e55b2e3d0b3c52a Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Wed, 20 Nov 2019 17:15:57 +0100
Subject: [PATCH] jsondatastore: add a search endpoint (#29889)

---
 passerelle/apps/jsondatastore/models.py | 24 ++++++++++++++++++---
 tests/test_jsondatastore.py             | 28 +++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/passerelle/apps/jsondatastore/models.py b/passerelle/apps/jsondatastore/models.py
index 72503f3b..b4991eae 100644
--- a/passerelle/apps/jsondatastore/models.py
+++ b/passerelle/apps/jsondatastore/models.py
@@ -100,9 +100,7 @@ class JsonDataStore(BaseResource):
     class Meta:
         verbose_name = _('JSON Data Store')
 
-    @endpoint(perm='can_access', name='data', pattern=r'$',
-              description=_('Listing'))
-    def list(self, request, name_id=None, q=None, **kwargs):
+    def filter(self, name_id=None, q=None, **kwargs):
         objects = JsonData.objects.filter(datastore=self)
         if name_id is not None:
             objects = objects.filter(name_id=name_id)
@@ -111,8 +109,28 @@ class JsonDataStore(BaseResource):
             objects = [o for o in objects if q in simplify(o.text)]
         for key, value in kwargs.items():
             objects = [o for o in objects if o.content.get(key) == value]
+        return objects
+
+    @endpoint(perm='can_access', name='data', pattern=r'$',
+              description=_('Listing'))
+    def list(self, request, name_id=None, q=None, **kwargs):
+        objects = self.filter(name_id, q, **kwargs)
         return {'data': [x.to_json() for x in objects]}
 
+    @endpoint(perm='can_access', name='search', pattern=r'$',
+              description=_('List content'))
+    def search(self, request, name_id=None, q=None,
+               url_field='url', text_field='text', description_field='description',
+               **kwargs):
+        objects = self.filter(name_id, q, **kwargs)
+        data = []
+        for obj in objects:
+            data.append({
+                'url': obj.content.get(url_field),
+                'text': obj.content.get(text_field) or obj.text,
+                'description': obj.content.get(description_field)})
+        return {'err': 0, 'data': data}
+
     @endpoint(perm='can_access', methods=['post'], name='data',
               pattern=r'create$',
               example_pattern='create',
diff --git a/tests/test_jsondatastore.py b/tests/test_jsondatastore.py
index 90524cdb..adf93964 100644
--- a/tests/test_jsondatastore.py
+++ b/tests/test_jsondatastore.py
@@ -239,3 +239,31 @@ def test_jsondatastore_list_by_q_attribute(app, jsondatastore):
     resp = app.get('/jsondatastore/foobar/data/',
                    params={'q': 'na'})
     assert resp.json['data'] == []
+
+def test_jsondatastore_search(app, jsondatastore):
+    jsondatastore.text_value_template = '{{name}}'
+    jsondatastore.save()
+    resp = app.post_json('/jsondatastore/foobar/data/create?name_id=name1',
+                         params={'me': '1', 'name': 'foÖ', 'url': 'url1'})
+    resp = app.post_json('/jsondatastore/foobar/data/create?name_id=name2',
+                         params={'me': '2', 'name': 'foo', 'url': 'url2'})
+    resp = app.post_json('/jsondatastore/foobar/data/create?name_id=name1',
+                         params={'me': '3', 'name': 'bar', 'url': 'url3'})
+
+    # JSON conformes with combo/apps/search/README
+    resp = app.get('/jsondatastore/foobar/search/',
+                   params={'me': '2'})
+    assert resp.json['data'] == [{'text': 'foo', 'url': 'url2', 'description': None}]
+
+    # specify different fields to return
+    resp = app.get('/jsondatastore/foobar/search/',
+                   params={'me': '2',
+                           'url_field': 'name',
+                           'text_field': 'me',
+                           'description_field': 'me'})
+    assert resp.json['data'] == [{'url': 'foo', 'text': '2', 'description': '2'}]
+
+    # filter on main text field
+    resp = app.get('/jsondatastore/foobar/search/',
+                   params={'q': 'Oô'})
+    assert sorted([d['url'] for d in resp.json['data']]) == ['url1', 'url2']
-- 
2.24.0

