launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #19610
[Merge] lp:~cjwatson/launchpad/testfix-safer-ajax-strings into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/testfix-safer-ajax-strings into lp:launchpad.
Commit message:
Be more careful about JSON-encoding array elements, and fix up tests.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/testfix-safer-ajax-strings/+merge/274237
Be more careful about JSON-encoding array elements: strings that are array elements have the same ambiguity problem as top-level strings, so we need to take care to encode them in the same way. Fix up tests for this and for other failures introduced by safer-ajax-strings.
The pillar sharing view needs to change to take account of this: it previously turned each key/value pair into an unquoted key,value string which lazr.restful handled, but when the keys and values are quoted separately this will no longer work. Just passing the permissions parameter as a JSON-encoded dictionary instead is simpler and safer.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/testfix-safer-ajax-strings into lp:launchpad.
=== modified file 'lib/lp/app/javascript/client.js'
--- lib/lp/app/javascript/client.js 2015-10-12 16:06:06 +0000
+++ lib/lp/app/javascript/client.js 2015-10-13 11:18:19 +0000
@@ -174,20 +174,27 @@
return config[key];
};
- module.append_qs = function(qs, key, value) {
+ module._encode_param = function(key, value, ws_param) {
+ var v = value;
+ if (Y.Lang.isObject(v) || (ws_param && Y.Lang.isString(v))) {
+ v = Y.JSON.stringify(v);
+ }
+ return encodeURIComponent(key) + "=" + encodeURIComponent(v);
+ };
+
+ module.append_qs = function(qs, key, value, ws_param) {
/* Append a key-value pair to a query string. */
+ if (ws_param === undefined) {
+ ws_param = false;
+ }
var elems = (qs && qs.length > 0) ? [qs] : [];
- var enc = encodeURIComponent;
if (Y.Lang.isArray(value)) {
var index;
for (index = 0; index < value.length; index++) {
- elems.push(enc(key) + "=" + enc(value[index]));
+ elems.push(module._encode_param(key, value[index], ws_param));
}
- } else if (Y.Lang.isObject(value) ||
- (key !== "ws.op" && Y.Lang.isString(value))) {
- elems.push(enc(key) + "=" + enc(Y.JSON.stringify(value)));
} else {
- elems.push(enc(key) + "=" + enc(value));
+ elems.push(module._encode_param(key, value, ws_param));
}
return elems.join("&");
};
@@ -719,7 +726,8 @@
var name;
for (name in parameters) {
if (parameters.hasOwnProperty(name)) {
- data = module.append_qs(data, name, parameters[name]);
+ data = module.append_qs(
+ data, name, parameters[name], true);
}
}
config.data = data;
@@ -736,7 +744,8 @@
data = module.append_qs(data, "ws.op", operation_name);
for (name in parameters) {
if (parameters.hasOwnProperty(name)) {
- data = module.append_qs(data, name, parameters[name]);
+ data = module.append_qs(
+ data, name, parameters[name], true);
}
}
=== modified file 'lib/lp/app/javascript/tests/test_lp_client.js'
--- lib/lp/app/javascript/tests/test_lp_client.js 2015-10-12 16:06:06 +0000
+++ lib/lp/app/javascript/tests/test_lp_client.js 2015-10-13 11:18:19 +0000
@@ -73,7 +73,7 @@
var qs = "";
qs = Y.lp.client.append_qs(qs, "Pöllä", "Perelló");
Assert.areEqual(
- "P%C3%83%C2%B6ll%C3%83%C2%A4=%22Perell%C3%83%C2%B3%22", qs,
+ "P%C3%83%C2%B6ll%C3%83%C2%A4=Perell%C3%83%C2%B3", qs,
'This tests is known to fail in Chrome.');
},
@@ -97,6 +97,26 @@
"foo=%7B%22text%22%3A%22A%5Cn%26%C3%83%C2%A7%22%7D", qs);
},
+ test_append_qs_ws_string: function() {
+ var qs = "";
+ qs = Y.lp.client.append_qs(qs, "Pöllä", "Perelló", true);
+ Assert.areEqual(
+ "P%C3%83%C2%B6ll%C3%83%C2%A4=%22Perell%C3%83%C2%B3%22", qs,
+ 'This tests is known to fail in Chrome.');
+ },
+
+ test_append_qs_ws_with_array: function() {
+ // append_qs(ws_param=true) appends multiple arguments to the
+ // query string when a parameter value is an array. Strings are
+ // quoted.
+ var qs = "";
+ qs = Y.lp.client.append_qs(qs, "foo", ["bar", 1], true);
+ Assert.areEqual("foo=%22bar%22&foo=1", qs);
+ // All values in the array are encoded correctly too.
+ qs = Y.lp.client.append_qs(qs, "a&b", ["a+b"], true);
+ Assert.areEqual("foo=%22bar%22&foo=1&a%26b=%22a%2Bb%22", qs);
+ },
+
test_field_uri: function() {
var get_field_uri = Y.lp.client.get_field_uri;
Assert.areEqual(
=== modified file 'lib/lp/bugs/javascript/bug_picker.js'
--- lib/lp/bugs/javascript/bug_picker.js 2012-09-10 20:52:27 +0000
+++ lib/lp/bugs/javascript/bug_picker.js 2015-10-13 11:18:19 +0000
@@ -134,10 +134,10 @@
var qs_data
= Y.lp.client.append_qs("", "ws.accept", "application.json");
qs_data = Y.lp.client.append_qs(qs_data, "ws.op", "getBugData");
- qs_data = Y.lp.client.append_qs(qs_data, "bug_id", bug_id);
+ qs_data = Y.lp.client.append_qs(qs_data, "bug_id", bug_id, true);
if (Y.Lang.isValue(LP.cache.bug)) {
qs_data = Y.lp.client.append_qs(
- qs_data, "related_bug", LP.cache.bug.self_link);
+ qs_data, "related_bug", LP.cache.bug.self_link, true);
}
var that = this;
var config = {
=== modified file 'lib/lp/bugs/javascript/tests/test_bug_picker.js'
--- lib/lp/bugs/javascript/tests/test_bug_picker.js 2013-03-20 03:41:40 +0000
+++ lib/lp/bugs/javascript/tests/test_bug_picker.js 2015-10-13 11:18:19 +0000
@@ -20,13 +20,13 @@
this.mockio.last_request.url);
var expected_data =
'ws.accept=application.json&ws.op=getBugData&' +
- 'bug_id=' + bug_id;
+ 'bug_id=%22' + bug_id + '%22';
if (Y.Lang.isValue(LP.cache.bug)) {
var bug_uri = encodeURIComponent('api/devel/bugs/1');
- expected_data += '&related_bug=' + bug_uri;
+ expected_data += '&related_bug=%22' + bug_uri + '%22';
}
Y.Assert.areEqual(
- this.mockio.last_request.config.data, expected_data);
+ expected_data, this.mockio.last_request.config.data);
} else {
Y.Assert.areEqual(
'/api/devel/bugs/1', this.mockio.last_request.url);
=== modified file 'lib/lp/code/javascript/tests/test_branchmergeproposal.nominate.js'
--- lib/lp/code/javascript/tests/test_branchmergeproposal.nominate.js 2012-10-26 10:00:20 +0000
+++ lib/lp/code/javascript/tests/test_branchmergeproposal.nominate.js 2015-10-13 11:18:19 +0000
@@ -115,8 +115,9 @@
reviewer_uri = encodeURIComponent(
Y.lp.client.get_absolute_uri(reviewer_uri));
Y.Assert.areEqual(
- 'ws.op=getBranchVisibilityInfo&person=' +
- reviewer_uri + '&branch_names=b2&branch_names=b1',
+ 'ws.op=getBranchVisibilityInfo&person=%22' +
+ reviewer_uri + '%22&' +
+ 'branch_names=%22b2%22&branch_names=%22b1%22',
this.mockio.last_request.config.data);
Y.Assert.isTrue(confirm_reviewer_called);
},
=== modified file 'lib/lp/code/javascript/tests/test_bugspeclinks.js'
--- lib/lp/code/javascript/tests/test_bugspeclinks.js 2013-03-20 03:41:40 +0000
+++ lib/lp/code/javascript/tests/test_bugspeclinks.js 2015-10-13 11:18:19 +0000
@@ -140,7 +140,7 @@
var bug_uri = encodeURIComponent(
'file:///api/devel/bugs/' + bug_id);
var expected_data =
- 'ws.op=linkBug&bug=' + bug_uri;
+ 'ws.op=linkBug&bug=%22' + bug_uri + '%22';
Y.Assert.areEqual(
expected_data, this.mockio.last_request.config.data);
},
=== modified file 'lib/lp/registry/javascript/sharing/pillarsharingview.js'
--- lib/lp/registry/javascript/sharing/pillarsharingview.js 2012-12-18 16:41:18 +0000
+++ lib/lp/registry/javascript/sharing/pillarsharingview.js 2015-10-13 11:18:19 +0000
@@ -545,11 +545,10 @@
this.get('information_types_by_value');
var sharing_permissions_by_value =
this.get('sharing_permissions_by_value');
- var permission_params = [];
+ var permission_params = {};
Y.each(permissions, function(permission, info_type) {
- permission_params.push(
- [information_types_by_value[info_type],
- sharing_permissions_by_value[permission]]);
+ permission_params[information_types_by_value[info_type]] =
+ sharing_permissions_by_value[permission];
});
var self = this;
var y_config = {
=== modified file 'lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js'
--- lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2013-03-20 03:41:40 +0000
+++ lib/lp/registry/javascript/sharing/tests/test_pillarsharingview.js 2015-10-13 11:18:19 +0000
@@ -264,8 +264,8 @@
'/api/devel/+services/sharing',
this.mockio.last_request.url);
Y.Assert.areEqual(
- 'ws.op=deletePillarGrantee&pillar=~pillar' +
- '&grantee=~fred',
+ 'ws.op=deletePillarGrantee&pillar=%22~pillar%22' +
+ '&grantee=%22~fred%22',
this.mockio.last_request.config.data);
this.mockio.last_request.successJSON(['Invisible']);
Y.Assert.isTrue(remove_grantee_success_called);
@@ -359,21 +359,24 @@
this.mockio.last_request.url);
var person_uri = Y.lp.client.normalize_uri('~/joe');
person_uri = Y.lp.client.get_absolute_uri(person_uri);
- var expected_url;
- expected_url = Y.lp.client.append_qs(
- expected_url, 'ws.op', 'sharePillarInformation');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'pillar', '~pillar');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'grantee', person_uri);
- expected_url = Y.lp.client.append_qs(
- expected_url, 'permissions', 'Policy 1,Nothing');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'permissions', 'Policy 2,All');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'permissions', 'Policy 3,Nothing');
- Y.Assert.areEqual(
- expected_url, this.mockio.last_request.config.data);
+ var expected_qs = {
+ 'ws.op': 'sharePillarInformation',
+ 'pillar': '"~pillar"',
+ 'grantee': '"' + person_uri + '"'
+ };
+ var expected_permissions = {
+ 'Policy 1': 'Nothing',
+ 'Policy 2': 'All',
+ 'Policy 3': 'Nothing'
+ };
+ var observed_qs = Y.QueryString.parse(
+ this.mockio.last_request.config.data);
+ var observed_permissions = Y.JSON.parse(
+ observed_qs['permissions']);
+ delete observed_qs['permissions'];
+ Y.ObjectAssert.areEqual(expected_qs, observed_qs);
+ Y.ObjectAssert.areEqual(
+ expected_permissions, observed_permissions);
this.mockio.last_request.successJSON({
grantee_entry: {
'name': 'joe',
@@ -407,17 +410,22 @@
this.mockio.last_request.url);
var person_uri = Y.lp.client.normalize_uri('~fred');
person_uri = Y.lp.client.get_absolute_uri(person_uri);
- var expected_url;
- expected_url = Y.lp.client.append_qs(
- expected_url, 'ws.op', 'sharePillarInformation');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'pillar', '~pillar');
- expected_url = Y.lp.client.append_qs(
- expected_url, 'grantee', person_uri);
- expected_url = Y.lp.client.append_qs(
- expected_url, 'permissions', 'Policy 1,Some');
- Y.Assert.areEqual(
- expected_url, this.mockio.last_request.config.data);
+ var expected_qs = {
+ 'ws.op': 'sharePillarInformation',
+ 'pillar': '"~pillar"',
+ 'grantee': '"' + person_uri + '"'
+ };
+ var expected_permissions = {
+ 'Policy 1': 'Some'
+ };
+ var observed_qs = Y.QueryString.parse(
+ this.mockio.last_request.config.data);
+ var observed_permissions = Y.JSON.parse(
+ observed_qs['permissions']);
+ delete observed_qs['permissions'];
+ Y.ObjectAssert.areEqual(expected_qs, observed_qs);
+ Y.ObjectAssert.areEqual(
+ expected_permissions, observed_permissions);
this.mockio.last_request.successJSON({
grantee_entry: {
'name': 'fred',
@@ -578,8 +586,9 @@
'/api/devel/+services/sharing',
this.mockio.last_request.url);
Y.Assert.areEqual(
- 'ws.op=updatePillarSharingPolicies&pillar=~pillar&' +
- artifact_type + '_sharing_policy=' + title + '%20Policy%201',
+ 'ws.op=updatePillarSharingPolicies&pillar=%22~pillar%22&' +
+ artifact_type + '_sharing_policy=%22' + title +
+ '%20Policy%201%22',
this.mockio.last_request.config.data);
},
@@ -694,6 +703,7 @@
})));
}, '0.1', {'requires': ['test', 'test-console', 'event', 'node-event-simulate',
+ 'querystring-parse', 'json-parse',
'lp.testing.mockio', 'lp.registry.sharing.granteepicker',
'lp.registry.sharing.granteetable', 'lp.app.errors',
'lp.registry.sharing.pillarsharingview']});
=== modified file 'lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js'
--- lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js 2015-04-29 10:33:33 +0000
+++ lib/lp/registry/javascript/sharing/tests/test_sharingdetailsview.js 2015-10-13 11:18:19 +0000
@@ -255,11 +255,11 @@
expected_qs = Y.lp.client.append_qs(
expected_qs, 'ws.op', 'revokeAccessGrants');
expected_qs = Y.lp.client.append_qs(
- expected_qs, 'pillar', '/pillar');
- expected_qs = Y.lp.client.append_qs(
- expected_qs, 'grantee', '~fred');
- expected_qs = Y.lp.client.append_qs(
- expected_qs, 'bugs', 'api/devel/bugs/2');
+ expected_qs, 'pillar', '/pillar', true);
+ expected_qs = Y.lp.client.append_qs(
+ expected_qs, 'grantee', '~fred', true);
+ expected_qs = Y.lp.client.append_qs(
+ expected_qs, 'bugs', 'api/devel/bugs/2', true);
Y.Assert.areEqual(expected_qs, mockio.last_request.config.data);
mockio.last_request.successJSON({});
Y.Assert.isTrue(remove_grant_success_called);
@@ -294,11 +294,12 @@
expected_qs = Y.lp.client.append_qs(
expected_qs, 'ws.op', 'revokeAccessGrants');
expected_qs = Y.lp.client.append_qs(
- expected_qs, 'pillar', '/pillar');
- expected_qs = Y.lp.client.append_qs(
- expected_qs, 'grantee', '~fred');
- expected_qs = Y.lp.client.append_qs(
- expected_qs, 'branches', 'api/devel/~someone/+junk/somebranch');
+ expected_qs, 'pillar', '/pillar', true);
+ expected_qs = Y.lp.client.append_qs(
+ expected_qs, 'grantee', '~fred', true);
+ expected_qs = Y.lp.client.append_qs(
+ expected_qs, 'branches', 'api/devel/~someone/+junk/somebranch',
+ true);
Y.Assert.areEqual(expected_qs, mockio.last_request.config.data);
mockio.last_request.successJSON({});
Y.Assert.isTrue(remove_grant_success_called);
@@ -334,12 +335,12 @@
expected_qs = Y.lp.client.append_qs(
expected_qs, 'ws.op', 'revokeAccessGrants');
expected_qs = Y.lp.client.append_qs(
- expected_qs, 'pillar', '/pillar');
+ expected_qs, 'pillar', '/pillar', true);
expected_qs = Y.lp.client.append_qs(
- expected_qs, 'grantee', '~fred');
+ expected_qs, 'grantee', '~fred', true);
expected_qs = Y.lp.client.append_qs(
expected_qs, 'gitrepositories',
- 'api/devel/~someone/+git/somerepo');
+ 'api/devel/~someone/+git/somerepo', true);
Y.Assert.areEqual(expected_qs, mockio.last_request.config.data);
mockio.last_request.successJSON({});
Y.Assert.isTrue(remove_grant_success_called);
Follow ups