From 33b7d7d74f0c97dc43e297ae260d7fd30cfc7959 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 24 Dec 2021 13:28:40 +0530 Subject: [PATCH 1/4] fix: Handle custom child tables via check_parent_permission Check `tabCustom Field` and `tabDocfield` for matching parent existence. --- frappe/model/db_query.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 16c0d18d9f..6d261dd4fd 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -787,12 +787,15 @@ class DatabaseQuery(object): def check_parent_permission(parent, child_doctype): if parent: # User may pass fake parent and get the information from the child table - if child_doctype and not frappe.db.exists('DocField', - {'parent': parent, 'options': child_doctype}): + if child_doctype and not ( + frappe.db.exists('DocField', {'parent': parent, 'options': child_doctype}) + or frappe.db.exists('Custom Field', {'dt': parent, 'options': child_doctype}) + ): raise frappe.PermissionError if frappe.permissions.has_permission(parent): return + # Either parent not passed or the user doesn't have permission on parent doctype of child table! raise frappe.PermissionError From 3b7b555148d8ffa9a4f10ffcb52855a28b3879ae Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 24 Dec 2021 13:57:07 +0530 Subject: [PATCH 2/4] fix: Pass parent_doctype required for DatabaseQuery perm checks has_child_table_permission would throw 'Parent DocType Required: Please specify a valid parent DocType for {TEST DOCTYPE}' after the previous commit 33b7d7d74f0c97dc43e297ae260d7fd30cfc7959. Passing parent_doctype solves this --- frappe/client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/client.py b/frappe/client.py index 6641e471af..e835e7fee7 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -32,6 +32,7 @@ def get_list(doctype, fields=None, filters=None, order_by=None, args = frappe._dict( doctype=doctype, + parent_doctype=parent, fields=fields, filters=filters, or_filters=or_filters, From 84ebdabe49fc9447acead8300808b4af3387974a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 24 Dec 2021 13:59:57 +0530 Subject: [PATCH 3/4] refactor(minor): frappe.has_permission The throw block was very clearly broken. Referencing frappe.throw inside __init__.py rip. Added drop in replacement msgprint call --- frappe/__init__.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 96aa2b1b5f..08c0f794b3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -740,17 +740,26 @@ def has_permission(doctype=None, ptype="read", doc=None, user=None, verbose=Fals :param doc: [optional] Checks User permissions for given doc. :param user: [optional] Check for given user. Default: current user. :param parent_doctype: Required when checking permission for a child DocType (unless doc is specified).""" + import frappe.permissions + if not doctype and doc: doctype = doc.doctype - import frappe.permissions out = frappe.permissions.has_permission(doctype, ptype, doc=doc, verbose=verbose, user=user, raise_exception=throw, parent_doctype=parent_doctype) + if throw and not out: - if doc: - frappe.throw(_("No permission for {0}").format(doc.doctype + " " + doc.name)) - else: - frappe.throw(_("No permission for {0}").format(doctype)) + # mimics frappe.throw + document_label = f"{doc.doctype} {doc.name}" if doc else doctype + msgprint( + _("No permission for {0}").format(document_label), + raise_exception=ValidationError, + title=None, + indicator='red', + is_minimizable=None, + wide=None, + as_list=False + ) return out From 0f71dd411bbbb3a3eaa30150f4d0a7acc4971e55 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 24 Dec 2021 14:01:26 +0530 Subject: [PATCH 4/4] style: DatabaseQuery.execute's permission cond block --- frappe/model/db_query.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 6d261dd4fd..cb2c2af898 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -36,10 +36,12 @@ class DatabaseQuery(object): ignore_ifnull=False, save_user_settings=False, save_user_settings_fields=False, update=None, add_total_row=None, user_settings=None, reference_doctype=None, run=True, strict=True, pluck=None, ignore_ddl=False, parent_doctype=None) -> List: - if not ignore_permissions and \ - not frappe.has_permission(self.doctype, "select", user=user, parent_doctype=parent_doctype) and \ - not frappe.has_permission(self.doctype, "read", user=user, parent_doctype=parent_doctype): + if ( + not ignore_permissions + and not frappe.has_permission(self.doctype, "select", user=user, parent_doctype=parent_doctype) + and not frappe.has_permission(self.doctype, "read", user=user, parent_doctype=parent_doctype) + ): frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(self.doctype)) raise frappe.PermissionError(self.doctype)