[FIX] project: manage true and false domain for project sharing

Before this commit, when the domain used in `read_group` and `search` to
check if the portal user can access to the fields used in the domain
does not take into account the `TRUE_LEAF` (that is, `(1, '=', 1)`) and
`FALSE_LEAF` (that is, `(0, '=', 1)`). In other words, when the
`TRUE_LEAF` or `FALSE_LEAF` is in the domain, an access error is raised
saying the field name `1` or `0` cannot be accessible by the portal user.

This commit allows to add `TRUE_LEAF` and `FALSE_LEAF` in the domain to
avoid having an access error because of that.

close #103214

closes odoo/odoo#103465

X-original-commit: 953033e1ab20a01918dae7ca495654cddef14af3
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
Signed-off-by: Xavier <xbo@odoo.com>
This commit is contained in:
Xavier BOL (xbo)
2022-10-18 20:49:26 +02:00
parent 3772a25920
commit d8fecf4c1c
2 changed files with 56 additions and 3 deletions
+3 -3
View File
@@ -1884,13 +1884,13 @@ class Task(models.Model):
# only take field name when having ':' e.g 'date_deadline:week' => 'date_deadline'
fields_list += [f.split(':')[0] for f in fields_groupby]
if domain:
fields_list += [term[0].split('.')[0] for term in domain if isinstance(term, (tuple, list))]
fields_list += [term[0].split('.')[0] for term in domain if isinstance(term, (tuple, list)) and term not in [expression.TRUE_LEAF, expression.FALSE_LEAF]]
self._ensure_fields_are_accessible(fields_list)
return super(Task, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
@api.model
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
fields_list = {term[0] for term in args if isinstance(term, (tuple, list))}
fields_list = {term[0] for term in args if isinstance(term, (tuple, list)) and term not in [expression.TRUE_LEAF, expression.FALSE_LEAF]}
self._ensure_fields_are_accessible(fields_list)
return super(Task, self)._search(args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
@@ -1902,7 +1902,7 @@ class Task(models.Model):
return super(Task, self).mapped(func)
def filtered_domain(self, domain):
fields_list = [term[0] for term in domain if isinstance(term, (tuple, list))]
fields_list = [term[0] for term in domain if isinstance(term, (tuple, list)) and term not in [expression.TRUE_LEAF, expression.FALSE_LEAF]]
self._ensure_fields_are_accessible(fields_list)
return super(Task, self).filtered_domain(domain)
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command
from odoo.osv import expression
from odoo.exceptions import AccessError
from odoo.tests import tagged
from odoo.tests.common import Form
@@ -246,3 +247,55 @@ class TestProjectSharing(TestProjectSharingCommon):
],
})
self.task_portal.with_user(self.user_portal).write({'stage_id': self.project_portal.type_ids[-1].id})
def test_orm_method_with_true_false_domain(self):
""" Test orm method overriden in project for project sharing works with TRUE_LEAF/FALSE_LEAF
Test Case
=========
1) Share a project in edit mode for portal user
2) Search the portal task contained in the project shared by using a domain with TRUE_LEAF
3) Check the task is found with the `search` method
4) filter the task with `TRUE_DOMAIN` and check if the task is always returned by `filtered_domain` method
5) filter the task with `FALSE_DOMAIN` and check if no task is returned by `filtered_domain` method
6) Search the task with `FALSE_LEAF` and check no task is found with `search` method
7) Call `read_group` method with `TRUE_LEAF` in the domain and check if the task is found
8) Call `read_group` method with `FALSE_LEAF` in the domain and check if no task is found
"""
domain = [('id', '=', self.task_portal.id)]
self.project_portal.write({
'collaborator_ids': [Command.create({
'partner_id': self.user_portal.partner_id.id,
})],
})
task = self.env['project.task'].with_user(self.user_portal).search(
expression.AND([
expression.TRUE_DOMAIN,
domain,
])
)
self.assertTrue(task, 'The task should be found.')
self.assertEqual(task, task.filtered_domain(expression.TRUE_DOMAIN), 'The task found should be kept since the domain is truly')
self.assertFalse(task.filtered_domain(expression.FALSE_DOMAIN), 'The task should not be found since the domain is falsy')
task = self.env['project.task'].with_user(self.user_portal).search(
expression.AND([
expression.FALSE_DOMAIN,
domain,
]),
)
self.assertFalse(task, 'No task should be found since the domain contained a falsy tuple.')
task_read_group = self.env['project.task'].read_group(
expression.AND([expression.TRUE_DOMAIN, domain]),
['id'],
[],
)
self.assertEqual(task_read_group[0]['__count'], 1, 'The task should be found with the read_group method containing a truly tuple.')
self.assertEqual(task_read_group[0]['id'], self.task_portal.id, 'The task should be found with the read_group method containing a truly tuple.')
task_read_group = self.env['project.task'].read_group(
expression.AND([expression.FALSE_DOMAIN, domain]),
['id'],
[],
)
self.assertFalse(task_read_group[0]['__count'], 'No result should found with the read_group since the domain is falsy.')