[FIX] models, test_access_rights: restore normal ACL check

Because of 4b1cb41cf7, we might try to read
the field 'active' on a record on which we can't read fields besides the name.
This thus triggers an access error where there should not have been.

In particular, this is the case for portal users: most often the records they
can access point to records that they can't read
(e.g. the partner of the internal user assigned to the ticket).
As a result, clicking on any link creates an ACL, and thus redirects to the
home page.

It turns out that filtered_domain was primarily used on already loaded records,
typically for the write, so it was assumed that the records could be read
in the first place.
However in the use-case of the portal, there is an explicit check on the read
rights with the portal user, explaining the discrepancy.

Since in the general case filtered_domain should be able to read all fields
to evaluate the domain, we put it in sudo.

fix co-authored with @rco

closes odoo/odoo#38540

X-original-commit: cff5cc8cc78a32eb204368e84ec4980324046405
Signed-off-by: Nans Lefebvre (len) <len@odoo.com>
This commit is contained in:
Nans Lefebvre
2019-10-11 18:27:30 +00:00
committed by fw-bot
parent 212294fe1c
commit 60534c65ae
7 changed files with 68 additions and 1 deletions
@@ -5,6 +5,7 @@
'category': 'Tests',
'data': [
'ir.model.access.csv',
'security.xml',
'data.xml',
],
}
@@ -3,3 +3,5 @@ access_test_access_right_some_obj,access_test_access_right_some_obj,model_test_a
access_test_access_right_container,access_test_access_right_container,model_test_access_right_container,,1,1,1,1
access_test_access_right_parent,access_test_access_right_parent,model_test_access_right_parent,,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
access_test_ticket_portal,access_test_ticket_portal,model_test_access_right_ticket,base.group_portal,1,0,0,0
access_test_ticket_user,access_test_ticket_user,model_test_access_right_ticket,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_test_access_right_container access_test_access_right_container model_test_access_right_container 1 1 1 1
4 access_test_access_right_parent access_test_access_right_parent model_test_access_right_parent 1 1 1 1
5 access_test_access_right_obj_categ access_test_access_right_obj_categ model_test_access_right_obj_categ 1 1 1 1
6 access_test_ticket_portal access_test_ticket_portal model_test_access_right_ticket base.group_portal 1 0 0 0
7 access_test_ticket_user access_test_ticket_user model_test_access_right_ticket base.group_user 1 1 1 1
+11
View File
@@ -40,3 +40,14 @@ class ObjCateg(models.Model):
if self.env.context.get('only_media'):
args += [('name', '=', 'Media')]
return super(ObjCateg, self).search(args, **kwargs)
class FakeTicket(models.Model):
"""We want to simulate a record that would typically be accessed by a portal user,
with a relational field to records that could not be accessed by a portal user.
"""
_name = 'test_access_right.ticket'
_description = 'Fake ticket For Test Access Right'
name = fields.Char()
message_partner_ids = fields.Many2many(comodel_name='res.partner')
@@ -0,0 +1,12 @@
<odoo>
<record id="test_access_right_fake_ticket" model="ir.rule">
<field name="name">Fake Ticket: portal or following</field>
<field name="model_id" ref="model_test_access_right_ticket"/>
<field name="domain_force">[
'|',
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
('message_partner_ids', 'in', [user.partner_id.id])
]</field>
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
</record>
</odoo>
@@ -1,2 +1,3 @@
from . import test_ir_rules
from . import test_feedback
from . import test_check_access
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo.tests
class TestAccess(odoo.tests.HttpCase):
def setUp(self):
super(TestAccess, self).setUp()
self.portal_user = self.env['res.users'].create({
'login': 'P',
'name': 'P',
'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])],
})
# a partner that can't be read by the portal user, would typically be a user's
self.internal_user_partner = self.env['res.partner'].create({'name': 'I'})
self.document = self.env['test_access_right.ticket'].create({
'name': 'Need help here',
'message_partner_ids': [(6, 0, [self.portal_user.partner_id.id,
self.internal_user_partner.id])],
})
def test_check_access(self):
"""Typically, a document consulted by a portal user P
will point to other records that P cannot read.
For example, if P wants to consult a ticket of his,
the ticket will have a reviewer or assigned user that is internal,
and which partner cannot be read by P.
This should not block P from accessing the ticket.
"""
document = self.document.with_user(self.portal_user)
# at this point, some fields might already be loaded in cache.
# if so, it means we would bypass the ACL when trying to read the field
# while this is bad, this is not the object of this test
self.internal_user_partner.invalidate_cache(fnames=['active'])
# from portal's _document_check_access:
document.check_access_rights('read')
document.check_access_rule('read')
# no raise, because we are supposed to be able to read our ticket
+1 -1
View File
@@ -3204,7 +3204,7 @@ Record ids: %(records)s
def _filter_access_rules_python(self, operation):
dom = self.env['ir.rule']._compute_domain(self._name, operation)
return self.filtered_domain(dom or [])
return self.sudo().filtered_domain(dom or [])
def unlink(self):
""" unlink()