[FIX] base,core: relax {child,parent}_of with related fields

In the context of branches, you need to be able to select taxes of
an ancestor company on an invoice/bill, even when you don't have access
to the ancestor company.

In order to do that, we relax the restriction when searching with a
`parent_of` or `child_of` on a related field, so that it also includes
ids of related field records you don't have access to. This should not
be a problem, since in the end the search will return records of a
model restricted by its own access rules.

task-3503204

closes odoo/odoo#138942

Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Dylan Kiss (dyki) <dyki@odoo.com>
This commit is contained in:
Dylan Kiss (dyki)
2023-10-18 12:05:25 +00:00
parent 541d2ecb87
commit f050ef335e
2 changed files with 12 additions and 12 deletions
+4 -4
View File
@@ -226,15 +226,15 @@ class TestExpression(SavepointCaseWithUserDemo):
# same kind of search from another model
Bank = self.env['res.partner.bank'].with_user(self.user_demo)
bank_top, _bank_med, bank_bot = Bank.create([
bank_top, bank_med, bank_bot = Bank.create([
{'acc_number': '1', 'partner_id': top.id},
{'acc_number': '2', 'partner_id': med.id},
{'acc_number': '3', 'partner_id': bot.id},
])
self.assertEqual(Bank.search([('partner_id', 'in', accessible.ids)]), bank_top + bank_bot)
self.assertEqual(Bank.search([('partner_id', 'child_of', top.ids)]), bank_top + bank_bot)
self.assertEqual(Bank.search([('partner_id', 'parent_of', bot.ids)]), bank_top + bank_bot)
self.assertEqual(Bank.search([('partner_id', 'child_of', top.ids)]), bank_top + bank_med + bank_bot)
self.assertEqual(Bank.search([('partner_id', 'parent_of', bot.ids)]), bank_top + bank_med + bank_bot)
def test_10_eq_lt_gt_lte_gte(self):
# test if less/greater than or equal operators work
@@ -1251,7 +1251,7 @@ class TestQueries(TransactionCase):
SELECT "res_partner_title"."id"
FROM "res_partner_title"
WHERE (COALESCE("res_partner_title"."name"->>'fr_FR', "res_partner_title"."name"->>'en_US') like %s)
ORDER BY COALESCE("res_partner_title"."name"->>'fr_FR', "res_partner_title"."name"->>'en_US')
ORDER BY COALESCE("res_partner_title"."name"->>'fr_FR', "res_partner_title"."name"->>'en_US')
''']):
Model.search([('name', 'like', 'foo')])
+8 -8
View File
@@ -869,11 +869,11 @@ 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)
left_model_sudo = left_model.sudo().with_context(active_test=False)
if left_model._parent_store:
domain = OR([
[('parent_path', '=like', rec.parent_path + '%')]
for rec in left_model.sudo().browse(ids)
for rec in left_model_sudo.browse(ids)
])
else:
# recursively retrieve all children nodes with sudo(); the
@@ -883,13 +883,13 @@ class expression(object):
if (left_model._name != left_model._fields[parent_name].comodel_name):
raise ValueError(f"Invalid parent field: {left_model._fields[parent_name]}")
child_ids = set()
records = left_model.sudo().browse(ids)
records = left_model_sudo.browse(ids)
while records:
child_ids.update(records._ids)
records = records.search([(parent_name, 'in', records.ids)], order='id') - records.browse(child_ids)
domain = [('id', 'in', list(child_ids))]
if prefix:
return [(left, 'in', left_model._search(domain))]
return [(left, 'in', left_model_sudo._search(domain))]
return domain
def parent_of_domain(left, ids, left_model, parent=None, prefix=''):
@@ -899,11 +899,11 @@ class expression(object):
ids = [id for id in ids if id] # ignore (left, 'parent_of', [False])
if not ids:
return [FALSE_LEAF]
left_model = left_model.with_context(active_test=False)
left_model_sudo = left_model.sudo().with_context(active_test=False)
if left_model._parent_store:
parent_ids = [
int(label)
for rec in left_model.sudo().browse(ids)
for rec in left_model_sudo.browse(ids)
for label in rec.parent_path.split('/')[:-1]
]
domain = [('id', 'in', parent_ids)]
@@ -913,13 +913,13 @@ class expression(object):
# done by the rest of the domain
parent_name = parent or left_model._parent_name
parent_ids = set()
records = left_model.sudo().browse(ids)
records = left_model_sudo.browse(ids)
while records:
parent_ids.update(records._ids)
records = records[parent_name] - records.browse(parent_ids)
domain = [('id', 'in', list(parent_ids))]
if prefix:
return [(left, 'in', left_model._search(domain))]
return [(left, 'in', left_model_sudo._search(domain))]
return domain
HIERARCHY_FUNCS = {'child_of': child_of_domain,