data sources: check identifiers as strings (#47974)

This commit is contained in:
Frédéric Péters 2020-10-22 18:11:10 +02:00 committed by Thomas NOEL
parent 16a147d537
commit fd9afcc57c
2 changed files with 53 additions and 1 deletions

View File

@ -6105,7 +6105,59 @@ def test_item_field_autocomplete_json_source(http_requests, pub):
assert formdef.data_class().select()[0].data['0_display'] == 'hello'
assert formdef.data_class().select()[0].data['0_structured'] == data['data'][0]
# same thing with numeric identifiers
formdef.data_class().wipe()
data_source.data_source = {'type': 'json', 'value': 'http://remote.example.net/json-numeric-id'}
data_source.store()
app = get_app(pub)
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {'data': [{'id': 1, 'text': 'hello', 'extra': 'foo'},
{'id': 2, 'text': 'world', 'extra': 'bar'}]}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp = app.get('/test/')
assert urlopen.call_count == 0
pq = resp.pyquery.remove_namespaces()
select2_url = pq('select').attr['data-select2-url']
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {'data': [{'id': 1, 'text': 'hello', 'extra': 'foo'}]}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp2 = app.get(select2_url + '?q=hell')
assert urlopen.call_count == 1
assert urlopen.call_args[0][0] == 'http://remote.example.net/json-numeric-id?q=hell'
assert resp2.json == data
# check unauthorized access
resp2 = get_app(pub).get(select2_url + '?q=hell', status=403)
# 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)
resp.form['f0'].force_value('1')
resp.form.fields['f0_display'].force_value('hello')
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {'data': [{'id': 1, 'text': 'hello', 'extra': 'foo'}]}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp = resp.form.submit('submit') # -> validation page
assert urlopen.call_count == 1
assert urlopen.call_args[0][0] == 'http://remote.example.net/json-numeric-id?id=1'
assert resp.form['f0'].value == '1'
assert resp.form['f0_label'].value == 'hello'
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {'data': [{'id': 1, 'text': 'hello', 'extra': 'foo'}]}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp = resp.form.submit('submit') # -> submit
assert urlopen.call_count == 1
assert urlopen.call_args[0][0] == 'http://remote.example.net/json-numeric-id?id=1'
assert formdef.data_class().select()[0].data['0'] == '1'
assert formdef.data_class().select()[0].data['0_display'] == 'hello'
assert formdef.data_class().select()[0].data['0_structured'] == data['data'][0]
# same thing with signed URLs
data_source.data_source = {'type': 'json', 'value': 'http://remote.example.net/json'}
data_source.store()
formdef.data_class().wipe()
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').write('''\
[wscall-secrets]

View File

@ -439,7 +439,7 @@ class NamedDataSource(XmlStorableObject):
def find_item(items, name, value):
from wcs.logged_errors import LoggedError
for item in items:
if item.get(name) == value:
if str(item.get(name)) == str(value):
return item
# not found
LoggedError.record(_('Could not find element by id "%s"') % value)