oca-server-auth/odoo-bringout-oca-server-auth-impersonate_login/impersonate_login/models/res_users.py
2025-08-29 15:43:06 +02:00

120 lines
4.6 KiB
Python

# Copyright 2024 Akretion (https://www.akretion.com).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.http import request
from odoo.service import security
logger = logging.getLogger(__name__)
class Users(models.Model):
_inherit = "res.users"
def _get_partner_name(self, user_id):
return self.env["res.users"].browse(user_id).partner_id.name
def _is_impersonate_user(self):
self.ensure_one()
return self.has_group("impersonate_login.group_impersonate_login")
def impersonate_login(self):
if request:
if request.session.impersonate_from_uid:
if self.id == request.session.impersonate_from_uid:
return self.back_to_origin_login()
else:
raise UserError(_("You are already Logged as another user."))
if self.id == request.session.uid:
raise UserError(_("It's you."))
if (
request.env.user._is_impersonate_user()
and request.env.user._is_internal()
):
target_uid = self.id
request.session.impersonate_from_uid = self._uid
request.session.uid = target_uid
impersonate_log = (
self.env["impersonate.log"]
.sudo()
.create(
{
"user_id": self._uid,
"impersonated_partner_id": self.env["res.users"]
.browse(target_uid)
.partner_id.id,
"date_start": fields.datetime.now(),
}
)
)
request.session.impersonate_log_id = impersonate_log.id
logger.info(
f"IMPERSONATE: {self._get_partner_name(self._uid)} "
f"Login as {self._get_partner_name(self.id)}"
)
# invalidate session token cache as we've changed the uid
request.env["res.users"].clear_caches()
request.session.session_token = security.compute_session_token(
request.session, request.env
)
# reload the client; open the first available root menu
menu = self.env["ir.ui.menu"].search([("parent_id", "=", False)])[:1]
return {
"type": "ir.actions.client",
"tag": "reload",
"params": {"menu_id": menu.id},
}
@api.model
def action_impersonate_login(self):
if request:
from_uid = request.session.impersonate_from_uid
if not from_uid:
action = self.env["ir.actions.act_window"]._for_xml_id(
"base.action_res_users"
)
action["views"] = [[self.env.ref("base.view_users_tree").id, "tree"]]
action["domain"] = [
("id", "!=", self.env.user.id),
("share", "=", False),
]
action["target"] = "new"
return action
@api.model
def back_to_origin_login(self):
if request:
from_uid = request.session.impersonate_from_uid
if from_uid:
request.session.uid = from_uid
self.env["impersonate.log"].sudo().browse(
request.session.impersonate_log_id
).write(
{
"date_end": fields.datetime.now(),
}
)
# invalidate session token cache as we've changed the uid
request.env["res.users"].clear_caches()
request.session.impersonate_from_uid = False
request.session.impersonate_log_id = False
request.session.session_token = security.compute_session_token(
request.session, request.env
)
logger.info(
f"IMPERSONATE: {self._get_partner_name(from_uid)} "
f"Logout as {self._get_partner_name(self._uid)}"
)
# reload the client; open the first available root menu
menu = self.env["ir.ui.menu"].search([("parent_id", "=", False)])[:1]
return {
"type": "ir.actions.client",
"tag": "reload",
"params": {"menu_id": menu.id},
}