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)]