From fc168b17a8e35e7b04496d7b91602b80b23c347a Mon Sep 17 00:00:00 2001 From: Benoit Socias Date: Thu, 1 Sep 2022 08:51:19 +0000 Subject: [PATCH] [FIX] http_routing, website: render error page if 403 fallback fails Since [1] the 403 pages displayed when a website page is restricted to a different group of users is the default one instead of the website one. After this commit 403 fallback errors are rendered by the default error rendering. Steps to reproduce: - Go to a page. (e.g. "Contact Us") - Select "Page Properties" in the "Pages" menu. - Go to the "Publish" tab. - Define visibility as "Some Users". - Select a user group. (e.g. "Administration / Access Rights") - Access to the same page in an incognito window. => The displayed 403 error page was the generic one instead of the website one (with the navigation header...) [1]: https://github.com/odoo/odoo/commit/eb7eecec976570ae3301c17a04adc9c110d5b14a task-2963843 closes odoo/odoo#99671 X-original-commit: fc0a0c2ccea83b3a9a5df0e300eac1fe7eb7a2a2 Signed-off-by: Julien Castiaux Signed-off-by: Benoit Socias (bso) --- addons/http_routing/models/ir_http.py | 12 ++++++++---- addons/website/tests/test_page.py | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py index d75608f1205..6b76757fadf 100644 --- a/addons/http_routing/models/ir_http.py +++ b/addons/http_routing/models/ir_http.py @@ -630,10 +630,14 @@ class IrHttp(models.AbstractModel): request.cr.rollback() if code == 403: - response = cls._serve_fallback() - if response: - cls._post_dispatch(response) - return response + try: + response = cls._serve_fallback() + if response: + cls._post_dispatch(response) + return response + except werkzeug.exceptions.Forbidden: + # Rendering does raise a Forbidden if target is not visible. + pass # Use default error page handling. elif code == 500: values = cls._get_values_500_error(request.env, values, exception) try: diff --git a/addons/website/tests/test_page.py b/addons/website/tests/test_page.py index c51cd90cb27..672fdfeb6c7 100644 --- a/addons/website/tests/test_page.py +++ b/addons/website/tests/test_page.py @@ -8,6 +8,7 @@ from odoo.tests import common, HttpCase, tagged from odoo.tests.common import HOST from odoo.tools import config, mute_logger from odoo.addons.website.tools import MockRequest +from odoo.fields import Command @tagged('-at_install', 'post_install') @@ -204,6 +205,7 @@ class TestPage(common.TransactionCase): self.assertTrue(website_id not in pages.mapped('website_id').ids, "The website from which we deleted the generic page should not have a specific one.") self.assertTrue(website_id not in View.search([('name', 'in', ('Base', 'Extension'))]).mapped('website_id').ids, "Same for views") + @tagged('-at_install', 'post_install') class WithContext(HttpCase): def setUp(self): @@ -336,3 +338,19 @@ class WithContext(HttpCase): self.assertEqual(canonical_url, f'{self.base_url()}/fr/page_1') self.assertEqual(alternate_en_url, f'{self.base_url()}/page_1') self.assertEqual(alternate_fr_url, f'{self.base_url()}/fr/page_1') + + def test_07_not_authorized(self): + # Create page that requires specific user role. + specific_page = self.page.copy({'website_id': self.env['website'].get_current_website().id}) + specific_page.write({ + 'arch': self.page.arch.replace('I am a generic page', 'I am a specific page not available for visitors'), + 'is_published': True, + 'visibility': 'restricted_group', + 'groups_id': [Command.link(self.ref('website.group_website_designer'))], + }) + # Access page as anonymous visitor. + self.authenticate(None, None) + r = self.url_open('/page_1') + # Check that is is rendered as a website page. + self.assertEqual(403, r.status_code, "Must fail with 403") + self.assertTrue('id="wrap"' in r.text, "Must be rendered as a website page")