From f206714af08bcc53f019df438b429725bc458e9e Mon Sep 17 00:00:00 2001 From: Jorge Pinna Puissant Date: Fri, 8 Feb 2019 14:08:20 +0000 Subject: [PATCH] [FIX] base: creation of portal user When creating a portal user from the User & Companies menu in the Settings. Before this commit, the created user had both groups' portal user and internal user, which generated an error in the display of the user accesses and rights. This also occurred if we manually add a portal user to the internal user group. Now, when creating a portal user, the user only has this group. Also, if we manually add a portal user to the internal user group, an error is raised to inform that only one user type is allowed. OPW-1929367 closes odoo/odoo#30958 Signed-off-by: "Lucas Perais (lpe)" --- odoo/addons/base/i18n/base.pot | 7 ++ odoo/addons/base/models/res_users.py | 34 +++++- odoo/addons/base/tests/test_user_has_group.py | 100 ++++++++++++++++++ 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/odoo/addons/base/i18n/base.pot b/odoo/addons/base/i18n/base.pot index 7e9a81a70b4..7ea5dc9eea9 100644 --- a/odoo/addons/base/i18n/base.pot +++ b/odoo/addons/base/i18n/base.pot @@ -20097,6 +20097,13 @@ msgstr "" msgid "The type of the report that will be rendered, each one having its own rendering method. HTML means the report will be opened directly in your browser PDF means the report will be rendered using Wkhtmltopdf and downloaded by the user." msgstr "" +#. module: base +#: code:addons/base/models/res_users.py:117 +#: code:addons/base/models/res_users.py:404 +#, python-format +msgid "The user cannot have more than one user types." +msgstr "" + #. module: base #: model:ir.model.fields,help:base.field_ir_filters__user_id msgid "The user this filter is private to. When left empty the filter is public and available to all users." diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index afcf613f7d9..ea80fa7dbb2 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -107,6 +107,11 @@ class Groups(models.Model): ('name_uniq', 'unique (category_id, name)', 'The name of the group must be unique within an application!') ] + @api.multi + @api.constrains('users') + def _check_one_user_type(self): + self.mapped('users')._check_one_user_type() + @api.depends('category_id.name', 'name') def _compute_full_name(self): # Important: value must be stored in environment of group, not group1! @@ -386,6 +391,13 @@ class Users(models.Model): if action_open_website and any(user.action_id.id == action_open_website.id for user in self): raise ValidationError(_('The "App Switcher" action cannot be selected as home action.')) + @api.multi + @api.constrains('groups_id') + def _check_one_user_type(self): + for user in self: + if len(user.groups_id.filtered(lambda x: x.category_id.xml_id == 'base.module_category_user_type')) > 1: + raise ValidationError(_('The user cannot have more than one user types.')) + @api.multi def toggle_active(self): for user in self: @@ -901,7 +913,14 @@ class UsersImplied(models.Model): if 'groups_id' in values: # complete 'groups_id' with implied groups user = self.new(values) - gs = user.groups_id | user.groups_id.mapped('trans_implied_ids') + group_public = self.env.ref('base.group_public', raise_if_not_found=False) + group_portal = self.env.ref('base.group_portal', raise_if_not_found=False) + if group_public and group_public in user.groups_id: + gs = self.env.ref('base.group_public') | self.env.ref('base.group_public').trans_implied_ids + elif group_portal and group_portal in user.groups_id: + gs = self.env.ref('base.group_portal') | self.env.ref('base.group_portal').trans_implied_ids + else: + gs = user.groups_id | user.groups_id.mapped('trans_implied_ids') values['groups_id'] = type(self).groups_id.convert_to_write(gs, user.groups_id) return super(UsersImplied, self).create(vals_list) @@ -913,9 +932,9 @@ class UsersImplied(models.Model): for user in self.with_context({}): if not user.has_group('base.group_user'): vals = {'groups_id': [(5, 0, 0)] + values['groups_id']} - else: - gs = set(concat(g.trans_implied_ids for g in user.groups_id)) - vals = {'groups_id': [(4, g.id) for g in gs]} + super(UsersImplied, user).write(vals) + gs = set(concat(g.trans_implied_ids for g in user.groups_id)) + vals = {'groups_id': [(4, g.id) for g in gs]} super(UsersImplied, user).write(vals) return res @@ -1177,7 +1196,12 @@ class UsersView(models.Model): values[f] = get_boolean_group(f) in gids elif is_selection_groups(f): selected = [gid for gid in get_selection_groups(f) if gid in gids] - values[f] = selected and selected[-1] or False + # if 'Internal User' is in the group, this is the "User Type" group + # and we need to show 'Internal User' selected, not Public/Portal. + if self.env.ref('base.group_user').id in selected: + values[f] = self.env.ref('base.group_user').id + else: + values[f] = selected and selected[-1] or False @api.model def fields_get(self, allfields=None, attributes=None): diff --git a/odoo/addons/base/tests/test_user_has_group.py b/odoo/addons/base/tests/test_user_has_group.py index d7e44410104..0151bd2354c 100644 --- a/odoo/addons/base/tests/test_user_has_group.py +++ b/odoo/addons/base/tests/test_user_has_group.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError class TestHasGroup(TransactionCase): @@ -23,6 +24,11 @@ class TestHasGroup(TransactionCase): 'groups_id': [(4, group0.id, 0)] }) + self.grp_internal_xml_id = 'base.group_user' + self.grp_internal = self.env.ref(self.grp_internal_xml_id) + self.grp_portal_xml_id = 'base.group_portal' + self.grp_portal = self.env.ref(self.grp_portal_xml_id) + def test_env_uid(self): Users = self.env['res.users'].sudo(self.test_user) self.assertTrue( @@ -43,3 +49,97 @@ class TestHasGroup(TransactionCase): self.test_user.has_group(self.group1), "the test user shoudl not belong to group1" ) + + def test_portal_creation(self): + grp_public = self.env.ref('base.group_public') + grp_test_portal_xml_id = 'test_user_has_group.portal_implied_group' + grp_test_portal = self.env['res.groups']._load_records([ + dict(xml_id=grp_test_portal_xml_id, values={'name': 'Test Group Portal'}) + ]) + grp_test_internal1 = self.env['res.groups']._load_records([ + dict(xml_id='test_user_has_group.internal_implied_group1', values={'name': 'Test Group Itnernal 1'}) + ]) + grp_test_internal2_xml_id = 'test_user_has_group.internal_implied_group2' + grp_test_internal2 = self.env['res.groups']._load_records([ + dict(xml_id=grp_test_internal2_xml_id, values={'name': 'Test Group Internal 2'}) + ]) + self.grp_portal.implied_ids = grp_test_portal + grp_test_internal1.implied_ids = self.grp_internal + grp_test_internal2.implied_ids = self.grp_internal + portal_user = self.env['res.users'].create({ + 'login': 'portalTest', + 'name': 'Portal test', + 'sel_groups_%s_%s_%s' % (self.grp_internal.id, self.grp_portal.id, grp_public.id): self.grp_portal.id, + 'sel_groups_%s_%s' % (grp_test_internal1.id, grp_test_internal2.id): grp_test_internal2.id, + }) + + self.assertTrue( + portal_user.has_group(self.grp_portal_xml_id), + "The portal user should belong to '%s'" % self.grp_portal_xml_id, + ) + self.assertTrue( + portal_user.has_group(grp_test_portal_xml_id), + "The portal user should belong to '%s'" % grp_test_portal_xml_id, + ) + self.assertFalse( + portal_user.has_group(grp_test_internal2_xml_id), + "The portal user should not belong to '%s'" % grp_test_internal2_xml_id + ) + self.assertFalse( + portal_user.has_group(self.grp_internal_xml_id), + "The portal user should not belong to '%s'" % self.grp_internal_xml_id + ) + + def test_portal_write(self): + grp_remove_xml_id = 'test_portal_write.group_to_remove' + grp_remove = self.env['res.groups']._load_records([ + dict(xml_id=grp_remove_xml_id, values={'name': 'Group to remove'}) + ]) + portal_user = self.env['res.users'].create({ + 'login': 'portalTest2', + 'name': 'Portal test 2', + 'groups_id': [(6, 0, [grp_remove.id])], + }) + grp_test_portal_xml_id = 'test_portal_write.portal_implied_group' + grp_test_portal = self.env['res.groups']._load_records([ + dict(xml_id=grp_test_portal_xml_id, values={'name': 'Test Group Portal'}) + ]) + self.grp_portal.implied_ids = grp_test_portal + portal_user.write({'groups_id': [(4, self.grp_portal.id, 0)]}) + + self.assertFalse( + portal_user.has_group(grp_remove_xml_id), + "The portal user should not belong to '%s'" % grp_remove_xml_id + ) + self.assertTrue( + portal_user.has_group(self.grp_portal_xml_id), + "The portal user should belong to '%s'" % self.grp_portal_xml_id, + ) + self.assertTrue( + portal_user.has_group(grp_test_portal_xml_id), + "The portal user should belong to '%s'" % grp_test_portal_xml_id, + ) + + def test_two_user_types(self): + #Create a user with two groups of user types kind (Internal and Portal) + grp_test = self.env['res.groups']._load_records([ + dict(xml_id='test_two_user_types.implied_groups', values={'name': 'Test Group'}) + ]) + grp_test.implied_ids += self.grp_internal + grp_test.implied_ids += self.grp_portal + + with self.assertRaises(ValidationError): + self.env['res.users'].create({ + 'login': 'test_two_user_types', + 'name': "Test User with two user types", + 'groups_id': [(6, 0, [grp_test.id])] + }) + + #Add a user with portal to the group Internal + test_user = self.env['res.users'].create({ + 'login': 'test_user_portal', + 'name': "Test User with two user types", + 'groups_id': [(6, 0, [self.grp_portal.id])] + }) + with self.assertRaises(ValidationError): + self.grp_internal.users = [(4, test_user.id)]