From 33b534ac6e57784ca40e79b1423627bdbfa64893 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 30 Nov 2018 15:02:07 +0530 Subject: [PATCH] Fix "replicate user permission" patch --- .../patches/v11_0/remove_skip_for_doctype.py | 31 +++++++++++++------ .../v11_0/replicate_old_user_permissions.py | 29 ++++++++++------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/frappe/patches/v11_0/remove_skip_for_doctype.py b/frappe/patches/v11_0/remove_skip_for_doctype.py index c53434ffa8..ccdabd4451 100644 --- a/frappe/patches/v11_0/remove_skip_for_doctype.py +++ b/frappe/patches/v11_0/remove_skip_for_doctype.py @@ -1,5 +1,6 @@ import frappe from frappe.desk.form.linked_with import get_linked_doctypes +from frappe.patches.v11_0.replicate_old_user_permissions import get_doctypes_to_skip # `skip_for_doctype` was a un-normalized way of storing for which # doctypes the user permission was applicable. @@ -12,19 +13,31 @@ from frappe.desk.form.linked_with import get_linked_doctypes def execute(): frappe.reload_doctype('User Permission') - linked_with_map = {} + + # to check if we need to migrate from skip_for_doctype + has_skip_for_doctype = frappe.db.has_column("User Permission", "skip_for_doctype") + skip_for_doctype_map = {} + for user_permission in frappe.get_all('User Permission', fields=['*']): - if not user_permission.skip_for_doctype: - frappe.db.set_value('User Permission', user_permission.name, 'apply_to_all_doctypes', 1) - continue - skip_for_doctype = user_permission.skip_for_doctype.split('\n') + if has_skip_for_doctype: + if not user_permission.skip_for_doctype: + frappe.db.set_value('User Permission', user_permission.name, 'apply_to_all_doctypes', 1) + continue + skip_for_doctype = user_permission.skip_for_doctype.split('\n') + else: + if skip_for_doctype_map[(user_permission.allow, user_permission.user)] == None: + skip_for_doctype = get_doctypes_to_skip(user_permission.allow, user_permission.user) + # cache skip for doctype for same user and doctype + skip_for_doctype_map[(user_permission.allow, user_permission.user)] = skip_for_doctype + else: + skip_for_doctype = skip_for_doctype_map[(user_permission.allow, user_permission.user)] + if skip_for_doctype: # only specific doctypes are selected # split this into multiple records and delete - if linked_with_map.get(user_permission.allow) == None: - linked_with_map[user_permission.allow] = get_linked_doctypes(user_permission.allow, True).keys() - # linked with doctypes that are not in skip_for_doctype - applicable_for_doctypes = filter(lambda d: d not in skip_for_doctype, linked_with_map[user_permission.allow]) + linked_doctypes = get_linked_doctypes(user_permission.allow, True).keys() + applicable_for_doctypes = list(set(linked_doctypes) - set(skip_for_doctype)) + frappe.db.sql('DELETE FROM `tabUser Permission` WHERE `name`=%s', user_permission.name) user_permission.name = None user_permission.skip_for_doctype = None diff --git a/frappe/patches/v11_0/replicate_old_user_permissions.py b/frappe/patches/v11_0/replicate_old_user_permissions.py index 6a89488577..63b072502d 100644 --- a/frappe/patches/v11_0/replicate_old_user_permissions.py +++ b/frappe/patches/v11_0/replicate_old_user_permissions.py @@ -1,7 +1,7 @@ import frappe import json from frappe.utils import cint -from frappe.permissions import get_valid_perms, get_linked_doctypes +from frappe.permissions import get_valid_perms def execute(): frappe.reload_doctype("User Permission") @@ -16,12 +16,14 @@ def execute(): if not doctype_to_skip_map: return for key, doctype_to_skip in doctype_to_skip_map.items(): if not doctype_to_skip: continue - doctype_to_skip = '\n'.join(doctype_to_skip) - frappe.db.sql(""" - update `tabUser Permission` - set skip_for_doctype = %s - where user=%s and allow=%s - """, (doctype_to_skip, key[1], key[0])) + if not frappe.db.has_column("User Permission", "applicable_for") \ + and frappe.db.has_column("User Permission", "skip_for_doctype"): + doctype_to_skip = '\n'.join(doctype_to_skip) + frappe.db.sql(""" + update `tabUser Permission` + set skip_for_doctype = %s + where user=%s and allow=%s + """, (doctype_to_skip, key[1], key[0])) def get_doctypes_to_skip(doctype, user): @@ -32,9 +34,6 @@ def get_doctypes_to_skip(doctype, user): parent_doctype = perm.parent try: linked_doctypes = get_linked_doctypes(parent_doctype) - child_doctypes = [d.options for d in frappe.get_meta(parent_doctype).get_table_fields()] - for child_dt in child_doctypes: - linked_doctypes += get_linked_doctypes(child_dt) if doctype not in linked_doctypes: continue except frappe.DoesNotExistError: # if doctype not found (may be due to rename) it should not be considered for skip @@ -72,4 +71,12 @@ def get_user_permission_doctypes(perm): try: return json.loads(perm.user_permission_doctypes or '[]') except ValueError: - return [] \ No newline at end of file + return [] + +def get_linked_doctypes(doctype): + from frappe.permissions import get_linked_doctypes + linked_doctypes = get_linked_doctypes(doctype) + child_doctypes = [d.options for d in frappe.get_meta(doctype).get_table_fields()] + for child_dt in child_doctypes: + linked_doctypes += get_linked_doctypes(child_dt) + return linked_doctypes \ No newline at end of file