From 3a7033463ea98def2e3fb85333c4f00f7c7d6925 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Mon, 7 Oct 2019 08:56:02 +0000 Subject: [PATCH] [FIX] website: allow authenticate in json multidb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit launch a server with --db-filter that match at least 2 dbs name Try to authenticate You will have an error request is unbound when you try to access request.env Now we retrieve the user from self instead of the request. New test to ensure rpc authentication is tested. Related to commit 245ef4b1 closes odoo/odoo#38969 X-original-commit: 4b3400c430bec7539aada0619fd203978daca2d8 Signed-off-by: Jérémy Kersten (jke) --- addons/test_website/controllers/main.py | 8 ++++++ .../static/tests/tours/json_auth.js | 26 +++++++++++++++++++ addons/test_website/tests/__init__.py | 1 + addons/test_website/tests/test_session.py | 9 +++++++ addons/test_website/views/templates.xml | 1 + addons/website/models/website_visitor.py | 25 ++++++++---------- .../models/website_visitor.py | 4 +-- addons/website_sale/controllers/main.py | 9 ++++--- 8 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 addons/test_website/static/tests/tours/json_auth.js create mode 100644 addons/test_website/tests/test_session.py diff --git a/addons/test_website/controllers/main.py b/addons/test_website/controllers/main.py index ec94cbc3aee..1fc9f8e54e6 100644 --- a/addons/test_website/controllers/main.py +++ b/addons/test_website/controllers/main.py @@ -44,6 +44,14 @@ class WebsiteTest(Home): def test_company_context(self): return request.make_response(json.dumps(request.context.get('allowed_company_ids'))) + # Test Session + + @http.route('/test_get_dbname', type='json', auth='public', website=True) + def test_get_dbname(self, **kwargs): + return request.env.cr.dbname + + # Test Error + @http.route('/test_error_view', type='http', auth='public', website=True) def test_error_view(self, **kwargs): return request.render('test_website.test_error_view') diff --git a/addons/test_website/static/tests/tours/json_auth.js b/addons/test_website/static/tests/tours/json_auth.js new file mode 100644 index 00000000000..6c4df8e26de --- /dev/null +++ b/addons/test_website/static/tests/tours/json_auth.js @@ -0,0 +1,26 @@ +odoo.define('test_website.json_auth', function (require) { +'use strict'; + +var tour = require('web_tour.tour'); +var session = require('web.session') + +tour.register('test_json_auth', { + test: true, +}, [{ + trigger: 'body', + run: async function () { + await session.rpc('/test_get_dbname').then( function (result){ + return session.rpc("/web/session/authenticate", { + db: result, + login: 'admin', + password: 'admin' + }); + }); + window.location.href = window.location.origin; + }, +}, { + trigger: 'span:contains(Mitchell Admin)', + run: function () {}, +} +]); +}); diff --git a/addons/test_website/tests/__init__.py b/addons/test_website/tests/__init__.py index 8b8ec3e4e44..4fab1ec9b68 100644 --- a/addons/test_website/tests/__init__.py +++ b/addons/test_website/tests/__init__.py @@ -6,3 +6,4 @@ from . import test_reset_views from . import test_error from . import test_views_during_module_operation from . import test_multi_company +from . import test_session diff --git a/addons/test_website/tests/test_session.py b/addons/test_website/tests/test_session.py new file mode 100644 index 00000000000..22975ebdda4 --- /dev/null +++ b/addons/test_website/tests/test_session.py @@ -0,0 +1,9 @@ +import odoo.tests +from odoo.tools import mute_logger + + +@odoo.tests.common.tagged('post_install', '-at_install') +class TestWebsiteSession(odoo.tests.HttpCase): + + def test_01_run_test(self): + self.start_tour('/', 'test_json_auth') diff --git a/addons/test_website/views/templates.xml b/addons/test_website/views/templates.xml index ee6b500c5ca..23e71565a55 100644 --- a/addons/test_website/views/templates.xml +++ b/addons/test_website/views/templates.xml @@ -10,6 +10,7 @@ + diff --git a/addons/website/models/website_visitor.py b/addons/website/models/website_visitor.py index 21105582346..33f6b34526a 100644 --- a/addons/website/models/website_visitor.py +++ b/addons/website/models/website_visitor.py @@ -159,7 +159,7 @@ class WebsiteVisitor(models.Model): 'context': ctx, } - def _get_visitor_from_request(self): + def _get_visitor_from_request(self, force_create=False): """ Return the visitor as sudo from the request if there is a visitor_uuid cookie. It is possible that the partner has changed or has disconnected. In that case the cookie is still referencing the old visitor and need to be replaced @@ -167,7 +167,8 @@ class WebsiteVisitor(models.Model): # This function can be called in json with mobile app. # In case of mobile app, no uid is set on the jsonRequest env. - if not request or not request.env.uid: + # In case of multi db, _env is None on request, and request.env unbound. + if not request: return None Visitor = self.env['website.visitor'].sudo() visitor = Visitor @@ -175,27 +176,23 @@ class WebsiteVisitor(models.Model): if access_token: visitor = Visitor.with_context(active_test=False).search([('access_token', '=', access_token)]) - if not request.env.user._is_public(): - partner_id = request.env.user.partner_id - if not visitor or visitor.partner_id != partner_id: + if not self.env.user._is_public(): + partner_id = self.env.user.partner_id + if not visitor or visitor.partner_id and visitor.partner_id != partner_id: # Partner and no cookie or wrong cookie visitor = Visitor.with_context(active_test=False).search([('partner_id', '=', partner_id.id)]) elif visitor and visitor.partner_id: # Cookie associated to a Partner visitor = Visitor - return visitor - def _get_visitor_from_request_or_create(self): - """ Return a tuple (visitor, response), see _get_visitor_from_request - If there is no visitor creates it and ensure the consistancy of the cookie. """ - visitor_sudo = self._get_visitor_from_request() - if not visitor_sudo: - visitor_sudo = self._create_visitor() - return visitor_sudo + if force_create and not visitor: + visitor = self._create_visitor() + + return visitor def _handle_webpage_dispatch(self, response, website_page): # get visitor. Done here to avoid having to do it multiple times in case of override. - visitor_sudo = self._get_visitor_from_request_or_create() + visitor_sudo = self._get_visitor_from_request(force_create=True) if request.httprequest.cookies.get('visitor_uuid', '') != visitor_sudo.access_token: expiration_date = datetime.now() + timedelta(days=365) response.set_cookie('visitor_uuid', visitor_sudo.access_token, expires=expiration_date) diff --git a/addons/website_livechat/models/website_visitor.py b/addons/website_livechat/models/website_visitor.py index 84d52f54d47..059a1ca61da 100644 --- a/addons/website_livechat/models/website_visitor.py +++ b/addons/website_livechat/models/website_visitor.py @@ -84,7 +84,7 @@ class WebsiteVisitor(models.Model): This will only happen if the mail channel linked to the chat request already has a message. So that empty livechat channel won't pop up at client side. """ super(WebsiteVisitor, self)._handle_website_page_visit(response, website_page, visitor_sudo) - visitor_id = self.env['website.visitor']._get_visitor_from_request().id if not visitor_sudo else visitor_sudo.id + visitor_id = visitor_sudo.id or self.env['website.visitor']._get_visitor_from_request().id if visitor_id: # get active chat_request linked to visitor chat_request_channel = self.env['mail.channel'].sudo().search([('livechat_visitor_id', '=', visitor_id), ('livechat_active', '=', True)], order='create_date desc', limit=1) @@ -101,5 +101,5 @@ class WebsiteVisitor(models.Model): "uuid": chat_request_channel.uuid, "type": "chat_request" }) - expiration_date = datetime.now() + timedelta(days=100*365) # never expire + expiration_date = datetime.now() + timedelta(days=100 * 365) # never expire response.set_cookie('im_livechat_session', livechat_session, expires=expiration_date.timestamp()) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index c231cdbb4ed..a11124e8207 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -1255,10 +1255,11 @@ class WebsiteSale(http.Controller): @http.route('/shop/products/recently_viewed_update', type='json', auth='public', website=True) def products_recently_viewed_update(self, product_id, **kwargs): res = {} - visitor_sudo = request.env['website.visitor']._get_visitor_from_request_or_create() - if request.httprequest.cookies.get('visitor_uuid', '') != visitor_sudo.access_token: - res['visitor_uuid'] = visitor_sudo.access_token - visitor_sudo._add_viewed_product(product_id) + visitor_sudo = request.env['website.visitor']._get_visitor_from_request(force_create=True) + if visitor_sudo: + if request.httprequest.cookies.get('visitor_uuid', '') != visitor_sudo.access_token: + res['visitor_uuid'] = visitor_sudo.access_token + visitor_sudo._add_viewed_product(product_id) return res @http.route('/shop/products/recently_viewed_delete', type='json', auth='public', website=True)