From bece0fb6755de1580e8bbd00fbc788ae2d0d15d9 Mon Sep 17 00:00:00 2001 From: Yolann Sabaux Date: Tue, 19 Jul 2022 07:05:08 +0000 Subject: [PATCH] [FIX] project: filter stages based on the user_id Steps to reproduce: - have a project with a stage having the user_id set to Mitchell Admin (in this scenario you would have to add the field in the view) - create a task in this stage - log in with Marc Demo - Try to open the project Issue: There will be an access error Cause: The domain allows to fetch all tasks from a project; even those from a prohibited stage Solution: - As in d4252825f52a3172420dcda0ea394e42da9f8853, we'll restrict the domain and "hide task stages if user is set". - Prevent the user to create/modify a record to it with with a `user_id` and `project_ids` opw-2917631 closes odoo/odoo#101965 X-original-commit: fdaef9276b89e2170128e205a4b7fd0b8defc2b1 Signed-off-by: Laurent Stukkens (ltu) Signed-off-by: Xavier --- addons/project/i18n/project.pot | 8 +++ addons/project/models/project.py | 5 ++ addons/project/tests/__init__.py | 1 + .../project/tests/test_project_task_type.py | 59 +++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 addons/project/tests/test_project_task_type.py diff --git a/addons/project/i18n/project.pot b/addons/project/i18n/project.pot index 8b072f5ab0f..6cef246111d 100644 --- a/addons/project/i18n/project.pot +++ b/addons/project/i18n/project.pot @@ -576,6 +576,14 @@ msgstr "" msgid "A tag with the same name already exists." msgstr "" +#. module: project +#: code:addons/project/models/project.py:0 +#, python-format +msgid "" +"A personal stage cannot be linked to a project because it is only visible to" +" its corresponding user." +msgstr "" + #. module: project #: model:ir.model.constraint,message:project.constraint_project_task_user_rel_project_personal_stage_unique msgid "A task can only have a single personal stage per user." diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 25f40dcd2ab..9b12cbaac24 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -169,6 +169,11 @@ class ProjectTaskType(models.Model): else: stage.disabled_rating_warning = False + @api.constrains('user_id', 'project_ids') + def _check_personal_stage_not_linked_to_projects(self): + if any(stage.user_id and stage.project_ids for stage in self): + raise UserError(_('A personal stage cannot be linked to a project because it is only visible to its corresponding user.')) + def remove_personal_stage(self): """ Remove a personal stage, tasks using that stage will move to the first diff --git a/addons/project/tests/__init__.py b/addons/project/tests/__init__.py index fb617a77540..c0c2e69792c 100644 --- a/addons/project/tests/__init__.py +++ b/addons/project/tests/__init__.py @@ -12,6 +12,7 @@ from . import test_project_sharing from . import test_project_sharing_portal_access from . import test_project_sharing_ui from . import test_project_subtasks +from . import test_project_task_type from . import test_project_ui from . import test_project_update_access_rights from . import test_project_update_flow diff --git a/addons/project/tests/test_project_task_type.py b/addons/project/tests/test_project_task_type.py new file mode 100644 index 00000000000..98f0e965008 --- /dev/null +++ b/addons/project/tests/test_project_task_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.exceptions import UserError +from odoo.addons.project.tests.test_project_base import TestProjectCommon + + +class TestProjectTaskType(TestProjectCommon): + + @classmethod + def setUpClass(cls): + super(TestProjectTaskType, cls).setUpClass() + + cls.stage_created = cls.env['project.task.type'].create({ + 'name': 'Stage Already Created', + }) + + def test_create_stage(self): + ''' + Verify that it is not possible to add to a newly created stage a `user_id` and a `project_ids` + ''' + with self.assertRaises(UserError): + self.env['project.task.type'].create({ + 'name': 'New Stage', + 'user_id': self.uid, + 'project_ids': [self.project_goats.id], + }) + + def test_modify_existing_stage(self): + ''' + - case 1: [`user_id`: not set, `project_ids`: not set] | Add `user_id` and `project_ids` => UserError + - case 2: [`user_id`: set, `project_ids`: not set] | Add `project_ids` => UserError + - case 3: [`user_id`: not set, `project_ids`: set] | Add `user_id` => UserError + ''' + # case 1 + with self.assertRaises(UserError): + self.stage_created.write({ + 'user_id': self.uid, + 'project_ids': [self.project_goats.id], + }) + + # case 2 + self.stage_created.write({ + 'user_id': self.uid, + }) + with self.assertRaises(UserError): + self.stage_created.write({ + 'project_ids': [self.project_goats.id], + }) + + # case 3 + self.stage_created.write({ + 'user_id': False, + 'project_ids': [self.project_goats.id], + }) + with self.assertRaises(UserError): + self.stage_created.write({ + 'user_id': self.uid, + })