From cdeb5dcb7cdcb07a2f3b37da36affc6d43718f3f Mon Sep 17 00:00:00 2001 From: "El-Shafei H." Date: Mon, 26 May 2025 17:02:00 +0300 Subject: [PATCH 1/3] Update permissions.py --- frappe/permissions.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/frappe/permissions.py b/frappe/permissions.py index 04549744d3b2..0fee2daaac2b 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -208,10 +208,6 @@ def get_doc_permissions(doc, user=None, ptype=None, debug=False): def is_user_owner(): return (doc.get("owner") or "").lower() == user.lower() - if not has_controller_permissions(doc, ptype, user=user, debug=debug): - push_perm_check_log(_("Not allowed via controller permission check"), debug=debug) - return {ptype: 0} - permissions = copy.deepcopy(get_role_permissions(meta, user=user, is_owner=is_user_owner(), debug=debug)) debug and _debug_log( @@ -246,6 +242,10 @@ def is_user_owner(): debug and _debug_log("User has no permissions because of User Permissions") permissions = {} + if not has_controller_permissions(doc, ptype, permissions, user=user, debug=debug): + push_perm_check_log(_("Not allowed via controller permission check"), debug=debug) + return {ptype: 0} + debug and _debug_log( "Final applicable permissions after evaluating user permissions: " + frappe.as_json(permissions, indent=8) @@ -431,7 +431,7 @@ def check_user_permission_on_link_fields(d): return True -def has_controller_permissions(doc, ptype, user=None, debug=False) -> bool: +def has_controller_permissions(doc, ptype, permissions, user=None, debug=False) -> bool: """Return controller permissions if denied, True if not defined. Controllers can only deny permission, they can not explicitly grant any permission that wasn't @@ -441,13 +441,21 @@ def has_controller_permissions(doc, ptype, user=None, debug=False) -> bool: hooks = frappe.get_hooks("has_permission") methods = hooks.get(doc.doctype, []) + hooks.get("*", []) + org_permissions = copy.deepcopy(permissions) for method in reversed(methods): - controller_permission = frappe.call(method, doc=doc, ptype=ptype, user=user, debug=debug) + controller_permission = frappe.call( + method, doc=doc, ptype=ptype, permissions=permissions, user=user, debug=debug + ) debug and _debug_log(f"Controller permission check from {method}: {controller_permission}") if not controller_permission: return bool(controller_permission) + if permissions != org_permissions: + for key, value in permissions.items(): + if org_permissions.get(key) == 0 and value == 1: + permissions[key] = 0 + return True From 00a705800e529c27090f9514623f352ac7532e20 Mon Sep 17 00:00:00 2001 From: "El-Shafei H." Date: Mon, 26 May 2025 17:02:44 +0300 Subject: [PATCH 2/3] Update toolbar.js --- frappe/public/js/frappe/form/toolbar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 71e1791c0f8b..70a4f6a4d0ce 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -455,7 +455,8 @@ frappe.ui.form.Toolbar = class Toolbar { cint(this.frm.doc.docstatus) != 1 && !this.frm.doc.__islocal && !frappe.model.is_single(this.frm.doctype) && - frappe.model.can_delete(this.frm.doctype) + frappe.model.can_delete(this.frm.doctype) && + this.frm.perm[0].delete ) { this.page.add_menu_item( __("Delete"), From c85fcc6dc8540bd2972f69d5b5f788caeb5c3c23 Mon Sep 17 00:00:00 2001 From: "El-Shafei H." Date: Tue, 27 May 2025 17:33:30 +0300 Subject: [PATCH 3/3] Update permissions.py --- frappe/permissions.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frappe/permissions.py b/frappe/permissions.py index 0fee2daaac2b..52c038ba50a0 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -447,15 +447,14 @@ def has_controller_permissions(doc, ptype, permissions, user=None, debug=False) controller_permission = frappe.call( method, doc=doc, ptype=ptype, permissions=permissions, user=user, debug=debug ) + if permissions != org_permissions: + for key, value in permissions.items(): + if org_permissions.get(key) == 0 and value == 1: + permissions[key] = 0 debug and _debug_log(f"Controller permission check from {method}: {controller_permission}") if not controller_permission: return bool(controller_permission) - if permissions != org_permissions: - for key, value in permissions.items(): - if org_permissions.get(key) == 0 and value == 1: - permissions[key] = 0 - return True