[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:
@@ -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')])
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user