feat: impersonate any user as Administrator

This commit is contained in:
Ankush Menat 2024-02-24 15:55:59 +05:30
parent 2588de6384
commit ecc9ff378e
3 changed files with 69 additions and 0 deletions

View file

@ -2,9 +2,12 @@
# License: MIT. See LICENSE
import json
import time
from contextlib import contextmanager
from unittest.mock import patch
from urllib.parse import parse_qs, urlparse
from werkzeug.http import parse_cookie
import frappe
import frappe.exceptions
from frappe.core.doctype.user.user import (
@ -18,6 +21,7 @@ from frappe.core.doctype.user.user import (
from frappe.desk.notifications import extract_mentions
from frappe.frappeclient import FrappeClient
from frappe.model.delete_doc import delete_doc
from frappe.tests.test_api import FrappeAPITestCase
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import get_url
@ -453,6 +457,37 @@ class TestUser(FrappeTestCase):
)
class TestImpersonation(FrappeAPITestCase):
def test_impersonation(self):
with test_user(roles=["System Manager"]) as user:
self.post(
self.method_path("frappe.core.doctype.user.user.impersonate"),
{"user": user.name, "reason": "test", "sid": self.sid},
)
resp = self.get(self.method_path("frappe.auth.get_logged_user"))
self.assertEqual(resp.json["message"], user.name)
@contextmanager
def test_user(*, first_name: str | None = None, email: str | None = None, roles: list[str], **kwargs):
try:
first_name = first_name or frappe.generate_hash()
email = email or (first_name + "@example.com")
user = frappe.new_doc(
"User",
send_welcome_email=0,
email=email,
first_name=first_name,
**kwargs,
)
user.append_roles(*roles)
user.insert()
yield user
finally:
user.delete(force=True, ignore_permissions=True)
frappe.db.commit()
def delete_contact(user):
frappe.db.delete("Contact", {"email_id": user})
frappe.db.delete("Contact Email", {"email_id": user})

View file

@ -108,6 +108,7 @@ frappe.ui.form.on("User", {
}
frm.toggle_display(["sb1", "sb3", "modules_access"], false);
frm.trigger("setup_impersonation");
if (!frm.is_new()) {
if (has_access_to_edit_user()) {
@ -340,6 +341,33 @@ frappe.ui.form.on("User", {
window.location.reload();
}
},
setup_impersonation: function (frm) {
if (frappe.session.user === "Administrator" && frm.doc.name != "Administrator") {
frm.add_custom_button("Login as User", () => {
if (frm.doc.restrict_ip) {
frappe.msgprint({
message:
"There's IP restriction for this user, you can not impersonate as this user.",
title: "IP restriction is enabled",
});
return;
}
frappe.confirm(
__(
"Current session will be logged out and you will login as {0}. Are you sure?",
[frm.doc.name.bold()]
),
() => {
frappe
.xcall("frappe.core.doctype.user.user.impersonate", {
user: frm.doc.name,
})
.then(() => window.location.reload());
}
);
});
}
},
});
frappe.ui.form.on("User Email", {

View file

@ -1343,3 +1343,9 @@ def get_enabled_users():
return enabled_users
return frappe.cache.get_value("enabled_users", _get_enabled_users)
@frappe.whitelist(methods=["POST"])
def impersonate(user: str):
frappe.only_for("Administrator")
frappe.local.login_manager.login_as(user)