Skip to content

Commit 115fc39

Browse files
committed
[FIX] website, *: unescape URL parameters when used in autocomplete
*: web_tour, website_blog Since [1] when the search box autocomplete was introduced, the URL parameters are implicitly included into the RPC that fetches the autocompletion results. Those parameters were not correctly unescaped before being sent to the RPC call. Because of this, a timestamp such as "2023-01-01 23:00:00" was sent as "2023-01-01+23%3A00%3A00" to the server. If that string reached the SQL layer, the "+" was interpreted as defining a timezone. This commit unescapes the URL parameters before using them in the RPC. Note that javascript's `decodeURIComponent` does not handle the '+' encoding of spaces inside URL parameters. For testing purpose, the following updates were needed to make it possible to select the `<option>` within the Archive month `<select>`: - because the `option`s are in a tree, the tool was adapted to take all `option`s into consideration instead of only the direct children of the `select`. - because the `option` text is dynamically created from the date of the test execution, the tool was adapted to allow targeting an `option` based on its index by specifying the tour step's `run` as `'text index N'`, `N` being the index of the `option`. Steps to reproduce: - Enable the sidebar of the `/blog` page. - Select a month in the sidebar. - Type something in the search box. => Did show an error popup while obtaining the autocompletion records. [1]: odoo@7559626 task-3213916 closes odoo#114615 X-original-commit: ac8d582 Signed-off-by: Romain Derie (rde) <rde@odoo.com> Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
1 parent 317977e commit 115fc39

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

addons/web_tour/static/src/js/running_tour_action_helper.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,22 @@ var RunningTourActionHelper = core.Class.extend({
102102
bubbles: true,
103103
}));
104104
} else if (values.$element.is("select")) {
105-
var $options = values.$element.children("option");
105+
var $options = values.$element.find("option");
106106
$options.prop("selected", false).removeProp("selected");
107107
var $selectedOption = $options.filter(function () { return $(this).val() === text; });
108108
if ($selectedOption.length === 0) {
109109
$selectedOption = $options.filter(function () { return $(this).text().trim() === text; });
110110
}
111+
const regex = /option\s+([0-9]+)/;
112+
if ($selectedOption.length === 0 && regex.test(text)) {
113+
// Extract position as 1-based, as the nth selectors.
114+
const position = parseInt(regex.exec(text)[1]);
115+
$selectedOption = $options.eq(position - 1); // eq is 0-based.
116+
}
111117
$selectedOption.prop("selected", true);
112118
this._click(values);
119+
// For situations where an `oninput` is defined.
120+
values.$element.trigger("input");
113121
} else {
114122
values.$element.focusIn();
115123
values.$element.trigger($.Event( "keydown", {key: '_', keyCode: 95}));

addons/website/static/src/snippets/s_searchbar/000.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,16 @@ publicWidget.registry.searchBar = publicWidget.Widget.extend({
6464
for (const keyValue of urlParams.split('&')) {
6565
const [key, value] = keyValue.split('=');
6666
if (value && key !== 'search') {
67-
this.options[key] = value;
67+
// Decode URI parameters: revert + to space then decodeURIComponent.
68+
this.options[decodeURIComponent(key.replace(/\+/g, '%20'))] = decodeURIComponent(value.replace(/\+/g, '%20'));
6869
}
6970
}
7071
}
7172
const pathParts = urlPath.split('/');
7273
for (const index in pathParts) {
73-
const value = pathParts[index];
74+
const value = decodeURIComponent(pathParts[index]);
7475
if (index > 0 && /-[0-9]+$/.test(value)) { // is sluggish
75-
this.options[pathParts[index - 1]] = value;
76+
this.options[decodeURIComponent(pathParts[index - 1])] = value;
7677
}
7778
}
7879

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/** @odoo-module **/
2+
3+
import tour from 'web_tour.tour';
4+
5+
/**
6+
* Makes sure that blog search can be used with the date filtering.
7+
*/
8+
tour.register('blog_autocomplete_with_date', {
9+
test: true,
10+
url: '/blog',
11+
}, [{
12+
content: "Select first month",
13+
trigger: 'select[name=archive]',
14+
run: 'text option 2',
15+
}, {
16+
content: "Enter search term",
17+
trigger: '.o_searchbar_form input',
18+
extra_trigger: '#o_wblog_posts_loop span:has(i.fa-calendar-o):has(a[href="/blog"])',
19+
run: 'text a',
20+
}, {
21+
content: "Wait for suggestions then click on search icon",
22+
extra_trigger: '.o_searchbar_form .o_dropdown_menu .o_search_result_item',
23+
trigger: '.o_searchbar_form button:has(i.oi-search)',
24+
}, {
25+
content: "Ensure both filters are applied",
26+
trigger: '#o_wblog_posts_loop:has(span:has(i.fa-calendar-o):has(a[href="/blog?search=a"])):has(span:has(i.fa-search):has(a[href^="/blog?date_begin"]))',
27+
run: () => {}, // This is a check.
28+
}]);

addons/website_blog/tests/test_ui.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ def test_admin(self):
2323

2424
def test_blog_post_tags(self):
2525
self.start_tour(self.env['website'].get_client_action_url('/blog'), 'blog_tags', login='admin')
26+
27+
def test_autocomplete_with_date(self):
28+
self.env.ref('website_blog.opt_blog_sidebar_show').active = True
29+
self.env.ref('website_blog.opt_sidebar_blog_index_follow_us').active = False
30+
self.start_tour("/blog", 'blog_autocomplete_with_date')

0 commit comments

Comments
 (0)