Check read access on parent field of child/parent operators

The 4th element of the clause is the parent field for the child_of/parent_of
operators, so it must be used to check access as related field.
Also we must remove the 4th element when checking related domain.

issue11115
review391371002
This commit is contained in:
Cédric Krier
2022-01-11 23:07:45 +01:00
parent 1f42642bc3
commit 2563aed9b0
3 changed files with 60 additions and 9 deletions
+17 -9
View File
@@ -496,13 +496,20 @@ class ModelStorage(Model):
if is_leaf(domain):
local, relate = (domain[0].split('.', 1) + [None])[:2]
to_check[cls.__name__].add(local)
if relate:
if len(domain) >= 4:
target = pool.get(domain[3])
elif hasattr(cls._fields[local], 'get_target'):
target = cls._fields[local].get_target()
else:
return
field = cls._fields[local]
target = None
if hasattr(field, 'get_target'):
target = cls._fields[local].get_target()
if (not relate
and (domain[1].endswith('child_of')
or domain[1].endswith('parent_of'))
and len(domain) >= 4):
relate = domain[3]
domain = domain[:3] + domain[4:]
if field._type == 'reference' and len(domain) >= 4:
target = pool.get(domain[3])
domain = domain[:3] + domain[4:]
if relate and target:
target_domain = [(relate,) + tuple(domain[1:])]
check_domain(target_domain, target, to_check)
elif not domain:
@@ -518,8 +525,9 @@ class ModelStorage(Model):
for oexpr, otype in order:
local, _, relate = oexpr.partition('.')
to_check[cls.__name__].add(local)
if relate and hasattr(cls._fields[local], 'get_target'):
target = cls._fields[local].get_target()
field = cls._fields[local]
if relate and hasattr(field, 'get_target'):
target = field.get_target()
target_order = [(relate, otype)]
check_order(target_order, target, to_check)
+1
View File
@@ -21,6 +21,7 @@ class TestAccessRelate(ModelSQL):
"Test Access"
__name__ = 'test.access.relate'
value = fields.Integer("Value")
parent = fields.Many2One('test.access.relate', "Parent")
class TestAccessModel(TestAccess):
+42
View File
@@ -935,6 +935,8 @@ class ModelFieldAccessReadTestCase(_ModelFieldAccessTestCase):
TestAccess.search([('relate.value', '=', 42)])
TestAccess.search([('reference.value', '=', 42, 'test.access.relate')])
TestAccess.search([
('reference.parent.value', '=', 42, 'test.access.relate')])
TestAccess.search([], order=[('relate.value', 'ASC')])
@with_transaction(context=_context)
@@ -958,9 +960,49 @@ class ModelFieldAccessReadTestCase(_ModelFieldAccessTestCase):
with self.assertRaises(AccessError):
TestAccess.search(
[('reference.value', '=', 42, 'test.access.relate')])
with self.assertRaises(AccessError):
TestAccess.search(
[('reference.parent.value', '=', 42, 'test.access.relate')])
with self.assertRaises(AccessError):
TestAccess.search([], order=[('relate.value', 'ASC')])
@with_transaction(context=_context)
def test_access_search_relate_parent_field(self):
"Test access on search relate with a parent field"
pool = Pool()
TestAccess = pool.get('test.access')
Field = pool.get('ir.model.field')
FieldAccess = pool.get('ir.model.field.access')
field, = Field.search([
('model.model', '=', 'test.access.relate'),
('name', '=', 'parent'),
])
FieldAccess.create([{
'field': field.id,
'perm_read': True,
}])
TestAccess.search([('relate', 'child_of', 42, 'parent')])
@with_transaction(context=_context)
def test_no_access_search_relate_parent_field(self):
"Test no access on search relate with a parent field"
pool = Pool()
TestAccess = pool.get('test.access')
Field = pool.get('ir.model.field')
FieldAccess = pool.get('ir.model.field.access')
field, = Field.search([
('model.model', '=', 'test.access.relate'),
('name', '=', 'parent'),
])
FieldAccess.create([{
'field': field.id,
'perm_read': False,
}])
with self.assertRaises(AccessError):
TestAccess.search([('relate', 'child_of', 42, 'parent')])
class ModelFieldAccessWriteTestCase(_ModelFieldAccessTestCase):
_perm = 'perm_write'