Files
server-backend/base_user_role/models/user.py
Andrius Laukavičius 115aba15df [FIX] base_user_role: default user multi-company
When creating user, default roles are using `base.default_user`, which
in multi-company case, can be from different company than user is being
created for. If thats the case, user creating another user, will get
access error, when trying to read default template user.

To work around that, we use sudo, to make sure, template user data can
be read regardless of a company.

Also improved the way base_user_role tests are run. Changed base test
class from TransactionCase to SavepointCase.

From how tests are ran perspective, both classes behave the same: each
test uses set up which is roll backed after.

But the difference is that SavepointCase case is much faster, because
it calls setUpClass once and saves this case for all tests (reusing
saved state).
2020-12-16 20:12:49 +02:00

101 lines
3.4 KiB
Python

# Copyright 2014 ABF OSIELL <http://osiell.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class ResUsers(models.Model):
_inherit = "res.users"
role_line_ids = fields.One2many(
comodel_name="res.users.role.line",
inverse_name="user_id",
string="Role lines",
default=lambda self: self._default_role_lines(),
)
role_ids = fields.One2many(
comodel_name="res.users.role",
string="Roles",
compute="_compute_role_ids",
)
@api.model
def _default_role_lines(self):
default_user = self.env.ref(
'base.default_user', raise_if_not_found=False).sudo()
default_values = []
if default_user:
for role_line in default_user.role_line_ids:
default_values.append(
{
"role_id": role_line.role_id.id,
"date_from": role_line.date_from,
"date_to": role_line.date_to,
"is_enabled": role_line.is_enabled,
}
)
return default_values
@api.multi
@api.depends("role_line_ids.role_id")
def _compute_role_ids(self):
for user in self:
user.role_ids = user.role_line_ids.mapped("role_id")
@api.model
def create(self, vals):
new_record = super(ResUsers, self).create(vals)
new_record.set_groups_from_roles()
return new_record
@api.multi
def write(self, vals):
res = super(ResUsers, self).write(vals)
self.sudo().set_groups_from_roles()
return res
def _get_applicable_roles(self):
return self.role_line_ids.filtered(
lambda rec: rec.is_enabled
and (
not rec.company_id or rec.company_id == rec.user_id.company_id
)
)
@api.multi
def set_groups_from_roles(self, force=False):
"""Set (replace) the groups following the roles defined on users.
If no role is defined on the user, its groups are let untouched unless
the `force` parameter is `True`.
"""
role_groups = {}
# We obtain all the groups associated to each role first, so that
# it is faster to compare later with each user's groups.
for role in self.mapped("role_line_ids.role_id"):
role_groups[role] = list(
set(
role.group_id.ids
+ role.implied_ids.ids
+ role.trans_implied_ids.ids
)
)
for user in self:
if not user.role_line_ids and not force:
continue
group_ids = []
for role_line in user._get_applicable_roles():
role = role_line.role_id
if role:
group_ids += role_groups[role]
group_ids = list(set(group_ids)) # Remove duplicates IDs
groups_to_add = list(set(group_ids) - set(user.groups_id.ids))
groups_to_remove = list(set(user.groups_id.ids) - set(group_ids))
to_add = [(4, gr) for gr in groups_to_add]
to_remove = [(3, gr) for gr in groups_to_remove]
groups = to_remove + to_add
if groups:
vals = {
"groups_id": groups,
}
super(ResUsers, user).write(vals)
return True