diff --git a/addons/base_setup/models/ir_http.py b/addons/base_setup/models/ir_http.py index 4622d28f4f8..4e7bb7df171 100644 --- a/addons/base_setup/models/ir_http.py +++ b/addons/base_setup/models/ir_http.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import models -from odoo.http import request class IrHttp(models.AbstractModel): @@ -9,6 +8,6 @@ class IrHttp(models.AbstractModel): def session_info(self): result = super(IrHttp, self).session_info() - if request.env.user._is_internal(): - result['show_effect'] = bool(request.env['ir.config_parameter'].sudo().get_param('base_setup.show_effect')) + if self.env.user._is_internal(): + result['show_effect'] = bool(self.env['ir.config_parameter'].sudo().get_param('base_setup.show_effect')) return result diff --git a/addons/bus/models/ir_http.py b/addons/bus/models/ir_http.py index 8c369326d88..7b6699f85ee 100644 --- a/addons/bus/models/ir_http.py +++ b/addons/bus/models/ir_http.py @@ -9,10 +9,10 @@ class IrHttp(models.AbstractModel): def session_info(self): result = super().session_info() - result['dbuuid'] = request.env['ir.config_parameter'].sudo().get_param('database.uuid') + result['dbuuid'] = self.env['ir.config_parameter'].sudo().get_param('database.uuid') return result def get_frontend_session_info(self): result = super().get_frontend_session_info() - result['dbuuid'] = request.env['ir.config_parameter'].sudo().get_param('database.uuid') + result['dbuuid'] = self.env['ir.config_parameter'].sudo().get_param('database.uuid') return result diff --git a/addons/hr_timesheet/models/ir_http.py b/addons/hr_timesheet/models/ir_http.py index eddb14e03a9..735e60be640 100644 --- a/addons/hr_timesheet/models/ir_http.py +++ b/addons/hr_timesheet/models/ir_http.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, models -from odoo.http import request class Http(models.AbstractModel): @@ -13,8 +12,8 @@ class Http(models.AbstractModel): widget to apply, depending on the current company. """ result = super(Http, self).session_info() - if request.env.user._is_internal(): - company_ids = request.env.user.company_ids + if self.env.user._is_internal(): + company_ids = self.env.user.company_ids for company in company_ids: result["user_companies"]["allowed_companies"][company.id].update({ @@ -30,7 +29,7 @@ class Http(models.AbstractModel): @api.model def get_timesheet_uoms(self): - company_ids = request.env.user.company_ids + company_ids = self.env.user.company_ids uom_ids = company_ids.mapped('timesheet_encode_uom_id') | \ company_ids.mapped('project_time_mode_id') return { diff --git a/addons/mail/models/ir_http.py b/addons/mail/models/ir_http.py index ff89ab3a5fb..fe7c7e1d62c 100644 --- a/addons/mail/models/ir_http.py +++ b/addons/mail/models/ir_http.py @@ -9,7 +9,7 @@ class IrHttp(models.AbstractModel): _inherit = 'ir.http' def session_info(self): - user = request.env.user + user = self.env.user result = super(IrHttp, self).session_info() if self.env.user._is_internal(): result['notification_type'] = user.notification_type @@ -18,7 +18,7 @@ class IrHttp(models.AbstractModel): user_context = {'lang': guest.lang} mods = odoo.conf.server_wide_modules or [] lang = user_context.get("lang") - translation_hash = request.env['ir.http'].sudo().get_web_translations_hash(mods, lang) + translation_hash = self.env['ir.http'].sudo().get_web_translations_hash(mods, lang) result['cache_hashes']['translations'] = translation_hash result.update({ 'name': guest.name, diff --git a/addons/partner_autocomplete/models/ir_http.py b/addons/partner_autocomplete/models/ir_http.py index f927e24bad5..4f7ff87ee53 100644 --- a/addons/partner_autocomplete/models/ir_http.py +++ b/addons/partner_autocomplete/models/ir_http.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import models -from odoo.http import request class Http(models.AbstractModel): @@ -12,5 +11,5 @@ class Http(models.AbstractModel): """ Add information about iap enrich to perform """ session_info = super(Http, self).session_info() if session_info.get('is_admin'): - session_info['iap_company_enrich'] = not request.env.user.company_id.iap_enrich_auto_done + session_info['iap_company_enrich'] = not self.env.user.company_id.iap_enrich_auto_done return session_info diff --git a/addons/web/controllers/session.py b/addons/web/controllers/session.py index 47e4f94cb2f..36eeab9bae5 100644 --- a/addons/web/controllers/session.py +++ b/addons/web/controllers/session.py @@ -40,6 +40,14 @@ class Session(http.Controller): registry = odoo.modules.registry.Registry(db) with registry.cursor() as cr: env = odoo.api.Environment(cr, request.session.uid, request.session.context) + if not request.db and not request.session.is_explicit: + # request._save_session would not update the session_token + # as it lacks an environment, rotating the session myself + http.root.session_store.rotate(request.session, env) + request.future_response.set_cookie( + 'session_id', request.session.sid, + max_age=http.SESSION_LIFETIME, httponly=True + ) return env['ir.http'].session_info() @http.route('/web/session/get_lang_list', type='json', auth="none") diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py index d8f3fa4bf85..02287053691 100644 --- a/addons/web/models/ir_http.py +++ b/addons/web/models/ir_http.py @@ -65,7 +65,7 @@ class Http(models.AbstractModel): } def session_info(self): - user = request.env.user + user = self.env.user session_uid = request.session.uid version_info = odoo.service.common.exp_version() @@ -89,7 +89,7 @@ class Http(models.AbstractModel): "is_system": user._is_system() if session_uid else False, "is_admin": user._is_admin() if session_uid else False, "user_context": user_context, - "db": request.db, + "db": self.env.cr.dbname, "server_version": version_info.get('server_version'), "server_version_info": version_info.get('server_version_info'), "support_url": "https://www.odoo.com/buy", @@ -106,7 +106,7 @@ class Http(models.AbstractModel): "max_file_upload_size": max_file_upload_size, "home_action_id": user.action_id.id, "cache_hashes": { - "translations": request.env['ir.http'].sudo().get_web_translations_hash( + "translations": self.env['ir.http'].sudo().get_web_translations_hash( mods, request.session.context['lang'] ) if session_uid else None, }, @@ -122,7 +122,7 @@ class Http(models.AbstractModel): # but is still included in some other calls (e.g. '/web/session/authenticate') # to avoid access errors and unnecessary information, it is only included for users # with access to the backend ('internal'-type users) - menus = request.env['ir.ui.menu'].load_menus(request.session.debug) + menus = self.env['ir.ui.menu'].load_menus(request.session.debug) ordered_menus = {str(k): v for k, v in menus.items()} menu_json_utf8 = json.dumps(ordered_menus, default=ustr, sort_keys=True).encode() session_info['cache_hashes'].update({ @@ -174,6 +174,6 @@ class Http(models.AbstractModel): return session_info def get_currencies(self): - Currency = request.env['res.currency'] + Currency = self.env['res.currency'] currencies = Currency.search([]).read(['symbol', 'position', 'decimal_places']) return {c['id']: {'symbol': c['symbol'], 'position': c['position'], 'digits': [69,c['decimal_places']]} for c in currencies} diff --git a/addons/web_tour/models/ir_http.py b/addons/web_tour/models/ir_http.py index bb44df13982..1d37ea1f834 100644 --- a/addons/web_tour/models/ir_http.py +++ b/addons/web_tour/models/ir_http.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import models -from odoo.http import request class Http(models.AbstractModel): @@ -12,6 +11,6 @@ class Http(models.AbstractModel): result = super().session_info() if result['is_admin']: demo_modules_count = self.env['ir.module.module'].sudo().search_count([('demo', '=', True)]) - result['web_tours'] = request.env['web_tour.tour'].get_consumed_tours() + result['web_tours'] = self.env['web_tour.tour'].get_consumed_tours() result['tour_disable'] = demo_modules_count > 0 return result diff --git a/odoo/addons/test_http/tests/test_session.py b/odoo/addons/test_http/tests/test_session.py index 2737ca33dbd..c4163ae9a28 100644 --- a/odoo/addons/test_http/tests/test_session.py +++ b/odoo/addons/test_http/tests/test_session.py @@ -1,9 +1,11 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. +import json from urllib.parse import urlparse from unittest.mock import patch import odoo +from odoo.tests.common import get_db_name from odoo.tools import mute_logger from .test_common import TestHttpBase @@ -91,3 +93,29 @@ class TestHttpSession(TestHttpBase): self.assertFalse(session['db']) self.assertEqual(res.status_code, 303) self.assertEqual(urlparse(res.headers['Location']).path, '/web/database/selector') + + def test_session4_web_authenticate_multidb(self): + self.db_list = [get_db_name(), 'another_database'] + + payload = json.dumps({ + 'jsonrpc': '2.0', + 'id': None, + 'method': 'call', + 'params': { + 'db': get_db_name(), + 'login': 'admin', + 'password': 'admin', + } + }) + + res = self.multidb_url_open( + '/web/session/authenticate', data=payload, headers={ + 'Content-Type': 'application/json', + } + ) + res.raise_for_status() + self.assertEqual(res.status_code, 200) + + res = self.multidb_url_open('/test_http/greeting-user') + res.raise_for_status() + self.assertEqual(res.status_code, 200, "Should not be redirected to /web/login") diff --git a/odoo/http.py b/odoo/http.py index 21424437713..e4922afed2a 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -857,6 +857,7 @@ class FilesystemSessionStore(sessions.FilesystemSessionStore): session.sid = self.generate_key() if session.uid and env: session.session_token = security.compute_session_token(session, env) + session.should_rotate = False self.save(session) def vacuum(self):