[FIX] base: do not depend on active_test to evaluate parent_of
Let's assume that
* Company S is a sub company of it's parent company P
* Company S has access to all the accounts and taxes of company P
* Some taxes are archived, but used
Because of the needed access rules, there will be a `parent_of` on the
record rules of accounts and taxes.
If we consider that we should consider the context key `active_test` to
add a implicit `('active', '=', True)` clause in the domain when
evaluating `parent_of` and `child_of` clauses, an access error will be
raised instead of hiding the archived records, even when simply trying
to read an archived record.
The archive feature and the security rules should be independent; if a
security rules needs to depend on the fact that a record is archived, it
should be explicit in the domain and not rely on side effects of the
implementation of `parent_of`/`child_of`
Part-of: odoo/odoo#125642
This commit is contained in:
@@ -196,7 +196,7 @@ class Partner(models.Model):
|
||||
title = fields.Many2one('res.partner.title')
|
||||
parent_id = fields.Many2one('res.partner', string='Related Company', index=True)
|
||||
parent_name = fields.Char(related='parent_id.name', readonly=True, string='Parent name')
|
||||
child_ids = fields.One2many('res.partner', 'parent_id', string='Contact', domain=[('active', '=', True)]) # force "active_test" domain to bypass _search() override
|
||||
child_ids = fields.One2many('res.partner', 'parent_id', string='Contact', domain=[('active', '=', True)])
|
||||
ref = fields.Char(string='Reference', index=True)
|
||||
lang = fields.Selection(_lang_get, string='Language',
|
||||
help="All the emails and documents sent to this contact will be translated in this language.")
|
||||
@@ -890,16 +890,6 @@ class Partner(models.Model):
|
||||
partner = self.create(create_values)
|
||||
return partner.id, partner.display_name
|
||||
|
||||
@api.model
|
||||
def _search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None):
|
||||
""" Override search() to always show inactive children when searching via ``child_of`` operator. The ORM will
|
||||
always call search() with a simple domain of the form [('parent_id', 'in', [ids])]. """
|
||||
# a special ``domain`` is set on the ``child_ids`` o2m to bypass this logic, as it uses similar domain expressions
|
||||
if len(domain) == 1 and len(domain[0]) == 3 and domain[0][:2] == ('parent_id', 'in') \
|
||||
and domain[0][2] != [False]:
|
||||
self = self.with_context(active_test=False)
|
||||
return super()._search(domain, offset, limit, order, access_rights_uid)
|
||||
|
||||
@api.model
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def find_or_create(self, email, assert_valid_email=False):
|
||||
|
||||
@@ -265,10 +265,10 @@ class TestHttpStatic(TestHttpStaticCommon):
|
||||
)
|
||||
|
||||
def test_static16_public_access_rights(self):
|
||||
public_user = self.env.ref('base.public_user')
|
||||
default_user = self.env.ref('base.default_user')
|
||||
|
||||
with self.subTest('model access rights'):
|
||||
res = self.url_open(f'/web/content/res.users/{public_user.id}/image_128')
|
||||
res = self.url_open(f'/web/content/res.users/{default_user.id}/image_128')
|
||||
self.assertEqual(res.status_code, 404)
|
||||
|
||||
with self.subTest('attachment + field access rights'):
|
||||
|
||||
+1
-1
@@ -5713,7 +5713,7 @@ class BaseModel(metaclass=MetaModel):
|
||||
else:
|
||||
(key, comparator, value) = leaf
|
||||
if comparator in ('child_of', 'parent_of'):
|
||||
stack.append(set(self.search([('id', 'in', self.ids), leaf], order='id')._ids))
|
||||
stack.append(set(self.with_context(active_test=False).search([('id', 'in', self.ids), leaf], order='id')._ids))
|
||||
continue
|
||||
|
||||
if key.endswith('.id'):
|
||||
|
||||
@@ -868,6 +868,7 @@ class expression(object):
|
||||
(when available), or as an expanded [(left,in,child_ids)] """
|
||||
if not ids:
|
||||
return [FALSE_LEAF]
|
||||
left_model = left_model.with_context(active_test=False)
|
||||
if left_model._parent_store:
|
||||
domain = OR([
|
||||
[('parent_path', '=like', rec.parent_path + '%')]
|
||||
@@ -896,6 +897,7 @@ class expression(object):
|
||||
(when available), or as an expanded [(left,in,parent_ids)] """
|
||||
if not ids:
|
||||
return [FALSE_LEAF]
|
||||
left_model = left_model.with_context(active_test=False)
|
||||
if left_model._parent_store:
|
||||
parent_ids = [
|
||||
int(label)
|
||||
|
||||
Reference in New Issue
Block a user