From 83a17a8242b592f9557462a8745a2a66b3096a8d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 1 Nov 2018 20:36:39 +0530 Subject: [PATCH] Fix user permission on link fields --- frappe/model/create_new.py | 4 ++-- frappe/model/db_query.py | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py index 639ecafe03..0d77044eeb 100644 --- a/frappe/model/create_new.py +++ b/frappe/model/create_new.py @@ -70,8 +70,8 @@ def get_user_default_value(df, defaults, user_permissions): # We don't want to include permissions of transactions to be used for defaults. if (frappe.get_meta(df.options).document_type=="Setup" and user_permissions_exist(df, user_permissions) - and len(user_permissions[df.options].get("docs", []))==1): - return user_permissions[df.options].get("docs")[0] + and len(user_permissions.get(df.options))==1): + return user_permissions.get(df.options)[0].get("doc") # 2 - Look in user defaults user_default = defaults.get(df.fieldname) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 6a91a4edd0..505f2cf083 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -34,7 +34,7 @@ class DatabaseQuery(object): ignore_permissions=False, user=None, with_comment_count=False, join='left join', distinct=False, start=None, page_length=None, limit=None, ignore_ifnull=False, save_user_settings=False, save_user_settings_fields=False, - update=None, add_total_row=None, user_settings=None): + update=None, add_total_row=None, user_settings=None, reference_doctype=None): if not ignore_permissions and not frappe.has_permission(self.doctype, "read", user=user): frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(self.doctype)) raise frappe.PermissionError(self.doctype) @@ -78,6 +78,10 @@ class DatabaseQuery(object): self.update = update self.user_settings_fields = copy.deepcopy(self.fields) + # for contextual user permission check + # to determine which user permission is applicable on link field of specific doctype + self.reference_doctype = reference_doctype + if user_settings: self.user_settings = json.loads(user_settings) @@ -218,10 +222,10 @@ class DatabaseQuery(object): if any("{0}(".format(keyword) in field.lower() for keyword in blacklisted_functions): _raise_exception() - if re.compile("[a-zA-Z]+\s*'").match(field): + if re.compile(r"[a-zA-Z]+\s*'").match(field): _raise_exception() - if re.compile('[a-zA-Z]+\s*,').match(field): + if re.compile(r'[a-zA-Z]+\s*,').match(field): _raise_exception() _is_query(field) @@ -507,6 +511,7 @@ class DatabaseQuery(object): match_conditions = [] for df in doctype_link_fields: user_permission_values = user_permissions.get(df.get('options'), {}) + if df.get('ignore_user_permissions'): continue empty_value_condition = 'ifnull(`tab{doctype}`.`{fieldname}`, "")=""'.format( @@ -521,8 +526,20 @@ class DatabaseQuery(object): condition = empty_value_condition + " or " for permission in user_permission_values: - if (not permission.get('applicable_for') # if applicable for all doctypes - or self.doctype==permission.get('applicable_for')): + if not permission.get('applicable_for'): + docs.append(permission.get('doc')) + + # append docs based on user permission applicable on reference doctype + + # This is useful when getting list of doc from a link field + # in this case parent doctype of the link will be the + # will be the reference doctype + + elif df.get('fieldname') == 'name' and self.reference_doctype: + if permission.get('applicable_for') == self.reference_doctype: + docs.append(permission.get('doc')) + + elif permission.get('applicable_for') == self.doctype: docs.append(permission.get('doc')) if docs: @@ -534,7 +551,14 @@ class DatabaseQuery(object): ) match_conditions.append("({condition})".format(condition=condition)) - match_filters[df.get('options')] = docs + + elif user_permission_values: + # this + condition += "`tab{doctype}`.`{fieldname}` in ('undefined')".format( + doctype=self.doctype, + fieldname=df.get('fieldname') + ) + match_conditions.append("({condition})".format(condition=condition)) if match_conditions: self.match_conditions.append(" and ".join(match_conditions))