From 7a4fa2f3085f6d55cd883cc08d2fae73a76e40a0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 06:32:25 +0000 Subject: [PATCH] feat: allow wildcard for doctype in permission hooks (#25729) (#25892) * feat: allow wildcard for doctype in permission hooks * fix: pass doctype to permission query * fix: combine methods instead of alternate * test: wildcard has_permssion hook * test: wildcard has_permssion make note public * fix: fetch list of hooks once (cherry picked from commit 7e16e902d9e56376c7b89e65db62a014f8ecb3cd) Co-authored-by: Revant Nandgaonkar --- frappe/model/db_query.py | 5 +++-- frappe/permissions.py | 3 ++- frappe/tests/test_hooks.py | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 16ac6bb1a5a..c8ea790d34c 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -1028,10 +1028,11 @@ def add_user_permissions(self, user_permissions): def get_permission_query_conditions(self): conditions = [] - condition_methods = frappe.get_hooks("permission_query_conditions", {}).get(self.doctype, []) + hooks = frappe.get_hooks("permission_query_conditions", {}) + condition_methods = hooks.get(self.doctype, []) + hooks.get("*", []) if condition_methods: for method in condition_methods: - c = frappe.call(frappe.get_attr(method), self.user) + c = frappe.call(frappe.get_attr(method), self.user, doctype=self.doctype) if c: conditions.append(c) diff --git a/frappe/permissions.py b/frappe/permissions.py index df80ccd670b..1a68a7d8a44 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -433,7 +433,8 @@ def has_controller_permissions(doc, ptype, user=None, debug=False) -> bool: if not user: user = frappe.session.user - methods = frappe.get_hooks("has_permission").get(doc.doctype, []) + hooks = frappe.get_hooks("has_permission") + methods = hooks.get(doc.doctype, []) + hooks.get("*", []) if not methods: return True diff --git a/frappe/tests/test_hooks.py b/frappe/tests/test_hooks.py index 970699d01cf..6e9130c6d75 100644 --- a/frappe/tests/test_hooks.py +++ b/frappe/tests/test_hooks.py @@ -44,6 +44,14 @@ def test_has_permission(self): hooks.has_permission["Address"] = address_has_permission_hook + wildcard_has_permission_hook = hooks.has_permission.get("*", []) + if isinstance(wildcard_has_permission_hook, str): + wildcard_has_permission_hook = [wildcard_has_permission_hook] + + wildcard_has_permission_hook.append("frappe.tests.test_hooks.custom_has_permission") + + hooks.has_permission["*"] = wildcard_has_permission_hook + # Clear cache frappe.cache.delete_value("app_hooks") @@ -53,12 +61,20 @@ def test_has_permission(self): user.add_roles("System Manager") address = frappe.new_doc("Address") + # Create Note + note = frappe.new_doc("Note") + note.public = 1 + # Test! self.assertTrue(frappe.has_permission("Address", doc=address, user=username)) + self.assertTrue(frappe.has_permission("Note", doc=note, user=username)) address.flags.dont_touch_me = True self.assertFalse(frappe.has_permission("Address", doc=address, user=username)) + note.flags.dont_touch_me = True + self.assertFalse(frappe.has_permission("Note", doc=note, user=username)) + def test_ignore_links_on_delete(self): email_unsubscribe = frappe.get_doc( {"doctype": "Email Unsubscribe", "email": "test@example.com", "global_unsubscribe": 1}