1# -*- coding: utf-8 -*-
2# Part of Odoo. See LICENSE file for full copyright and licensing details.
3
4from odoo.addons.mail.tests.common import mail_new_test_user
5from odoo.addons.project.tests.test_project_base import TestProjectCommon
6from odoo.exceptions import AccessError, ValidationError
7from odoo.tests.common import users
8
9
10class TestAccessRights(TestProjectCommon):
11
12    def setUp(self):
13        super().setUp()
14        self.task = self.create_task('Make the world a better place')
15        self.user = mail_new_test_user(self.env, 'Internal user', groups='base.group_user')
16        self.portal = mail_new_test_user(self.env, 'Portal user', groups='base.group_portal')
17
18    def create_task(self, name, *, with_user=None, **kwargs):
19        values = dict(name=name, project_id=self.project_pigs.id, **kwargs)
20        return self.env['project.task'].with_user(with_user or self.env.user).create(values)
21
22
23class TestCRUDVisibilityFollowers(TestAccessRights):
24
25    def setUp(self):
26        super().setUp()
27        self.project_pigs.privacy_visibility = 'followers'
28
29    @users('Internal user', 'Portal user')
30    def test_project_no_write(self):
31        with self.assertRaises(AccessError, msg="%s should not be able to write on the project" % self.env.user.name):
32            self.project_pigs.with_user(self.env.user).name = "Take over the world"
33
34        self.project_pigs.allowed_user_ids = self.env.user
35        with self.assertRaises(AccessError, msg="%s should not be able to write on the project" % self.env.user.name):
36            self.project_pigs.with_user(self.env.user).name = "Take over the world"
37
38    @users('Internal user', 'Portal user')
39    def test_project_no_unlink(self):
40        self.project_pigs.task_ids.unlink()
41        with self.assertRaises(AccessError, msg="%s should not be able to unlink the project" % self.env.user.name):
42            self.project_pigs.with_user(self.env.user).unlink()
43
44        self.project_pigs.allowed_user_ids = self.env.user
45        self.project_pigs.task_ids.unlink()
46        with self.assertRaises(AccessError, msg="%s should not be able to unlink the project" % self.env.user.name):
47            self.project_pigs.with_user(self.env.user).unlink()
48
49    @users('Internal user', 'Portal user')
50    def test_project_no_read(self):
51        self.project_pigs.invalidate_cache()
52        with self.assertRaises(AccessError, msg="%s should not be able to read the project" % self.env.user.name):
53            self.project_pigs.with_user(self.env.user).name
54
55    @users('Portal user')
56    def test_project_allowed_portal_no_read(self):
57        self.project_pigs.allowed_user_ids = self.env.user
58        self.project_pigs.invalidate_cache()
59        with self.assertRaises(AccessError, msg="%s should not be able to read the project" % self.env.user.name):
60            self.project_pigs.with_user(self.env.user).name
61
62    @users('Internal user')
63    def test_project_allowed_internal_read(self):
64        self.project_pigs.allowed_user_ids = self.env.user
65        self.project_pigs.invalidate_cache()
66        self.project_pigs.with_user(self.env.user).name
67
68    @users('Internal user', 'Portal user')
69    def test_task_no_read(self):
70        self.task.invalidate_cache()
71        with self.assertRaises(AccessError, msg="%s should not be able to read the task" % self.env.user.name):
72            self.task.with_user(self.env.user).name
73
74    @users('Portal user')
75    def test_task_allowed_portal_no_read(self):
76        self.project_pigs.allowed_user_ids = self.env.user
77        self.task.invalidate_cache()
78        with self.assertRaises(AccessError, msg="%s should not be able to read the task" % self.env.user.name):
79            self.task.with_user(self.env.user).name
80
81    @users('Internal user')
82    def test_task_allowed_internal_read(self):
83        self.project_pigs.allowed_user_ids = self.env.user
84        self.task.invalidate_cache()
85        self.task.with_user(self.env.user).name
86
87    @users('Internal user', 'Portal user')
88    def test_task_no_write(self):
89        with self.assertRaises(AccessError, msg="%s should not be able to write on the task" % self.env.user.name):
90            self.task.with_user(self.env.user).name = "Paint the world in black & white"
91
92        self.project_pigs.allowed_user_ids = self.env.user
93        with self.assertRaises(AccessError, msg="%s should not be able to write on the task" % self.env.user.name):
94            self.task.with_user(self.env.user).name = "Paint the world in black & white"
95
96    @users('Internal user', 'Portal user')
97    def test_task_no_create(self):
98        with self.assertRaises(AccessError, msg="%s should not be able to create a task" % self.env.user.name):
99            self.create_task("Archive the world, it's not needed anymore")
100
101        self.project_pigs.allowed_user_ids = self.env.user
102        with self.assertRaises(AccessError, msg="%s should not be able to create a task" % self.env.user.name):
103            self.create_task("Archive the world, it's not needed anymore")
104
105    @users('Internal user', 'Portal user')
106    def test_task_no_unlink(self):
107        with self.assertRaises(AccessError, msg="%s should not be able to unlink the task" % self.env.user.name):
108            self.task.with_user(self.env.user).unlink()
109
110        self.project_pigs.allowed_user_ids = self.env.user
111        with self.assertRaises(AccessError, msg="%s should not be able to unlink the task" % self.env.user.name):
112            self.task.with_user(self.env.user).unlink()
113
114
115class TestCRUDVisibilityPortal(TestAccessRights):
116
117    def setUp(self):
118        super().setUp()
119        self.project_pigs.privacy_visibility = 'portal'
120
121    @users('Portal user')
122    def test_task_portal_no_read(self):
123        self.task.invalidate_cache()
124        with self.assertRaises(AccessError, msg="%s should not be able to read the task" % self.env.user.name):
125            self.task.with_user(self.env.user).name
126
127    @users('Portal user')
128    def test_task_allowed_portal_read(self):
129        self.project_pigs.allowed_user_ids = self.env.user
130        self.task.invalidate_cache()
131        self.task.with_user(self.env.user).name
132
133    @users('Internal user')
134    def test_task_internal_read(self):
135        self.task.with_user(self.env.user).name
136
137
138class TestCRUDVisibilityEmployees(TestAccessRights):
139
140    def setUp(self):
141        super().setUp()
142        self.project_pigs.privacy_visibility = 'employees'
143
144    @users('Portal user')
145    def test_task_portal_no_read(self):
146        self.task.invalidate_cache()
147        with self.assertRaises(AccessError, msg="%s should not be able to read the task" % self.env.user.name):
148            self.task.with_user(self.env.user).name
149
150        self.project_pigs.allowed_user_ids = self.env.user
151        self.task.invalidate_cache()
152        with self.assertRaises(AccessError, msg="%s should not be able to read the task" % self.env.user.name):
153            self.task.with_user(self.env.user).name
154
155    @users('Internal user')
156    def test_task_allowed_portal_read(self):
157        self.task.invalidate_cache()
158        self.task.with_user(self.env.user).name
159
160
161class TestAllowedUsers(TestAccessRights):
162
163    def setUp(self):
164        super().setUp()
165        self.project_pigs.privacy_visibility = 'followers'
166
167    def test_project_permission_added(self):
168        self.project_pigs.allowed_user_ids = self.user
169        self.assertIn(self.user, self.task.allowed_user_ids)
170
171    def test_project_default_permission(self):
172        self.project_pigs.allowed_user_ids = self.user
173        task = self.create_task("Review the end of the world")
174        self.assertIn(self.user, task.allowed_user_ids)
175
176    def test_project_default_customer_permission(self):
177        self.project_pigs.privacy_visibility = 'portal'
178        self.project_pigs.partner_id = self.portal.partner_id
179        self.assertIn(self.portal, self.task.allowed_user_ids)
180        self.assertIn(self.portal, self.project_pigs.allowed_user_ids)
181
182    def test_project_permission_removed(self):
183        self.project_pigs.allowed_user_ids = self.user
184        self.project_pigs.allowed_user_ids -= self.user
185        self.assertNotIn(self.user, self.task.allowed_user_ids)
186
187    def test_project_specific_permission(self):
188        self.project_pigs.allowed_user_ids = self.user
189        john = mail_new_test_user(self.env, login='John')
190        self.task.allowed_user_ids |= john
191        self.project_pigs.allowed_user_ids -= self.user
192        self.assertIn(john, self.task.allowed_user_ids, "John should still be allowed to read the task")
193
194    def test_project_specific_remove_mutliple_tasks(self):
195        self.project_pigs.allowed_user_ids = self.user
196        john = mail_new_test_user(self.env, login='John')
197        task = self.create_task('task')
198        self.task.allowed_user_ids |= john
199        self.project_pigs.allowed_user_ids -= self.user
200        self.assertIn(john, self.task.allowed_user_ids)
201        self.assertNotIn(john, task.allowed_user_ids)
202        self.assertNotIn(self.user, task.allowed_user_ids)
203        self.assertNotIn(self.user, self.task.allowed_user_ids)
204
205    def test_no_portal_allowed(self):
206        with self.assertRaises(ValidationError, msg="It should not allow to add portal users"):
207            self.task.allowed_user_ids = self.portal
208
209    def test_visibility_changed(self):
210        self.project_pigs.privacy_visibility = 'portal'
211        self.task.allowed_user_ids |= self.portal
212        self.assertNotIn(self.user, self.task.allowed_user_ids, "Internal user should have been removed from allowed users")
213        self.project_pigs.privacy_visibility = 'employees'
214        self.assertNotIn(self.portal, self.task.allowed_user_ids, "Portal user should have been removed from allowed users")
215
216    def test_write_task(self):
217        self.user.groups_id |= self.env.ref('project.group_project_user')
218        self.assertNotIn(self.user, self.project_pigs.allowed_user_ids)
219        self.task.allowed_user_ids = self.user
220        self.project_pigs.invalidate_cache()
221        self.task.invalidate_cache()
222        self.task.with_user(self.user).name = "I can edit a task!"
223
224    def test_no_write_project(self):
225        self.user.groups_id |= self.env.ref('project.group_project_user')
226        self.assertNotIn(self.user, self.project_pigs.allowed_user_ids)
227        with self.assertRaises(AccessError, msg="User should not be able to edit project"):
228            self.project_pigs.with_user(self.user).name = "I can't edit a task!"
229