diff --git a/frappe/auth.py b/frappe/auth.py index caf55380ac..d9b219bfac 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -326,6 +326,12 @@ class LoginManager: self.user = user self.post_login() + def impersonate(self, user): + current_user = frappe.session.user + self.login_as(user) + # Flag this session as impersonated session, so other code can log this. + frappe.local.session_obj.set_impersonsated(current_user) + def logout(self, arg="", user=None): if not user: user = frappe.session.user diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 4024ddc390..6ba5f0744a 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1347,5 +1347,7 @@ def get_enabled_users(): @frappe.whitelist(methods=["POST"]) def impersonate(user: str): + from frappe.sessions import Session + frappe.only_for("Administrator") - frappe.local.login_manager.login_as(user) + frappe.local.login_manager.impersonate(user) diff --git a/frappe/sessions.py b/frappe/sessions.py index 1968ea438c..5a0765524f 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -385,6 +385,14 @@ class Session: return updated_in_db + def set_impersonsated(self, original_user): + self.data.data.impersonated_by = original_user + # Forcefully flush session + self.update(force=True) + + def impersonated_by(self) -> str | None: + return self.data.data.impersonated_by + def get_expiry_period_for_query(): if frappe.db.db_type == "postgres":