diff --git a/frappe/core/doctype/user_permission/user_permission.py b/frappe/core/doctype/user_permission/user_permission.py index f3541865ca..b0407d1a01 100644 --- a/frappe/core/doctype/user_permission/user_permission.py +++ b/frappe/core/doctype/user_permission/user_permission.py @@ -105,7 +105,7 @@ def get_user_permissions(user=None): out = {} - def add_doc_to_perm(perm, doc_name, is_default): + def add_doc_to_perm(perm, doc_name, is_default, hide_descendants): # group rules for each type # for example if allow is "Customer", then build all allowed customers # in a list @@ -114,7 +114,12 @@ def get_user_permissions(user=None): out[perm.allow].append( frappe._dict( - {"doc": doc_name, "applicable_for": perm.get("applicable_for"), "is_default": is_default} + { + "doc": doc_name, + "applicable_for": perm.get("applicable_for"), + "is_default": is_default, + "hide_descendants": hide_descendants, + } ) ) @@ -125,12 +130,12 @@ def get_user_permissions(user=None): filters=dict(user=user), ): meta = frappe.get_meta(perm.allow) - add_doc_to_perm(perm, perm.for_value, perm.is_default) + add_doc_to_perm(perm, perm.for_value, perm.is_default, perm.hide_descendants) if meta.is_nested_set() and not perm.hide_descendants: decendants = frappe.db.get_descendants(perm.allow, perm.for_value) for doc in decendants: - add_doc_to_perm(perm, doc, False) + add_doc_to_perm(perm, doc, False, False) out = frappe._dict(out) frappe.cache.hset("user_permissions", user, out) diff --git a/frappe/permissions.py b/frappe/permissions.py index 0ed085234f..3d85c955b8 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -356,7 +356,8 @@ def has_user_permission(doc, user=None, debug=False, *, ptype=None): # STEP 1: --------------------- # check user permissions on self if doctype in user_permissions: - allowed_docs = get_allowed_docs_for_doctype(user_permissions.get(doctype, []), doctype) + doctype_up = user_permissions.get(doctype, []) + allowed_docs = get_allowed_docs_for_doctype(doctype_up, doctype) # if allowed_docs is empty it states that there is no applicable permission under the current doctype @@ -367,20 +368,12 @@ def has_user_permission(doc, user=None, debug=False, *, ptype=None): if parent := doc.get(doc.nsm_parent_field): from frappe.utils.nestedset import get_ancestors_of + doc_hide_descendants = {d.doc: d.hide_descendants for d in doctype_up} + for d in [parent, *get_ancestors_of(doctype, parent)]: - if d in allowed_docs: - try: - up = frappe.get_doc( - "User Permission", - {"allow": doctype, "for_value": d, "user": user}, - fields=["hide_descendants"], - ) - except frappe.DoesNotExistError: - frappe.clear_last_message() - continue - if not up.hide_descendants: - condition = False - break + if d in allowed_docs and not doc_hide_descendants[d]: + condition = False + break else: condition = str(docname) not in allowed_docs