summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Castiaux <juc@odoo.com>2019-08-12 15:14:40 +0000
committerJulien Castiaux <juc@odoo.com>2019-08-19 09:04:09 +0000
commit855447fc77fdbe2972be043b7ba9131567d21b9f (patch)
tree3862516f0fbd7ef69e4f1c1a6a4779240ec7d972
parent0458337bc362b4ecc020fd95a5896dc9d394322b (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>
-rw-r--r--odoo/addons/base/ir/ir_rule.py4
-rw-r--r--odoo/addons/test_access_rights/ir.model.access.csv1
-rw-r--r--odoo/addons/test_access_rights/models.py12
-rw-r--r--odoo/addons/test_access_rights/tests/test_ir_rules.py38
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)