diff options
| author | Julien Castiaux <juc@odoo.com> | 2019-08-12 15:14:40 +0000 |
|---|---|---|
| committer | Julien Castiaux <juc@odoo.com> | 2019-08-19 09:04:09 +0000 |
| commit | 855447fc77fdbe2972be043b7ba9131567d21b9f (patch) | |
| tree | 3862516f0fbd7ef69e4f1c1a6a4779240ec7d972 /odoo | |
| parent | 0458337bc362b4ecc020fd95a5896dc9d394322b (diff) | |
[FIX] ir_rule: invalid user context propagation
Create two models, `object` and `category`. The object have a Many2One
to the category. Override the `search` on the category so it returns a
subset of the records if a context key is present. Create an IR Rule on
object with the following pseudo-domain: `categ_id in category.search([])`.
Search on object with the context key present. Even if the context
should only be applied to category, it is applied to object too thus
there are some object missing.
When evaluating the domain of IR Rules, the current user is propagated
with the current environment context. API calls triggered by the domain
are called with the given context, possibly populating the cache with
different records than it would normally does without the context (i.e.
at `addons/point_of_sale/models/account_journal.py#L19-L23`). Following
requests do use that invalid cache thus return invalid results.
Forcing an empty context on the user used during the evaluation of the
context ensures the IR Rules are working as they should and is
future-proof (cf `load_company` v13 context key)
opw-2041667
closes #35123
closes #35125
closes odoo/odoo#35667
Signed-off-by: Julien Castiaux <Julien00859@users.noreply.github.com>
Co-authored-by: Hugo Adan <hugo@vauxoo.com>
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/base/ir/ir_rule.py | 4 | ||||
| -rw-r--r-- | odoo/addons/test_access_rights/ir.model.access.csv | 1 | ||||
| -rw-r--r-- | odoo/addons/test_access_rights/models.py | 12 | ||||
| -rw-r--r-- | odoo/addons/test_access_rights/tests/test_ir_rules.py | 38 |
4 files changed, 50 insertions, 5 deletions
diff --git a/odoo/addons/base/ir/ir_rule.py b/odoo/addons/base/ir/ir_rule.py index a319b74a1a2..c1174915451 100644 --- a/odoo/addons/base/ir/ir_rule.py +++ b/odoo/addons/base/ir/ir_rule.py @@ -42,7 +42,9 @@ class IrRule(models.Model): def _eval_context(self): """Returns a dictionary to use as evaluation context for ir.rule domains.""" - return {'user': self.env.user, 'time': time} + # use an empty context for 'user' to make the domain evaluation + # independent from the context + return {'user': self.env.user.with_context({}), 'time': time} @api.depends('groups') def _compute_global(self): diff --git a/odoo/addons/test_access_rights/ir.model.access.csv b/odoo/addons/test_access_rights/ir.model.access.csv index eda40f960d9..4bbc5b37c59 100644 --- a/odoo/addons/test_access_rights/ir.model.access.csv +++ b/odoo/addons/test_access_rights/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_test_access_right_some_obj,access_test_access_right_some_obj,model_test_access_right_some_obj,,1,1,1,1 access_test_access_right_container,access_test_access_right_container,model_test_access_right_container,,1,1,1,1 +access_test_access_right_obj_categ,access_test_access_right_obj_categ,model_test_access_right_obj_categ,,1,1,1,1 diff --git a/odoo/addons/test_access_rights/models.py b/odoo/addons/test_access_rights/models.py index ee4b7ffb216..04d73128335 100644 --- a/odoo/addons/test_access_rights/models.py +++ b/odoo/addons/test_access_rights/models.py @@ -7,9 +7,21 @@ class SomeObj(models.Model): _name = 'test_access_right.some_obj' val = fields.Integer() + categ_id = fields.Many2one('test_access_right.obj_categ') class Container(models.Model): _name = 'test_access_right.container' some_ids = fields.Many2many('test_access_right.some_obj', 'test_access_right_rel', 'container_id', 'some_id') + + +class ObjCateg(models.Model): + _name = 'test_access_right.obj_categ' + + name = fields.Char(required=True) + + def search(self, args, **kwargs): + if self.env.context.get('only_media'): + args += [('name', '=', 'Media')] + return super(ObjCateg, self).search(args, **kwargs) diff --git a/odoo/addons/test_access_rights/tests/test_ir_rules.py b/odoo/addons/test_access_rights/tests/test_ir_rules.py index c1ce6cc6b80..dc74e3ee59d 100644 --- a/odoo/addons/test_access_rights/tests/test_ir_rules.py +++ b/odoo/addons/test_access_rights/tests/test_ir_rules.py @@ -8,10 +8,11 @@ class TestRules(TransactionCase): def setUp(self): super(TestRules, self).setUp() - self.id1 = self.env['test_access_right.some_obj']\ - .create({'val': 1}).id - self.id2 = self.env['test_access_right.some_obj']\ - .create({'val': -1}).id + ObjCateg = self.env['test_access_right.obj_categ'] + SomeObj = self.env['test_access_right.some_obj'] + self.categ1 = ObjCateg.create({'name': 'Food'}).id + self.id1 = SomeObj.create({'val': 1, 'categ_id': self.categ1}).id + self.id2 = SomeObj.create({'val': -1, 'categ_id': self.categ1}).id # create a global rule forbidding access to records with a negative # (or zero) val self.env['ir.rule'].create({ @@ -19,6 +20,13 @@ class TestRules(TransactionCase): 'model_id': self.browse_ref('test_access_rights.model_test_access_right_some_obj').id, 'domain_force': "[('val', '>', 0)]" }) + # create a global rule that forbid access to records without + # categories, the search is part of the test + self.env['ir.rule'].create({ + 'name': 'See all categories', + 'model_id': self.browse_ref('test_access_rights.model_test_access_right_some_obj').id, + 'domain_force': "[('categ_id', 'in', user.env['test_access_right.obj_categ'].search([]).ids)]" + }) def test_basic_access(self): env = self.env(user=self.browse_ref('base.public_user')) @@ -56,3 +64,25 @@ class TestRules(TransactionCase): container_user.write({'some_ids': [(5,)]}) self.assertItemsEqual(container_user.some_ids.ids, []) self.assertItemsEqual(container_admin.some_ids.ids, [self.id2]) + + def test_no_context_in_ir_rules(self): + """ The context should not impact the ir rules. """ + env = self.env(user=self.browse_ref('base.public_user')) + ObjCateg = self.env['test_access_right.obj_categ'] + SomeObj = self.env['test_access_right.some_obj'] + + # validate the effect of context on category search, there are + # no existing media category + self.assertTrue(ObjCateg.search([])) + self.assertFalse(ObjCateg.with_context(only_media=True).search([])) + + # record1 is food and is accessible with an empy context + ObjCateg.clear_caches() + records = SomeObj.search([('id', '=', self.id1)]) + self.assertTrue(records) + + # it should also be accessible as the context is not used when + # searching for SomeObjs + ObjCateg.clear_caches() + records = SomeObj.with_context(only_media=True).search([('id', '=', self.id1)]) + self.assertTrue(records) |
