Skip to content

Commit

Permalink
[14.0][ADD] impersonate_login
Browse files Browse the repository at this point in the history
  • Loading branch information
Kev-Roche committed Apr 17, 2024
1 parent 2e77ab2 commit e7334b8
Show file tree
Hide file tree
Showing 25 changed files with 1,051 additions and 0 deletions.
96 changes: 96 additions & 0 deletions impersonate_login/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
=================
Impersonate Login
=================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1fca331cbc5f2dcb804e5612e5669a9ab4998d80f22d46d6683266580f9ca40f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
:target: https://github.com/OCA/server-auth/tree/14.0/impersonate_login
:alt: OCA/server-auth
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-auth-14-0/server-auth-14-0-impersonate_login
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=14.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows to login as another user.
In the chatter, the user who is logged as another user is displayed.
The mails and messages are sent from the orignal user.
A table diplays the impersonated logins in technical.
The user can return to his own user by clicking on the button "Return to my user".
This module is very useful for the support team.
An alternative module will be auth_admin_passkey.

**Table of contents**

.. contents::
:local:

Usage
=====

1. On the top right corner, click my user and "switch login"
2. Same place to "return to my login"

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-auth/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/server-auth/issues/new?body=module:%20impersonate_login%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Akretion

Contributors
~~~~~~~~~~~~

* Kévin Roche <kevin.roche@akretion.com>

Maintainers
~~~~~~~~~~~

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-Kev-Roche| image:: https://github.com/Kev-Roche.png?size=40px
:target: https://github.com/Kev-Roche
:alt: Kev-Roche

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-Kev-Roche|

This module is part of the `OCA/server-auth <https://github.com/OCA/server-auth/tree/14.0/impersonate_login>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions impersonate_login/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
30 changes: 30 additions & 0 deletions impersonate_login/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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).

{
"name": "Impersonate Login",
"summary": "tools",
"version": "14.0.1.0.0",
"category": "Tools",
"website": "https://github.com/OCA/server-auth",
"author": "Akretion, Odoo Community Association (OCA)",
"maintainers": ["Kev-Roche"],
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"web",
"mail",
],
"data": [
"views/assets.xml",
"views/res_users.xml",
"views/impersonate_log.xml",
"security/group.xml",
"security/ir.model.access.csv",
],
"qweb": [
"static/src/xml/user_menu.xml",
],
}
6 changes: 6 additions & 0 deletions impersonate_login/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from . import res_users
from . import ir_http
from . import mail_thread
from . import mail_message
from . import impersonate_log
from . import model
26 changes: 26 additions & 0 deletions impersonate_login/models/impersonate_log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (C) 2024 Akretion (<http://www.akretion.com>).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).


from odoo import fields, models


class ImpersonateLog(models.Model):
_name = "impersonate.log"
_description = "Impersonate Logs"

user_id = fields.Many2one(
comodel_name="res.partner",
string="User",
)
impersonated_partner_id = fields.Many2one(
comodel_name="res.partner",
string="Logged as",
)
date_start = fields.Datetime(
string="Start Date",
)
date_end = fields.Datetime(
string="End Date",
)
20 changes: 20 additions & 0 deletions impersonate_login/models/ir_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (C) 2024 Akretion (<http://www.akretion.com>).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import models
from odoo.http import request


class Http(models.AbstractModel):
_inherit = "ir.http"

def session_info(self):
session_info = super().session_info()
session_info.update(
{
"is_impersonate_user": request.env.user._is_impersonate_user(),
"impersonate_from_uid": request.session.impersonate_from_uid,
}
)
return session_info
52 changes: 52 additions & 0 deletions impersonate_login/models/mail_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (C) 2024 Akretion (<http://www.akretion.com>).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models
from odoo.http import request


class Message(models.Model):
_inherit = "mail.message"

impersonated_author_id = fields.Many2one(
comodel_name="res.partner",
string="Impersonated Author",
compute="_compute_impersonated_author_id",
store=True,
)

body = fields.Html(
compute="_compute_message_body",
store=True,
)

@api.depends("author_id")
def _compute_impersonated_author_id(self):
for rec in self:
if request and request.session.impersonate_from_uid:
rec.impersonated_author_id = (
self.env["res.users"]
.browse(request.session.impersonate_from_uid)
.partner_id.id
)
else:
rec.impersonated_author_id = False

@api.depends("author_id", "impersonated_author_id")
def _compute_message_body(self):
for rec in self:
additional_info = ""
if (
request
and request.session.impersonate_from_uid
and rec.impersonated_author_id
):
current_partner = (
self.env["res.users"].browse(request.session.uid).partner_id
)
additional_info = _(f"Logged as {current_partner.name}")
if rec.body and additional_info:
rec.body = f"<b>{additional_info}</b><br/>{rec.body}"
else:
rec.body = additional_info
30 changes: 30 additions & 0 deletions impersonate_login/models/mail_thread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright (C) 2024 Akretion (<http://www.akretion.com>).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import models
from odoo.http import request


class MailThread(models.AbstractModel):
_inherit = "mail.thread"

def _message_compute_author(
self, author_id=None, email_from=None, raise_exception=True
):
if (
request
and request.session.impersonate_from_uid
and author_id in [request.session.uid, None]
):
author = (
self.env["res.users"]
.browse(request.session.impersonate_from_uid)
.partner_id
)
email = author.email_formatted
return author.id, email
else:
return super()._message_compute_author(
author_id, email_from, raise_exception
)
23 changes: 23 additions & 0 deletions impersonate_login/models/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (C) 2024 Akretion (<http://www.akretion.com>).
# @author Kévin Roche <kevin.roche@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, models
from odoo.http import request


class BaseModel(models.AbstractModel):
_inherit = "base"

@api.model
def _create(self, data_list):
if request and request.session.impersonate_from_uid:
user = self.env["res.users"].browse(request.session.impersonate_from_uid)
return super(BaseModel, self.with_user(user))._create(data_list)
return super()._create(data_list)

def write(self, vals):
if request and request.session.impersonate_from_uid:
user = self.env["res.users"].browse(request.session.impersonate_from_uid)
return super(BaseModel, self.with_user(user)).write(vals)
return super().write(vals)
87 changes: 87 additions & 0 deletions impersonate_login/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# 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:
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():
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.env["res.users"]
.browse(self._uid)
.partner_id.id,
"impersonated_user_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)}"
)

request.env["res.users"].clear_caches()
request.session.session_token = security.compute_session_token(
request.session, request.env
)
return {
"type": "ir.actions.client",
"tag": "reload",
}

@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(),
}
)
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)}"
)
1 change: 1 addition & 0 deletions impersonate_login/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Kévin Roche <kevin.roche@akretion.com>
7 changes: 7 additions & 0 deletions impersonate_login/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
This module allows to login as another user.
In the chatter, the user who is logged as another user is displayed.
The mails and messages are sent from the orignal user.
A table diplays the impersonated logins in technical.
The user can return to his own user by clicking on the button "Return to my user".
This module is very useful for the support team.
An alternative module will be auth_admin_passkey.
2 changes: 2 additions & 0 deletions impersonate_login/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1. On the top right corner, click my user and "switch login"
2. Same place to "return to my login"
Loading

0 comments on commit e7334b8

Please sign in to comment.