[FIX] im_livechat: matching rule in cache
The problem was that the matching rule was evaluated before sending the html page, and the script was inserted in the page according to the matching rule (it wasn't inserted if the rule was 'hide_button'). However, the matching rule wasn't re-evaluated if the page was already in the cache. The page content thus might depend on a matching rule computed for someone else in that case. Rather than inserting the script according to the matching rule, we insert it only if there is an operator available. We then ask for the matching rule in the livechat widget, by RPC, and we reject its willStart deferred if the rule says so. We also re-check for operator availability in the same RPC.
This commit is contained in:
@@ -29,12 +29,36 @@ class LivechatController(http.Controller):
|
|||||||
def loader(self, channel_id, **kwargs):
|
def loader(self, channel_id, **kwargs):
|
||||||
username = kwargs.get("username", _("Visitor"))
|
username = kwargs.get("username", _("Visitor"))
|
||||||
channel = request.env['im_livechat.channel'].sudo().browse(channel_id)
|
channel = request.env['im_livechat.channel'].sudo().browse(channel_id)
|
||||||
info = request.env['im_livechat.channel'].with_context(from_external_page=True).match_rules(request, channel.id, username=username)
|
info = request.env['im_livechat.channel'].get_livechat_info(channel.id, username=username)
|
||||||
return request.render('im_livechat.loader', {'info': info, 'web_session_required': True}) if info else False
|
return request.render('im_livechat.loader', {'info': info, 'web_session_required': True}) if info['available'] else False
|
||||||
|
|
||||||
@http.route('/im_livechat/available', type='json', auth="public")
|
@http.route('/im_livechat/init', type='json', auth="public")
|
||||||
def available(self, channel_id):
|
def livechat_init(self, channel_id):
|
||||||
return len(request.env['im_livechat.channel'].browse(channel_id).get_available_users())
|
LivechatChannel = request.env['im_livechat.channel']
|
||||||
|
available = len(LivechatChannel.browse(channel_id).get_available_users())
|
||||||
|
rule = {}
|
||||||
|
if available:
|
||||||
|
# find the country from the request
|
||||||
|
country_id = False
|
||||||
|
country_code = request.session.geoip and request.session.geoip.get('country_code') or False
|
||||||
|
if country_code:
|
||||||
|
country_ids = self.env['res.country'].sudo().search([('code', '=', country_code)])
|
||||||
|
if country_ids:
|
||||||
|
country_id = country_ids[0].id
|
||||||
|
# extract url
|
||||||
|
url = request.httprequest.headers.get('Referer')
|
||||||
|
# find the first matching rule for the given country and url
|
||||||
|
matching_rule = request.env['im_livechat.channel.rule'].sudo().match_rule(channel_id, url, country_id)
|
||||||
|
if matching_rule:
|
||||||
|
rule = {
|
||||||
|
'action': matching_rule.action,
|
||||||
|
'auto_popup_timer': matching_rule.auto_popup_timer,
|
||||||
|
'regex_url': matching_rule.regex_url,
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'available_for_me': available and (not rule or rule['action'] != 'hide_button'),
|
||||||
|
'rule': rule,
|
||||||
|
}
|
||||||
|
|
||||||
@http.route('/im_livechat/get_session', type="json", auth='public')
|
@http.route('/im_livechat/get_session', type="json", auth='public')
|
||||||
def get_session(self, channel_id, anonymous_name, **kwargs):
|
def get_session(self, channel_id, anonymous_name, **kwargs):
|
||||||
|
|||||||
@@ -193,36 +193,13 @@ class ImLivechatChannel(models.Model):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def match_rules(self, request, channel_id, username='Visitor'):
|
def get_livechat_info(self, channel_id, username='Visitor'):
|
||||||
info = {
|
info = {}
|
||||||
'server_url': self.env['ir.config_parameter'].get_param('web.base.url'),
|
info['available'] = self.browse(channel_id).get_available_users(),
|
||||||
'options': self.sudo().get_channel_infos(channel_id),
|
if info['available']:
|
||||||
}
|
info['server_url'] = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||||
info['options']["default_username"] = username
|
info['options'] = self.sudo().get_channel_infos(channel_id)
|
||||||
# find the country from the request
|
info['options']["default_username"] = username
|
||||||
country_id = False
|
|
||||||
country_code = request.session.geoip and request.session.geoip.get('country_code') or False
|
|
||||||
if country_code:
|
|
||||||
country_ids = self.env['res.country'].sudo().search([('code', '=', country_code)])
|
|
||||||
if country_ids:
|
|
||||||
country_id = country_ids[0].id
|
|
||||||
# extract url
|
|
||||||
if self.env.context.get('from_external_page', False):
|
|
||||||
url = request.httprequest.headers.get('Referer')
|
|
||||||
else:
|
|
||||||
url = request.httprequest.base_url
|
|
||||||
# find the match rule for the given country and url
|
|
||||||
rule = self.env['im_livechat.channel.rule'].sudo().match_rule(channel_id, url, country_id)
|
|
||||||
if rule:
|
|
||||||
if rule.action == 'hide_button':
|
|
||||||
# don't return the initialization script, since its blocked (in the country)
|
|
||||||
return False
|
|
||||||
rule_data = {
|
|
||||||
'action': rule.action,
|
|
||||||
'auto_popup_timer': rule.auto_popup_timer,
|
|
||||||
'regex_url': rule.regex_url,
|
|
||||||
}
|
|
||||||
info['rule'] = rule and rule_data or False
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ var LivechatButton = Widget.extend({
|
|||||||
"click": "open_chat"
|
"click": "open_chat"
|
||||||
},
|
},
|
||||||
|
|
||||||
init: function (parent, server_url, options, rule) {
|
init: function (parent, server_url, options) {
|
||||||
this._super(parent);
|
this._super(parent);
|
||||||
this.options = _.defaults(options || {}, {
|
this.options = _.defaults(options || {}, {
|
||||||
placeholder: _t('Ask something ...'),
|
placeholder: _t('Ask something ...'),
|
||||||
@@ -28,7 +28,6 @@ var LivechatButton = Widget.extend({
|
|||||||
button_text: _t("Chat with one of our collaborators"),
|
button_text: _t("Chat with one of our collaborators"),
|
||||||
default_message: _t("How may I help you?"),
|
default_message: _t("How may I help you?"),
|
||||||
});
|
});
|
||||||
this.rule = rule || {};
|
|
||||||
this.channel = null;
|
this.channel = null;
|
||||||
this.chat_window = null;
|
this.chat_window = null;
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
@@ -39,44 +38,41 @@ var LivechatButton = Widget.extend({
|
|||||||
var cookie = utils.get_cookie('im_livechat_session');
|
var cookie = utils.get_cookie('im_livechat_session');
|
||||||
var ready;
|
var ready;
|
||||||
if (!cookie) {
|
if (!cookie) {
|
||||||
ready = session.rpc("/im_livechat/available", {channel_id: this.options.channel_id});
|
ready = session.rpc("/im_livechat/init", {channel_id: this.options.channel_id}).then(function (result) {
|
||||||
|
if (!result.available_for_me) {
|
||||||
|
return $.Deferred().reject();
|
||||||
|
}
|
||||||
|
self.rule = result.rule;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
var channel = JSON.parse(cookie);
|
var channel = JSON.parse(cookie);
|
||||||
ready = $.when(true, session.rpc("/im_livechat/history", {channel_id: channel.id, limit: 100}));
|
ready = session.rpc("/im_livechat/history", {channel_id: channel.id, limit: 100}).then(function (history) {
|
||||||
|
self.history = history;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return ready.then(function (available, history) {
|
return ready.then(this.load_qweb_template.bind(this));
|
||||||
self.available = available;
|
|
||||||
self.history = history;
|
|
||||||
if (available) {
|
|
||||||
return self.load_qweb_template();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function () {
|
start: function () {
|
||||||
if (!this.available) {
|
this.$el.text(this.options.button_text);
|
||||||
this.do_hide();
|
if (this.history) {
|
||||||
} else {
|
_.each(this.history.reverse(), this.add_message.bind(this));
|
||||||
this.$el.text(this.options.button_text);
|
this.open_chat();
|
||||||
if (this.history) {
|
} else if (this.rule.action === 'auto_popup') {
|
||||||
_.each(this.history.reverse(), this.add_message.bind(this));
|
var auto_popup_cookie = utils.get_cookie('im_livechat_auto_popup');
|
||||||
this.open_chat();
|
if (!auto_popup_cookie || JSON.parse(auto_popup_cookie)) {
|
||||||
} else if (this.rule.action === 'auto_popup') {
|
this.auto_popup_timeout = setTimeout(this.open_chat.bind(this), this.rule.auto_popup_timer*1000);
|
||||||
var auto_popup_cookie = utils.get_cookie('im_livechat_auto_popup');
|
}
|
||||||
if (!auto_popup_cookie || JSON.parse(auto_popup_cookie)) {
|
}
|
||||||
this.auto_popup_timeout = setTimeout(this.open_chat.bind(this), this.rule.auto_popup_timer*1000);
|
bus.on('notification', this, function (notification) {
|
||||||
|
if (this.channel && (notification[0] === this.channel.uuid)) {
|
||||||
|
this.add_message(notification[1]);
|
||||||
|
this.render_messages();
|
||||||
|
if (this.chat_window.folded) {
|
||||||
|
this.chat_window.update_unread(this.chat_window.unread_msgs+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus.on('notification', this, function (notification) {
|
});
|
||||||
if (this.channel && (notification[0] === this.channel.uuid)) {
|
|
||||||
this.add_message(notification[1]);
|
|
||||||
this.render_messages();
|
|
||||||
if (this.chat_window.folded) {
|
|
||||||
this.chat_window.update_unread(this.chat_window.unread_msgs+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return this._super();
|
return this._super();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -140,10 +140,10 @@
|
|||||||
<template id="loader" name="Livechat : Javascript appending the livechat button">
|
<template id="loader" name="Livechat : Javascript appending the livechat button">
|
||||||
|
|
||||||
<t t-if="not info">
|
<t t-if="not info">
|
||||||
<t t-set="info" t-value="request.env['im_livechat.channel'].match_rules(request, channel)"/>
|
<t t-set="info" t-value="request.env['im_livechat.channel'].get_livechat_info(channel)"/>
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
<t t-if="info" t-translation="off">
|
<t t-if="info['available']" t-translation="off">
|
||||||
document.addEventListener("DOMContentLoaded", function(event) {
|
document.addEventListener("DOMContentLoaded", function(event) {
|
||||||
<t t-if="web_session_required">
|
<t t-if="web_session_required">
|
||||||
odoo.define('web.session', function (require) {
|
odoo.define('web.session', function (require) {
|
||||||
@@ -158,8 +158,7 @@
|
|||||||
var button = new im_livechat.LivechatButton(
|
var button = new im_livechat.LivechatButton(
|
||||||
$('body'),
|
$('body'),
|
||||||
"<t t-esc="info['server_url']"/>",
|
"<t t-esc="info['server_url']"/>",
|
||||||
<t t-raw="json.dumps(info.get('options', {}))"/>,
|
<t t-raw="json.dumps(info.get('options', {}))"/>
|
||||||
<t t-raw="json.dumps(info.get('rule', False))"/>
|
|
||||||
);
|
);
|
||||||
button.appendTo($('body'));
|
button.appendTo($('body'));
|
||||||
window.livechat_button = button;
|
window.livechat_button = button;
|
||||||
|
|||||||
Reference in New Issue
Block a user