From ffc4323b32498f097cb71e4bff9095afacb46338 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Sat, 29 Oct 2022 14:54:07 +0200 Subject: [PATCH] api: apply named ds parameters on autocomplete results (#39723) --- tests/form_pages/test_all.py | 38 ++++++++++++++++++++++++++++++++---- wcs/api.py | 21 ++++++++------------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/tests/form_pages/test_all.py b/tests/form_pages/test_all.py index d4b2ee05d..c52cd1db3 100644 --- a/tests/form_pages/test_all.py +++ b/tests/form_pages/test_all.py @@ -6562,7 +6562,7 @@ def test_item_field_autocomplete_json_source(http_requests, pub, error_email, em resp2 = app.get(select2_url + '?q=hell') assert len(rsps.calls) == 1 assert rsps.calls[-1].request.url == 'http://remote.example.net/json?q=hell' - assert resp2.json == data + assert resp2.json == dict(data, err=0) # check unauthorized access resp2 = get_app(pub).get(select2_url + '?q=hell', status=403) @@ -6582,7 +6582,7 @@ def test_item_field_autocomplete_json_source(http_requests, pub, error_email, em resp2 = app.get(select2_url + '?q=hell') assert len(rsps.calls) == 1 assert rsps.calls[-1].request.url == 'http://remote.example.net/json?q=hell' - assert resp2.json == {'data': [], 'err': '1'} + assert resp2.json == {'data': [], 'err': 1} assert emails.count() == 0 data_source.notify_on_errors = True @@ -6641,7 +6641,7 @@ def test_item_field_autocomplete_json_source(http_requests, pub, error_email, em resp2 = app.get(select2_url + '?q=hell') assert len(rsps.calls) == 1 assert rsps.calls[-1].request.url == 'http://remote.example.net/json-numeric-id?q=hell' - assert resp2.json == data + assert resp2.json == dict(data, err=0) # check unauthorized access resp2 = get_app(pub).get(select2_url + '?q=hell', status=403) @@ -6697,7 +6697,7 @@ remote.example.net = 1234 assert rsps.calls[-1].request.url.startswith( 'http://remote.example.net/json?q=hell&orig=example.net&' ) - assert resp2.json == data + assert resp2.json == dict(data, err=0) # simulate select2 mode, with qommon.forms.js adding an extra hidden widget resp.form.fields['f0_display'] = Hidden(form=resp.form, tag='input', name='f0_display', pos=10) @@ -6764,6 +6764,36 @@ remote.example.net = 1234 resp2 = app.get(select2_url + '?q=hell', status=403) assert len(rsps.calls) == 0 + # check with data, id and text attribute + data_source.data_source = {'type': 'json', 'value': 'http://remote.example.net/json'} + data_source.data_attribute = 'x.results' + data_source.id_attribute = 'key' + data_source.text_attribute = 'value' + data_source.store() + + formdef.data_class().wipe() + + app = get_app(pub) + with responses.RequestsMock() as rsps: + resp = app.get('/test/') + pq = resp.pyquery.remove_namespaces() + select2_url = pq('select').attr['data-select2-url'] + + with responses.RequestsMock() as rsps: + data = { + 'x': { + 'results': [ + {'key': '1', 'value': 'hello', 'extra': 'foo'}, + ] + } + } + normalized_data = { + 'data': [{'id': '1', 'text': 'hello', 'extra': 'foo', 'key': '1', 'value': 'hello'}] + } + rsps.get('http://remote.example.net/json', json=data) + resp2 = app.get(select2_url + '?q=hell') + assert resp2.json == dict(normalized_data, err=0) + def test_item_field_autocomplete_jsonp_source(http_requests, pub): create_user(pub) diff --git a/wcs/api.py b/wcs/api.py index bebb1672f..61dfeb28a 100644 --- a/wcs/api.py +++ b/wcs/api.py @@ -35,6 +35,7 @@ from wcs.conditions import Condition, ValidationError from wcs.ctl.hobo_notify import CmdHoboNotify from wcs.data_sources import NamedDataSource from wcs.data_sources import get_object as get_data_source_object +from wcs.data_sources import request_json_items from wcs.formdef import FormDef from wcs.forms.common import FormStatusPage from wcs.qommon import get_cfg @@ -1180,23 +1181,17 @@ class AutocompleteDirectory(Directory): info = token.context if 'url' in info: + named_data_source = None + if info.get('data_source'): + named_data_source = NamedDataSource.get(info['data_source']) url = info['url'] url += urllib.parse.quote(get_request().form.get('q', '')) url = sign_url_auto_orig(url) get_response().set_content_type('application/json') - try: - return misc.urlopen(url).read() - except ConnectionError as e: - if 'data_source' in info: - error_summary = 'Error loading JSON data source (%s)' % str(e) - data_source = NamedDataSource.get(info['data_source']) - get_publisher().record_error( - error_summary, - context='[DATASOURCE]', - notify=data_source.notify_on_errors, - record=data_source.record_on_errors, - ) - return json.dumps({'data': [], 'err': '1'}) + entries = request_json_items(url, named_data_source and named_data_source.extended_data_source) + if entries is not None: + return json.dumps({'err': 0, 'data': entries}) + return json.dumps({'err': 1, 'data': []}) # carddef_ref in info carddef_ref = info['carddef_ref'] -- 2.37.2