feat: impersonate any user as Administrator
This commit is contained in:
parent
2588de6384
commit
ecc9ff378e
3 changed files with 69 additions and 0 deletions
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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", {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue