1# -*- coding: utf-8 -*-
2# Part of Odoo. See LICENSE file for full copyright and licensing details.
3
4from odoo.tests.common import TransactionCase
5from odoo.exceptions import ValidationError
6
7
8class TestHasGroup(TransactionCase):
9    def setUp(self):
10        super(TestHasGroup, self).setUp()
11
12        self.group0 = 'test_user_has_group.group0'
13        self.group1 = 'test_user_has_group.group1'
14        group0, group1 = self.env['res.groups']._load_records([
15            dict(xml_id=self.group0, values={'name': 'group0'}),
16            dict(xml_id=self.group1, values={'name': 'group1'}),
17        ])
18
19        self.test_user = self.env['res.users'].create({
20            'login': 'testuser',
21            'partner_id': self.env['res.partner'].create({
22                'name': "Strawman Test User"
23            }).id,
24            'groups_id': [(6, 0, [group0.id])]
25        })
26
27        self.grp_internal_xml_id = 'base.group_user'
28        self.grp_internal = self.env.ref(self.grp_internal_xml_id)
29        self.grp_portal_xml_id = 'base.group_portal'
30        self.grp_portal = self.env.ref(self.grp_portal_xml_id)
31        self.grp_public_xml_id = 'base.group_public'
32        self.grp_public = self.env.ref(self.grp_public_xml_id)
33
34    def test_env_uid(self):
35        Users = self.env['res.users'].with_user(self.test_user)
36        self.assertTrue(
37            Users.has_group(self.group0),
38            "the test user should belong to group0"
39        )
40        self.assertFalse(
41            Users.has_group(self.group1),
42            "the test user should *not* belong to group1"
43        )
44
45    def test_record(self):
46        self.assertTrue(
47            self.test_user.has_group(self.group0),
48            "the test user should belong to group0",
49        )
50        self.assertFalse(
51            self.test_user.has_group(self.group1),
52            "the test user shoudl not belong to group1"
53        )
54
55    def test_portal_creation(self):
56        """Here we check that portal user creation fails if it tries to create a user
57           who would also have group_user by implied_group.
58           Otherwise, it succeeds with the groups we asked for.
59        """
60        grp_public = self.env.ref('base.group_public')
61        grp_test_portal_xml_id = 'test_user_has_group.portal_implied_group'
62        grp_test_portal = self.env['res.groups']._load_records([
63            dict(xml_id=grp_test_portal_xml_id, values={'name': 'Test Group Portal'})
64        ])
65        grp_test_internal1 = self.env['res.groups']._load_records([
66            dict(xml_id='test_user_has_group.internal_implied_group1', values={'name': 'Test Group Itnernal 1'})
67        ])
68        grp_test_internal2_xml_id = 'test_user_has_group.internal_implied_group2'
69        grp_test_internal2 = self.env['res.groups']._load_records([
70            dict(xml_id=grp_test_internal2_xml_id, values={'name': 'Test Group Internal 2'})
71        ])
72        self.grp_portal.implied_ids = grp_test_portal
73
74        grp_test_internal1.implied_ids = False
75        grp_test_internal2.implied_ids = False
76
77        portal_user = self.env['res.users'].create({
78            'login': 'portalTest',
79            'name': 'Portal test',
80            'sel_groups_%s_%s_%s' % (self.grp_internal.id, self.grp_portal.id, grp_public.id): self.grp_portal.id,
81            'sel_groups_%s_%s' % (grp_test_internal1.id, grp_test_internal2.id): grp_test_internal2.id,
82        })
83
84        self.assertTrue(
85            portal_user.has_group(self.grp_portal_xml_id),
86            "The portal user should belong to '%s'" % self.grp_portal_xml_id,
87        )
88        self.assertTrue(
89            portal_user.has_group(grp_test_portal_xml_id),
90            "The portal user should belong to '%s'" % grp_test_portal_xml_id,
91        )
92        self.assertTrue(
93            portal_user.has_group(grp_test_internal2_xml_id),
94            "The portal user should belong to '%s'" % grp_test_internal2_xml_id
95        )
96        self.assertFalse(
97            portal_user.has_group(self.grp_internal_xml_id),
98            "The portal user should not belong to '%s'" % self.grp_internal_xml_id
99        )
100
101        portal_user.unlink()  # otherwise, badly modifying the implication would raise
102
103        grp_test_internal1.implied_ids = self.grp_internal
104        grp_test_internal2.implied_ids = self.grp_internal
105
106        with self.assertRaises(ValidationError): # current group implications forbid to create a portal user
107            portal_user = self.env['res.users'].create({
108                'login': 'portalFail',
109                'name': 'Portal fail',
110                'sel_groups_%s_%s_%s' % (self.grp_internal.id, self.grp_portal.id, grp_public.id): self.grp_portal.id,
111                'sel_groups_%s_%s' % (grp_test_internal1.id, grp_test_internal2.id): grp_test_internal2.id,
112            })
113
114    def test_portal_write(self):
115        """Check that adding a new group to a portal user works as expected,
116           except if it implies group_user/public, in chich case it should raise.
117        """
118        grp_test_portal = self.env["res.groups"].create({"name": "implied by portal"})
119        self.grp_portal.implied_ids = grp_test_portal
120
121        portal_user = self.env['res.users'].create({
122            'login': 'portalTest2',
123            'name': 'Portal test 2',
124            'groups_id': [(6, 0, [self.grp_portal.id])],
125            })
126
127        self.assertEqual(
128            portal_user.groups_id, (self.grp_portal + grp_test_portal),
129            "The portal user should have the implied group.",
130        )
131
132        grp_fail = self.env["res.groups"].create(
133            {"name": "fail", "implied_ids": [(6, 0, [self.grp_internal.id])]})
134
135        with self.assertRaises(ValidationError):
136            portal_user.write({'groups_id': [(4, grp_fail.id)]})
137
138    def test_two_user_types(self):
139        #Create a user with two groups of user types kind (Internal and Portal)
140        grp_test = self.env['res.groups']._load_records([
141            dict(xml_id='test_two_user_types.implied_groups', values={'name': 'Test Group'})
142        ])
143        grp_test.implied_ids += self.grp_internal
144        grp_test.implied_ids += self.grp_portal
145
146        with self.assertRaises(ValidationError):
147            self.env['res.users'].create({
148                'login': 'test_two_user_types',
149                'name': "Test User with two user types",
150                'groups_id': [(6, 0, [grp_test.id])]
151            })
152
153        #Add a user with portal to the group Internal
154        test_user = self.env['res.users'].create({
155                'login': 'test_user_portal',
156                'name': "Test User with two user types",
157                'groups_id': [(6, 0, [self.grp_portal.id])]
158             })
159        with self.assertRaises(ValidationError):
160            self.grp_internal.users = [(4, test_user.id)]
161
162    def test_two_user_types_implied_groups(self):
163        """Contrarily to test_two_user_types, we simply add an implied_id to a group.
164           This will trigger the addition of the relevant users to the relevant groups;
165           if, say, this was done in SQL and thus bypassing the ORM, it would bypass the constraints
166           and thus give us a case uncovered by the aforementioned test.
167        """
168        grp_test = self.env["res.groups"].create(
169            {"name": "test", "implied_ids": [(6, 0, [self.grp_internal.id])]})
170
171        test_user = self.env['res.users'].create({
172            'login': 'test_user_portal',
173            'name': "Test User with one user types",
174            'groups_id': [(6, 0, [grp_test.id])]
175        })
176
177        with self.assertRaises(ValidationError):
178            grp_test.write({'implied_ids': [(4, self.grp_portal.id)]})
179
180    def test_demote_user(self):
181        """When a user is demoted to the status of portal/public,
182           we should strip him of all his (previous) rights
183        """
184        group_0 = self.env.ref(self.group0)  # the group to which test_user already belongs
185        group_U = self.env["res.groups"].create({"name": "U", "implied_ids": [(6, 0, [self.grp_internal.id])]})
186        self.grp_internal.implied_ids = False  # only there to simplify the test by not having to care about its trans_implied_ids
187
188        self.test_user.write({'groups_id': [(4, group_U.id)]})
189        self.assertEqual(
190            self.test_user.groups_id, (group_0 + group_U + self.grp_internal),
191            "We should have our 2 groups and the implied user group",
192        )
193
194        # Now we demote him. The JS framework sends 3 and 4 commands,
195        # which is what we write here, but it should work even with a 5 command or whatever.
196        self.test_user.write({'groups_id': [
197            (3, self.grp_internal.id),
198            (3, self.grp_public.id),
199            (4, self.grp_portal.id),
200        ]})
201
202        # if we screw up the removing groups/adding the implied ids, we could end up in two situations:
203        # 1. we have a portal user with way too much rights (e.g. 'Contact Creation', which does not imply any other group)
204        # 2. because a group may be (transitively) implying group_user, then it would raise an exception
205        # so as a compromise we remove all groups when demoting a user
206        # (even technical display groups, e.g. TaxB2B, which could be re-added later)
207        self.assertEqual(
208            self.test_user.groups_id, (self.grp_portal),
209            "Here the portal group does not imply any other group, so we should only have this group.",
210        )
211
212    def test_implied_groups(self):
213        """ We check that the adding of implied ids works correctly for normal users and portal users.
214            In the second case, working normally means raising if a group implies to give 'group_user'
215            rights to a portal user.
216        """
217        U = self.env["res.users"]
218        G = self.env["res.groups"]
219        group_user = self.env.ref('base.group_user')
220        group_portal = self.env.ref('base.group_portal')
221        group_no_one = self.env.ref('base.group_no_one')
222
223        group_A = G.create({"name": "A"})
224        group_AA = G.create({"name": "AA", "implied_ids": [(6, 0, [group_A.id])]})
225        group_B = G.create({"name": "B"})
226        group_BB = G.create({"name": "BB", "implied_ids": [(6, 0, [group_B.id])]})
227
228        # user_a is a normal user, so we expect groups to be added when we add them,
229        # as well as 'implied_groups'; otherwise nothing else should happen.
230        # By contrast, for a portal user we want implied groups not to be added
231        # if and only if it would not give group_user (or group_public) privileges
232        user_a = U.create({"name": "a", "login": "a", "groups_id": [(6, 0, [group_AA.id, group_user.id])]})
233        self.assertEqual(user_a.groups_id, (group_AA + group_A + group_user + group_no_one))
234
235        user_b = U.create({"name": "b", "login": "b", "groups_id": [(6, 0, [group_portal.id, group_AA.id])]})
236        self.assertEqual(user_b.groups_id, (group_AA + group_A + group_portal))
237
238        # user_b is not an internal user, but giving it a new group just added a new group
239        (user_a + user_b).write({"groups_id": [(4, group_BB.id)]})
240        self.assertEqual(user_a.groups_id, (group_AA + group_A + group_BB + group_B + group_user + group_no_one))
241        self.assertEqual(user_b.groups_id, (group_AA + group_A + group_BB + group_B + group_portal))
242
243        # now we create a group that implies the group_user
244        # adding it to a user should work normally, whereas adding it to a portal user should raise
245        group_C = G.create({"name": "C", "implied_ids": [(6, 0, [group_user.id])]})
246
247        user_a.write({"groups_id": [(4, group_C.id)]})
248        self.assertEqual(user_a.groups_id, (group_AA + group_A + group_BB + group_B + group_C + group_user + group_no_one))
249
250        with self.assertRaises(ValidationError):
251            user_b.write({"groups_id": [(4, group_C.id)]})
252