From 59584283c52f06a478e61e93b1d0f69a750a1768 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 17 May 2017 11:13:58 +0200 Subject: [FIX] web: properly escape field values when necessary This rev. removes some html injections issues: - in char and text field widgets - in phone field widget in mobile - in list views (when no widget is instantiated) --- .../web/static/tests/fields/basic_fields_tests.js | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 7b9fbd061eb..41530f85c4f 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -710,6 +710,33 @@ QUnit.module('basic_fields', { _t.database.multi_lang = multiLang; }); + QUnit.test('char field does not allow html injections', function (assert) { + assert.expect(1); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + form.$('input').val('').trigger('input'); + form.$buttons.find('.o_form_button_save').click(); + assert.strictEqual(form.$('.o_field_widget').text(), '', + 'the value should have been properly escaped'); + + form.destroy(); + }); QUnit.module('UrlWidget'); @@ -2166,6 +2193,42 @@ QUnit.module('basic_fields', { list.destroy(); }); + QUnit.test('phone field does not allow html injections', function (assert) { + assert.expect(1); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + viewOptions: { + mode: 'edit', + }, + config: { + device: { + size_class: 0, + SIZES: { XS: 0, SM: 1, MD: 2, LG: 3 }, + } + }, + }); + + var val = ''; + form.$('input').val(val).trigger('input'); + + // save + form.$buttons.find('.o_form_button_save').click(); + assert.strictEqual(form.$('.o_field_widget').text().split('\u00AD').join(''), val, + "value should have been correctly escaped"); + + form.destroy(); + }); QUnit.module('PriorityWidget'); -- cgit v1.2.3 From ba6a3a91ae78297c7f8ddcf7630ecef46048c15e Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Wed, 17 May 2017 09:22:40 +0200 Subject: [FIX] web: MonetaryField: read currency_field in options In the xml definition of views, a 'currency_field' can be specified in the node options: It indicates which field the monetary widget has to use to determine the currency to display. Before this rev., the widget didn't look for the 'currency_field' in the options, but directly in the node attrs, so this simply didn't work. This was for example the case on the crm.lead kanban and form views. --- .../web/static/tests/fields/basic_fields_tests.js | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 41530f85c4f..ca951506e28 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1769,6 +1769,37 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('monetary field with monetary field given in options', function (assert) { + assert.expect(1); + + this.data.partner.fields.qux.type = "monetary"; + this.data.partner.fields.company_currency_id = { + string: "Company Currency", type: "many2one", relation: "currency", + }; + this.data.partner.records[4].company_currency_id = 2; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '
', + res_id: 5, + session: { + currencies: _.indexBy(this.data.currency.records, 'id'), + }, + }); + + assert.strictEqual(form.$('.o_field_monetary').html(), "9.10 €", + "field monetary should be formatted with correct currency"); + + form.destroy(); + }); + QUnit.test('should keep the focus when being edited in x2many lists', function (assert) { assert.expect(6); -- cgit v1.2.3 From c929a81e8f015f9234f68749a29fe6a9c21577b6 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 19 May 2017 10:13:24 +0200 Subject: [FIX] web: DebounceField: do nothing after widget destruction DebounceFields debounce the function that notify field changes to their environment (using _.debounce). It may happen that this function is called once the field widget is destroyed (e.g. type something in a char field and quickly click on Save, the function is called directly by _commitChanges, but the debounced call is still pending). It may be a problem if the subsequent code does something like this.getSession().some_key, as if the widget is destroyed, it has no parent that can provide it the session, and thus it crashes. Also rename attribute _debouncedStarted into _isDirty as it makes much more sense. --- .../web/static/tests/fields/basic_fields_tests.js | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'addons/web/static/tests/fields/basic_fields_tests.js') diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index ca951506e28..07d13fbe93a 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1,6 +1,7 @@ odoo.define('web.basic_fields_tests', function (require) { "use strict"; +var basicFields = require('web.basic_fields'); var concurrency = require('web.concurrency'); var core = require('web.core'); var FormView = require('web.FormView'); @@ -10,6 +11,7 @@ var session = require('web.session'); var testUtils = require('web.test_utils'); var createView = testUtils.createView; +var DebouncedField = basicFields.DebouncedField; var _t = core._t; QUnit.module('fields', {}, function () { @@ -120,6 +122,66 @@ QUnit.module('basic_fields', { } }, function () { + QUnit.module('DebouncedField'); + + QUnit.test('debounced fields do not trigger call _setValue once destroyed', function (assert) { + var done = assert.async(); + assert.expect(4); + + var def = $.Deferred(); + var _doAction = DebouncedField.prototype._doAction; + DebouncedField.prototype._doAction = function () { + _doAction.apply(this, arguments); + def.resolve(); + }; + var _setValue = DebouncedField.prototype._setValue; + DebouncedField.prototype._setValue = function () { + assert.step('_setValue'); + _setValue.apply(this, arguments); + }; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + fieldDebounce: 3, + viewOptions: { + mode: 'edit', + }, + }); + + // change the value + form.$('input').val('new value').trigger('input'); + assert.verifySteps([], "_setValue shouldn't have been called yet"); + + // save + form.$buttons.find('.o_form_button_save').click(); + assert.verifySteps(['_setValue'], "_setValue should have been called once"); + + // destroy the form view + def = $.Deferred(); + form.destroy(); + + // wait for the debounced callback to be called + def.then(function () { + assert.verifySteps(['_setValue'], + "_setValue should not have been called after widget destruction"); + + DebouncedField.prototype._doAction = _doAction; + DebouncedField.prototype._setValue = _setValue; + done(); + }); + + }); + QUnit.module('FieldBoolean'); QUnit.test('boolean field in form view', function (assert) { -- cgit v1.2.3