Files
odoo_source/odoo/addons/test_http/tests/test_session.py
T
Julien Castiaux ca5ca24bc6 [FIX] core: check browser lang is installed
A visitor could visit a web page having a lang in its context that is
not installed in the databased he is connected to. The problem is that
visitors are not logged-in thus it is not possible to determine their
lang via their `res.users` preferences. The lang used instead is the
lang set in the `Accept-Language` header of the incoming request, that
header is set by various browsers in accordance to the user system
preferences or browser settings.

The browser lang (`Request.best`) is only parsed according to the
`babel` database, it is a lang syntactically speaking but not necessary
a lang that is installed in the database.

At the moment the browser lang is set in the context (inside of
`Request._get_dbname_and_session`), it is not possible to verify it is
installed in the database as no connection to any database as been
established yet. Instead the lang is validated inside of
`ir.http._pre_dispatch` which is the method responsible to prepare/fix
various stuff on the request/session/context.

In regard to 93b684d3c7, we prefer to fallback on English, hence the
modification in `get_lang`.

closes odoo/odoo#116683

Reference-to: 93b684d3c7 ([FIX] base: lang should fallback on english instead of arab)
X-original-commit: 743e97667e44cdaab6db334d807cf3d409cea621
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
2023-03-28 10:30:02 +02:00

134 lines
5.1 KiB
Python

# 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
GEOIP_ODOO_FARM_2 = {
'city': 'Ramillies',
'country_code': 'BE',
'country_name': 'Belgium',
'latitude': 50.6314,
'longitude': 4.8573,
'region': 'WAL',
'time_zone': 'Europe/Brussels'
}
class TestHttpSession(TestHttpBase):
@mute_logger('odoo.http') # greeting_none called ignoring args {'debug'}
def test_session0_debug_mode(self):
session = self.authenticate(None, None)
self.assertEqual(session.debug, '')
self.db_url_open('/test_http/greeting').raise_for_status()
self.assertEqual(session.debug, '')
self.db_url_open('/test_http/greeting?debug=1').raise_for_status()
self.assertEqual(session.debug, '1')
self.db_url_open('/test_http/greeting').raise_for_status()
self.assertEqual(session.debug, '1')
self.db_url_open('/test_http/greeting?debug=').raise_for_status()
self.assertEqual(session.debug, '')
def test_session1_default_session(self):
# The default session should not be saved on the filestore.
with patch.object(odoo.http.root.session_store, 'save') as mock_save:
res = self.db_url_open('/test_http/geoip')
res.raise_for_status()
try:
mock_save.assert_not_called()
except AssertionError as exc:
msg = f'save() was called with args: {mock_save.call_args}'
raise AssertionError(msg) from exc
def test_session3_logout_15_0_geoip(self):
session = self.authenticate(None, None)
session['db'] = 'idontexist'
session['geoip'] = {} # Until saas-15.2 geoip was directly stored in the session
odoo.http.root.session_store.save(session)
with self.assertLogs('odoo.http', level='WARNING') as (_, warnings):
res = self.multidb_url_open('/test_http/ensure_db', dblist=['db1', 'db2'])
self.assertEqual(warnings, [
"WARNING:odoo.http:Logged into database 'idontexist', but dbfilter rejects it; logging session out.",
])
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")
def test_session5_default_lang(self):
self.env['res.lang']._activate_lang('en_US') # default lang
lang_fr = self.env['res.lang']._activate_lang('fr_FR')
with self.subTest(case='no preferred lang'):
res = self.url_open('/test_http/echo-http-context-lang')
self.assertEqual(res.text, 'en_US')
with self.subTest(case='fr preferred and fr_FR enabled'):
res = self.url_open('/test_http/echo-http-context-lang', headers={
'Accept-Language': 'fr',
})
self.assertEqual(res.text, 'fr_FR')
with self.subTest(case='fr preferred but fr_FR disabled'):
lang_fr.active = False
res = self.url_open('/test_http/echo-http-context-lang', headers={
'Accept-Language': 'fr',
})
self.assertEqual(res.text, 'en_US')
def test_session6_saved_lang(self):
session = self.authenticate('demo', 'demo')
self.env['res.lang']._activate_lang('en_US') # default lang
lang_fr = self.env['res.lang']._activate_lang('fr_FR')
with self.subTest(case='no saved lang'):
res = self.url_open('/test_http/echo-http-context-lang')
self.assertEqual(res.text, 'en_US')
with self.subTest(case='fr saved and fr_FR enabled'):
session.context['lang'] = 'fr_FR'
odoo.http.root.session_store.save(session)
res = self.url_open('/test_http/echo-http-context-lang')
self.assertEqual(res.text, 'fr_FR')
with self.subTest(case='fr saved but fr_FR disabled'):
session['lang'] = 'fr_FR'
odoo.http.root.session_store.save(session)
lang_fr.active = False
res = self.url_open('/test_http/echo-http-context-lang')
self.assertEqual(res.text, 'en_US')