From f06f30b64f92d1d2e07230c61dd233a6dc1a2e7e Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 24 Jun 2024 13:57:19 +0000 Subject: [PATCH] feat: role replication --- .../core/doctype/role_replication/__init__.py | 0 .../role_replication/role_replication.js | 18 +++++++ .../role_replication/role_replication.json | 52 +++++++++++++++++++ .../role_replication/role_replication.py | 43 +++++++++++++++ .../role_replication/test_role_replication.py | 9 ++++ 5 files changed, 122 insertions(+) create mode 100644 frappe/core/doctype/role_replication/__init__.py create mode 100644 frappe/core/doctype/role_replication/role_replication.js create mode 100644 frappe/core/doctype/role_replication/role_replication.json create mode 100644 frappe/core/doctype/role_replication/role_replication.py create mode 100644 frappe/core/doctype/role_replication/test_role_replication.py diff --git a/frappe/core/doctype/role_replication/__init__.py b/frappe/core/doctype/role_replication/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/role_replication/role_replication.js b/frappe/core/doctype/role_replication/role_replication.js new file mode 100644 index 0000000000..eef305cbfd --- /dev/null +++ b/frappe/core/doctype/role_replication/role_replication.js @@ -0,0 +1,18 @@ +// Copyright (c) 2024, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on("Role Replication", { + refresh(frm) { + frm.disable_save(); + frm.page.set_primary_action(__("Replicate"), ($btn) => { + $btn.text(__("Replicating...")); + frappe.run_serially([ + () => frappe.dom.freeze("Replicating..."), + () => frm.call("replicate_role"), + () => frappe.dom.unfreeze(), + () => frappe.msgprint(__("Replication completed.")), + () => $btn.text(__("Replicate")), + ]); + }); + }, +}); diff --git a/frappe/core/doctype/role_replication/role_replication.json b/frappe/core/doctype/role_replication/role_replication.json new file mode 100644 index 0000000000..77ef317e41 --- /dev/null +++ b/frappe/core/doctype/role_replication/role_replication.json @@ -0,0 +1,52 @@ +{ + "actions": [], + "creation": "2024-06-24 18:25:23.163914", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "existing_role", + "column_break_ydyj", + "new_role" + ], + "fields": [ + { + "fieldname": "existing_role", + "fieldtype": "Link", + "label": "Existing Role", + "options": "Role" + }, + { + "fieldname": "column_break_ydyj", + "fieldtype": "Column Break" + }, + { + "description": "Input existing role name if you would like to extend it with access of another role.", + "fieldname": "new_role", + "fieldtype": "Data", + "label": "New Role" + } + ], + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2024-06-24 19:26:54.279801", + "modified_by": "Administrator", + "module": "Core", + "name": "Role Replication", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "creation", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/frappe/core/doctype/role_replication/role_replication.py b/frappe/core/doctype/role_replication/role_replication.py new file mode 100644 index 0000000000..df9505f418 --- /dev/null +++ b/frappe/core/doctype/role_replication/role_replication.py @@ -0,0 +1,43 @@ +# Copyright (c) 2024, Frappe Technologies and contributors +# For license information, please see license.txt + +import frappe +from frappe.core.page.permission_manager.permission_manager import get_permissions +from frappe.model.document import Document + + +class RoleReplication(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + existing_role: DF.Link | None + new_role: DF.Data | None + # end: auto-generated types + + @frappe.whitelist() + def replicate_role(self): + frappe.only_for("System Manager") + + new_role = frappe.db.get_value("Role", self.new_role, "name") + if not new_role: + new_role = frappe.get_doc({"doctype": "Role", "role_name": self.new_role}).insert().name + + perms = get_permissions(role=self.existing_role) + for perm in perms: + perm.update( + { + "name": None, + "creation": None, + "modified": None, + "modified_by": None, + "owner": None, + "linked_doctypes": None, + "role": new_role, + } + ) + frappe.get_doc({"doctype": "Custom DocPerm", **perm}).insert() diff --git a/frappe/core/doctype/role_replication/test_role_replication.py b/frappe/core/doctype/role_replication/test_role_replication.py new file mode 100644 index 0000000000..f315a06ff1 --- /dev/null +++ b/frappe/core/doctype/role_replication/test_role_replication.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Frappe Technologies and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestRoleReplication(FrappeTestCase): + pass