diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index e587db98996..89ea93ae05f 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -194,7 +194,7 @@ class BaseAutomation(models.Model): """ Filter the records that satisfy the precondition of action ``self``. """ if self.filter_pre_domain and records: domain = [('id', 'in', records.ids)] + safe_eval(self.filter_pre_domain, self._get_eval_context()) - return records.search(domain) + return records.sudo().search(domain).with_env(records.env) else: return records @@ -205,7 +205,7 @@ class BaseAutomation(models.Model): """ Filter the records that satisfy the postcondition of action ``self``. """ if self.filter_domain and records: domain = [('id', 'in', records.ids)] + safe_eval(self.filter_domain, self._get_eval_context()) - return records.search(domain), domain + return records.sudo().search(domain).with_env(records.env), domain else: return records, None diff --git a/addons/test_base_automation/models/test_base_automation.py b/addons/test_base_automation/models/test_base_automation.py index b2109f3185d..557cfa8e60d 100644 --- a/addons/test_base_automation/models/test_base_automation.py +++ b/addons/test_base_automation/models/test_base_automation.py @@ -49,3 +49,19 @@ class LineTest(models.Model): name = fields.Char() lead_id = fields.Many2one('base.automation.lead.test', ondelete='cascade') user_id = fields.Many2one('res.users') + + +class ModelWithAccess(models.Model): + _name = "base.automation.link.test" + _description = "Automated Rule Link Test" + + name = fields.Char() + linked_id = fields.Many2one('base.automation.linked.test', ondelete='cascade') + + +class ModelWithoutAccess(models.Model): + _name = "base.automation.linked.test" + _description = "Automated Rule Linked Test" + + name = fields.Char() + another_field = fields.Char() diff --git a/addons/test_base_automation/security/ir.model.access.csv b/addons/test_base_automation/security/ir.model.access.csv index cc380da05ad..16be23cd17e 100644 --- a/addons/test_base_automation/security/ir.model.access.csv +++ b/addons/test_base_automation/security/ir.model.access.csv @@ -1,3 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_base_automation_lead_test,access_base_automation_lead_test,model_base_automation_lead_test,base.group_system,1,1,1,1 access_base_automation_line_test,access_base_automation_line_test,model_base_automation_line_test,base.group_system,1,1,1,1 +access_base_automation_link_test,access_base_automation_link_test,model_base_automation_link_test,,1,1,1,1 +access_base_automation_linked_test,access_base_automation_linked_test,model_base_automation_linked_test,,1,1,1,1 diff --git a/addons/test_base_automation/tests/test_flow.py b/addons/test_base_automation/tests/test_flow.py index 657add84892..780a037eadd 100644 --- a/addons/test_base_automation/tests/test_flow.py +++ b/addons/test_base_automation/tests/test_flow.py @@ -5,6 +5,7 @@ from unittest.mock import patch from odoo.addons.base.tests.common import TransactionCaseWithUserDemo from odoo.tests import tagged +from odoo.exceptions import AccessError @tagged('post_install', '-at_install') @@ -296,3 +297,60 @@ record['name'] = record.name + 'X'""", self.assertEqual(lead.name, 'XX', "No update should have happened.") lead.partner_id = partner1 self.assertEqual(lead.name, 'XXX', "One update should have happened.") + + def test_30_modelwithoutaccess(self): + """ + Ensure a domain on a M2O without user access doesn't fail. + We create a base automation with a filter on a model the user haven't access to + - create a group + - restrict acl to this group and set only admin in it + - create base.automation with a filter + - create a record in the restricted model in admin + - create a record in the non restricted model in demo + """ + Model = self.env['base.automation.link.test'] + Comodel = self.env['base.automation.linked.test'] + + access = self.env.ref("test_base_automation.access_base_automation_linked_test") + access.group_id = self.env['res.groups'].create({ + 'name': "Access to base.automation.linked.test", + "users": [(6, 0, [self.user_admin.id,])] + }) + + # sanity check: user demo has no access to the comodel of 'linked_id' + with self.assertRaises(AccessError): + Comodel.with_user(self.user_demo).check_access_rights('read') + + # check base automation with filter that performs Comodel.search() + self.env['base.automation'].create({ + 'name': 'test no access', + 'model_id': self.env['ir.model']._get_id("base.automation.link.test"), + 'trigger': 'on_create_or_write', + 'filter_pre_domain': "[('linked_id.another_field', '=', 'something')]", + 'state': 'code', + 'active': True, + 'code': "action = [rec.name for rec in records]" + }) + Comodel.create([ + {'name': 'a first record', 'another_field': 'something'}, + {'name': 'another record', 'another_field': 'something different'}, + ]) + rec1 = Model.create({'name': 'a record'}) + rec1.write({'name': 'a first record'}) + rec2 = Model.with_user(self.user_demo).create({'name': 'another record'}) + rec2.write({'name': 'another value'}) + + # check base automation with filter that performs Comodel.name_search() + self.env['base.automation'].create({ + 'name': 'test no name access', + 'model_id': self.env['ir.model']._get_id("base.automation.link.test"), + 'trigger': 'on_create_or_write', + 'filter_pre_domain': "[('linked_id', '=', 'whatever')]", + 'state': 'code', + 'active': True, + 'code': "action = [rec.name for rec in records]" + }) + rec3 = Model.create({'name': 'a random record'}) + rec3.write({'name': 'a first record'}) + rec4 = Model.with_user(self.user_demo).create({'name': 'again another record'}) + rec4.write({'name': 'another value'})