from odoo import SUPERUSER_ID, _, api, models from odoo.exceptions import AccessError IR_CONFIG_NAME = "access_restricted.fields_view_get_uid" class ResUsers(models.Model): _inherit = "res.users" @api.model def get_views(self, views, options=None): last_uid = self.env["ir.config_parameter"].sudo().get_param(IR_CONFIG_NAME) if int(last_uid) != self.env.uid: self.env["res.groups"]._update_user_groups_view() return super().get_views(views, options) def write(self, vals): if 'groups_id' in vals: self.env["ir.config_parameter"].sudo().set_param(IR_CONFIG_NAME, "0") return super().write(vals) class ResGroups(models.Model): _inherit = "res.groups" @api.model def _update_user_groups_view(self): real_uid = self.env.uid self.env["ir.config_parameter"].sudo().set_param(IR_CONFIG_NAME, real_uid) self.env.flush_all() @api.model def get_application_groups(self, domain=None): if domain is None: domain = [] domain.append(("share", "=", False)) real_uid = int( self.env["ir.config_parameter"].sudo().get_param(IR_CONFIG_NAME, "0") ) if real_uid and real_uid != SUPERUSER_ID: group_no_one_id = self.env.ref("base.group_no_one").id domain = domain + [ "|", ("user_ids", "in", [real_uid]), ("id", "=", group_no_one_id), ] return self.sudo().search(domain) def write(self, vals): config = self.env.context.get("config") # `isinstance` check is a non-xmplrpc proof. if config and isinstance(config, models.Model): implied_ids = vals.get("implied_ids") classified_group = config._get_classified_fields()["group"] # when `res.config.settings`'s `execute` method writes the `users` field to group, # it is always to remove users and the `users` field is the only key in the write dict users = vals.get("user_ids") implied_group = implied_ids and implied_ids[0][1] users_exclude_operation = ( users and len(vals) == 1 and all(u[0] == 3 for u in users) ) # ``all(u[0] == 3 for u in users)`` is to be sure that all operations are for removing. # `(3, id)` tuple removes the record from the set (the Many2many field `users`) add_implied_group_operation = implied_group in [ group[2].id for group in classified_group ] curr_user_allowed = self.env.user._is_superuser() or self.env.user.has_group( "access_restricted.group_allow_add_implied_from_settings" ) if ( users_exclude_operation or add_implied_group_operation and curr_user_allowed ): self = self.with_user(SUPERUSER_ID) else: # do nothing with groups if there is no permission to add from settings return # in the https://github.com/odoo/odoo/commit/5f12e244f6e57b8edb56788147774150e2ae134d commit # the method was refactored due to a higher performance. # Super method lacks of orm part so as consequent ir rules are not checked and we check its conditions manually. # We apply super method and check the difference of implied groups, # if the not proper group was set error is raised check_for_implied_ids = ( "implied_ids" in vals and vals["implied_ids"] and self.env.user.id != SUPERUSER_ID ) if check_for_implied_ids: implied_ids_before = self.mapped("implied_ids") groups_before = self.env.user.group_ids result = super(ResGroups, self).write(vals) if check_for_implied_ids: implied_ids_after = self.mapped("implied_ids") group_no_one = self.env.ref("base.group_no_one") implied_group_ids = implied_ids_after - implied_ids_before - group_no_one # R1 <= R2 True if all records of R1 are also in R2 if not implied_group_ids <= groups_before: raise AccessError( _( "You cannot add groups to Implied groups, because you are not allowed to increase your rights. " "Please contact your system administrator." ) ) return result