From ca23abf580e9903832400033730b1f99ab2de780 Mon Sep 17 00:00:00 2001 From: Xavier Morel <xmo@odoo.com> Date: Mon, 11 Sep 2023 12:36:00 +0000 Subject: [PATCH] [FIX] base: correctly check debug mode when formatting access errors Intent of checking `group_no_one` was always to query the advanced info / debug mode, however when the semantics of group_no_one got changed in 31518bc09b1ae2be37c3555799e2c122f0a4dbcd this site was missed, and now always displays "advanced" errors for internal users. Which was not the intent. Also since we're printing `display_name` and some of them annoyingly hook onto context variables to show extended information, reset the context to the user's default in order to avoid such extended-formatting `display_name`. Also fix "debug mode" in `TestIRRuleFeedback`, which has been broken since time immemorial (likely as long as the group_no_one semantics changed). closes odoo/odoo#135162 X-original-commit: f9d55c698ac911e21b5899183f169cafdaacfe8a Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com> --- odoo/addons/base/models/ir_rule.py | 3 +- .../test_access_rights/tests/test_feedback.py | 35 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/odoo/addons/base/models/ir_rule.py b/odoo/addons/base/models/ir_rule.py index bdb798cba455..6c4965314b1a 100644 --- a/odoo/addons/base/models/ir_rule.py +++ b/odoo/addons/base/models/ir_rule.py @@ -216,6 +216,7 @@ class IrRule(models.Model): def _make_access_error(self, operation, records): _logger.info('Access Denied by record rules for operation: %s on record ids: %r, uid: %s, model: %s', operation, records.ids[:6], self._uid, records._name) + self = self.with_context(self.env.user.context_get()) model = records._name description = self.env['ir.model']._get(model).name or model @@ -229,7 +230,7 @@ class IrRule(models.Model): operation_error = msg_heads[operation] resolution_info = _("Contact your administrator to request access if necessary.") - if not self.env.user.has_group('base.group_no_one') or not self.env.user.has_group('base.group_user'): + if not self.user_has_groups('base.group_no_one') or not self.env.user.has_group('base.group_user'): msg = """{operation_error} {resolution_info}""".format( diff --git a/odoo/addons/test_access_rights/tests/test_feedback.py b/odoo/addons/test_access_rights/tests/test_feedback.py index e2c7cff6c68a..dec52bc809a0 100644 --- a/odoo/addons/test_access_rights/tests/test_feedback.py +++ b/odoo/addons/test_access_rights/tests/test_feedback.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- +from unittest.mock import Mock + +import odoo from odoo import SUPERUSER_ID, Command from odoo.exceptions import AccessError -from odoo.tests import common, TransactionCase +from odoo.tests import TransactionCase class Feedback(TransactionCase): @@ -158,11 +161,19 @@ class TestIRRuleFeedback(Feedback): """ def setUp(self): super().setUp() + self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self.model = self.env['ir.model'].search([('model', '=', 'test_access_right.some_obj')]) self.record = self.env['test_access_right.some_obj'].create({ 'val': 0, }).with_user(self.user) + + def debug_mode(self): + odoo.http._request_stack.push(Mock(db=self.env.cr.dbname, env=self.env, debug=True)) + self.addCleanup(odoo.http._request_stack.pop) + self.env['base'].invalidate_cache() + + def _make_rule(self, name, domain, global_=False, attr='write'): res = self.env['ir.rule'].create({ 'name': name, @@ -187,9 +198,7 @@ class TestIRRuleFeedback(Feedback): Contact your administrator to request access if necessary.""") - # debug mode - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -215,10 +224,9 @@ Contact your administrator to request access if necessary.""" % (self.record.dis p.with_user(self.user).write({'val': 1}) def test_locals(self): - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', '[("val", "=", 42)]') self._make_rule('rule 1', '[("val", "=", 78)]') + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -236,10 +244,9 @@ Contact your administrator to request access if necessary.""" % (self.record.dis ) def test_globals_all(self): - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', '[("val", "=", 42)]', global_=True) self._make_rule('rule 1', '[("val", "=", 78)]', global_=True) + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -260,10 +267,9 @@ Contact your administrator to request access if necessary.""" % (self.record.dis """ Global rules are AND-eded together, so when an access fails it might be just one of the rules, and we want an exact listing """ - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', '[("val", "=", 42)]', global_=True) self._make_rule('rule 1', '[(1, "=", 1)]', global_=True) + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -280,12 +286,11 @@ Contact your administrator to request access if necessary.""" % (self.record.dis ) def test_combination(self): - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', '[("val", "=", 42)]', global_=True) self._make_rule('rule 1', '[(1, "=", 1)]', global_=True) self._make_rule('rule 2', '[(0, "=", 1)]') self._make_rule('rule 3', '[("val", "=", 55)]') + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -307,10 +312,9 @@ Contact your administrator to request access if necessary.""" % (self.record.dis """ If one of the failing rules mentions company_id, add a note that this might be a multi-company issue. """ - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', "[('company_id', '=', user.company_id.id)]") self._make_rule('rule 1', '[("val", "=", 0)]', global_=True) + self.debug_mode() with self.assertRaises(AccessError) as ctx: self.record.write({'val': 1}) self.assertEqual( @@ -332,10 +336,9 @@ Contact your administrator to request access if necessary.""" % (self.record.dis """ because of prefetching, read() goes through a different codepath to apply rules """ - self.env.ref('base.group_no_one').write({'users': [Command.link(self.user.id)]}) - self.env.ref('base.group_user').write({'users': [Command.link(self.user.id)]}) self._make_rule('rule 0', "[('company_id', '=', user.company_id.id)]", attr='read') self._make_rule('rule 1', '[("val", "=", 1)]', global_=True, attr='read') + self.debug_mode() with self.assertRaises(AccessError) as ctx: _ = self.record.val self.assertEqual( -- GitLab