diff --git a/frappe/__init__.py b/frappe/__init__.py index 5506fcaed2..0413efed9f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -355,8 +355,8 @@ def get_roles(username=None): return ["Guest"] if username: - import frappe.utils.user - return frappe.utils.user.get_roles(username) + import frappe.permissions + return frappe.permissions.get_roles(username) else: return get_user().get_roles() @@ -447,6 +447,9 @@ def only_for(roles): """Raise `frappe.PermissionError` if the user does not have any of the given **Roles**. :param roles: List of roles to check.""" + if local.flags.in_test: + return + if not isinstance(roles, (tuple, list)): roles = (roles,) roles = set(roles) diff --git a/frappe/core/doctype/custom_docperm/__init__.py b/frappe/core/doctype/custom_docperm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.js b/frappe/core/doctype/custom_docperm/custom_docperm.js new file mode 100644 index 0000000000..1f04a638a1 --- /dev/null +++ b/frappe/core/doctype/custom_docperm/custom_docperm.js @@ -0,0 +1,8 @@ +// Copyright (c) 2016, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Custom DocPerm', { + refresh: function(frm) { + + } +}); diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.json b/frappe/core/doctype/custom_docperm/custom_docperm.json new file mode 100644 index 0000000000..dd2cfb6248 --- /dev/null +++ b/frappe/core/doctype/custom_docperm/custom_docperm.json @@ -0,0 +1,809 @@ +{ + "allow_copy": 0, + "allow_import": 1, + "allow_rename": 0, + "autoname": "hash", + "beta": 0, + "creation": "2017-01-11 04:21:35.217943", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "role_and_level", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Role and Level", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "role", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Role", + "length": 0, + "no_copy": 0, + "oldfieldname": "role", + "oldfieldtype": "Link", + "options": "Role", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "150px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "Filter records based on User Permissions defined for a user", + "fieldname": "apply_user_permissions", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Apply User Permissions", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "Apply this rule if the User is the Owner", + "fieldname": "if_owner", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "If user is the owner", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "permlevel", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Level", + "length": 0, + "no_copy": 0, + "oldfieldname": "permlevel", + "oldfieldtype": "Int", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "40px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "40px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "description": "JSON list of DocTypes used to apply User Permissions. If empty, all linked DocTypes will be used to apply User Permissions.", + "fieldname": "user_permission_doctypes", + "fieldtype": "Code", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "User Permission DocTypes", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_4", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Permissions", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "read", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Read", + "length": 0, + "no_copy": 0, + "oldfieldname": "read", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "write", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Write", + "length": 0, + "no_copy": 0, + "oldfieldname": "write", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "create", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Create", + "length": 0, + "no_copy": 0, + "oldfieldname": "create", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "delete", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Delete", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_8", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "submit", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Submit", + "length": 0, + "no_copy": 0, + "oldfieldname": "submit", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cancel", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Cancel", + "length": 0, + "no_copy": 0, + "oldfieldname": "cancel", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "amend", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Amend", + "length": 0, + "no_copy": 0, + "oldfieldname": "amend", + "oldfieldtype": "Check", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "additional_permissions", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Additional Permissions", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "report", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Report", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "32px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "32px" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "export", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Export", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "import", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Import", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "This role update User Permissions for a user", + "fieldname": "set_user_permissions", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Set User Permissions", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_19", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "share", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Share", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "print", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Print", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "email", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Email", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2017-01-11 04:21:35.217943", + "modified_by": "Administrator", + "module": "Core", + "name": "Custom DocPerm", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "is_custom": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 1, + "read_only_onload": 0, + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 0, + "track_seen": 0 +} \ No newline at end of file diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.py b/frappe/core/doctype/custom_docperm/custom_docperm.py new file mode 100644 index 0000000000..3d2f2334d7 --- /dev/null +++ b/frappe/core/doctype/custom_docperm/custom_docperm.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class CustomDocPerm(Document): + pass diff --git a/frappe/core/doctype/custom_docperm/test_custom_docperm.py b/frappe/core/doctype/custom_docperm/test_custom_docperm.py new file mode 100644 index 0000000000..bd6e17ccc9 --- /dev/null +++ b/frappe/core/doctype/custom_docperm/test_custom_docperm.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Custom DocPerm') + +class TestCustomDocPerm(unittest.TestCase): + pass diff --git a/frappe/core/doctype/docperm/docperm.json b/frappe/core/doctype/docperm/docperm.json index be205b2fb7..8e9273118e 100644 --- a/frappe/core/doctype/docperm/docperm.json +++ b/frappe/core/doctype/docperm/docperm.json @@ -22,6 +22,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Role and Level", "length": 0, "no_copy": 0, @@ -29,6 +30,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -47,6 +49,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Role", "length": 0, "no_copy": 0, @@ -58,6 +61,7 @@ "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -78,6 +82,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Apply User Permissions", "length": 0, "no_copy": 0, @@ -85,6 +90,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -104,6 +110,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "If user is the owner", "length": 0, "no_copy": 0, @@ -112,33 +119,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "is_custom", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Is Custom", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -157,12 +138,14 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -182,6 +165,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Level", "length": 0, "no_copy": 0, @@ -192,6 +176,7 @@ "print_hide_if_no_value": 0, "print_width": "40px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -213,6 +198,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "User Permission DocTypes", "length": 0, "no_copy": 0, @@ -220,6 +206,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -238,6 +225,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Permissions", "length": 0, "no_copy": 0, @@ -245,6 +233,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -264,6 +253,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Read", "length": 0, "no_copy": 0, @@ -274,6 +264,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -294,6 +285,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Write", "length": 0, "no_copy": 0, @@ -304,6 +296,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -324,6 +317,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Create", "length": 0, "no_copy": 0, @@ -334,6 +328,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -354,6 +349,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Delete", "length": 0, "no_copy": 0, @@ -361,6 +357,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -379,12 +376,14 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -403,6 +402,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Submit", "length": 0, "no_copy": 0, @@ -413,6 +413,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -432,6 +433,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Cancel", "length": 0, "no_copy": 0, @@ -442,6 +444,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -461,6 +464,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Amend", "length": 0, "no_copy": 0, @@ -471,6 +475,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -490,6 +495,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Additional Permissions", "length": 0, "no_copy": 0, @@ -497,6 +503,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -516,6 +523,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Report", "length": 0, "no_copy": 0, @@ -524,6 +532,7 @@ "print_hide_if_no_value": 0, "print_width": "32px", "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -544,6 +553,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Export", "length": 0, "no_copy": 0, @@ -551,6 +561,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -569,6 +580,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Import", "length": 0, "no_copy": 0, @@ -576,6 +588,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -595,6 +608,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Set User Permissions", "length": 0, "no_copy": 0, @@ -602,6 +616,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -620,12 +635,14 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -645,6 +662,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Share", "length": 0, "no_copy": 0, @@ -653,6 +671,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -672,6 +691,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Print", "length": 0, "no_copy": 0, @@ -679,6 +699,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -698,6 +719,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Email", "length": 0, "no_copy": 0, @@ -705,6 +727,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -722,7 +745,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-09-29 08:07:20.450064", + "modified": "2017-01-11 04:21:44.249780", "modified_by": "Administrator", "module": "Core", "name": "DocPerm", @@ -732,5 +755,6 @@ "read_only": 0, "read_only_onload": 0, "sort_order": "ASC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 8b3c490bf5..373bd7a277 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -499,10 +499,10 @@ def get_user_roles(arg=None): return frappe.get_roles(frappe.form_dict['uid']) @frappe.whitelist() -def get_perm_info(arg=None): +def get_perm_info(role): """get permission info""" - return frappe.db.sql("""select * from tabDocPerm where role=%s - and docstatus<2 order by parent, permlevel""", (frappe.form_dict['role'],), as_dict=1) + from frappe.permissions import get_all_perms + return get_all_perms(role) @frappe.whitelist(allow_guest=True) def update_password(new_password, key=None, old_password=None): diff --git a/frappe/core/page/permission_manager/permission_manager.js b/frappe/core/page/permission_manager/permission_manager.js index 7d13d3a3a1..3b96e73e93 100644 --- a/frappe/core/page/permission_manager/permission_manager.js +++ b/frappe/core/page/permission_manager/permission_manager.js @@ -234,7 +234,8 @@ frappe.PermissionEngine = Class.extend({ checkbox.find("input") .prop("checked", d[fieldname] ? true: false) .attr("data-ptype", fieldname) - .attr("data-name", d.name) + .attr("data-role", d.role) + .attr("data-permlevel", d.permlevel) .attr("data-doctype", d.parent) checkbox.find("label") @@ -307,16 +308,18 @@ frappe.PermissionEngine = Class.extend({ var me = this; $("") .appendTo($("").appendTo(row)) - .attr("data-name", d.name) .attr("data-doctype", d.parent) + .attr("data-role", d.role) + .attr("data-permlevel", d.permlevel) .click(function() { return frappe.call({ module: "frappe.core", page: "permission_manager", method: "remove", args: { - name: $(this).attr("data-name"), - doctype: $(this).attr("data-doctype") + doctype: $(this).attr("data-doctype"), + role: $(this).attr("data-role"), + permlevel: $(this).attr("data-permlevel") }, callback: function(r) { if(r.exc) { @@ -339,7 +342,8 @@ frappe.PermissionEngine = Class.extend({ this.body.on("click", "input[type='checkbox']", function() { var chk = $(this); var args = { - name: chk.attr("data-name"), + role: chk.attr("data-role"), + permlevel: chk.attr("data-permlevel"), doctype: chk.attr("data-doctype"), ptype: chk.attr("data-ptype"), value: chk.prop("checked") ? 1 : 0 @@ -465,7 +469,8 @@ frappe.PermissionEngine = Class.extend({ method: "update", args: { doctype: d.parent, - name: d.name, + role: d.role, + permlevel: d.permlevel, ptype: "user_permission_doctypes", value: user_permission_doctypes }, @@ -477,6 +482,9 @@ frappe.PermissionEngine = Class.extend({ setTimeout(function() { msg.hide(); }, 3000); d.user_permission_doctypes = user_permission_doctypes; dialog.hide(); + if(r.message==='refresh') { + me.refresh(); + } } } }); diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index b223352e77..aebdbb7a16 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -7,7 +7,7 @@ import frappe.defaults from frappe.modules.import_file import get_file_path, read_doc_from_file from frappe.translate import send_translations from frappe.desk.notifications import delete_notification_count_for -from frappe.permissions import reset_perms, get_linked_doctypes +from frappe.permissions import reset_perms, get_linked_doctypes, get_all_perms @frappe.whitelist() def get_roles_and_doctypes(): @@ -17,7 +17,6 @@ def get_roles_and_doctypes(): "doctypes": [d[0] for d in frappe.db.sql("""select name from `tabDocType` dt where istable=0 and name not in ('DocType') and - exists(select * from `tabDocField` where parent=dt.name) and exists(select * from `tabDocPerm` dp,`tabRole` role where dp.role = role.name and dp.parent=dt.name and not role.disabled)""")], "roles": [d[0] for d in frappe.db.sql("""select name from tabRole where name != 'Administrator' and disabled=0""")] @@ -26,29 +25,30 @@ def get_roles_and_doctypes(): @frappe.whitelist() def get_permissions(doctype=None, role=None): frappe.only_for("System Manager") - out = frappe.db.sql("""select * from tabDocPerm - where %s%s order by parent, permlevel, role""" % - (doctype and (" parent='%s'" % frappe.db.escape(doctype)) or "", - role and ((doctype and " and " or "") + " role='%s'" % frappe.db.escape(role)) or ""), - as_dict=True) + if role: + out = get_all_perms(role) + if doctype: + out = [p for p in out if p.parent == doctype] + else: + out = frappe.get_all('Custom DocPerm', fields='*', filters=dict(parent = doctype)) + if not out: + out = frappe.get_all('DocPerm', fields='*', filters=dict(parent = doctype)) linked_doctypes = {} for d in out: - d.linked_doctypes = linked_doctypes.setdefault(d.parent, get_linked_doctypes(d.parent)) + if not d.parent in linked_doctypes: + linked_doctypes[d.parent] = get_linked_doctypes(d.parent) + d.linked_doctypes = linked_doctypes[d.parent] return out -@frappe.whitelist() -def remove(doctype, name): - frappe.only_for("System Manager") - frappe.db.sql("""delete from tabDocPerm where name=%s""", name) - validate_and_reset(doctype, for_remove=True) - @frappe.whitelist() def add(parent, role, permlevel): frappe.only_for("System Manager") + setup_custom_perms(parent) + frappe.get_doc({ - "doctype":"DocPerm", + "doctype":"Custom DocPerm", "__islocal": 1, "parent": parent, "parenttype": "DocType", @@ -61,12 +61,56 @@ def add(parent, role, permlevel): validate_and_reset(parent) @frappe.whitelist() -def update(name, doctype, ptype, value=None): +def update(doctype, role, permlevel, ptype, value=None): frappe.only_for("System Manager") - frappe.db.sql("""update tabDocPerm set `%s`=%s where name=%s"""\ + + out = None + if setup_custom_perms(doctype): + out = 'refresh' + + name = frappe.get_value('Custom DocPerm', dict(parent=doctype, role=role, permlevel=permlevel)) + + frappe.db.sql("""update `tabCustom DocPerm` set `%s`=%s where name=%s"""\ % (frappe.db.escape(ptype), '%s', '%s'), (value, name)) validate_and_reset(doctype) + return out + +@frappe.whitelist() +def remove(doctype, role, permlevel): + frappe.only_for("System Manager") + setup_custom_perms(doctype) + + name = frappe.get_value('Custom DocPerm', dict(parent=doctype, role=role, permlevel=permlevel)) + + frappe.db.sql('delete from `tabCustom DocPerm` where name=%s', name) + validate_and_reset(doctype, for_remove=True) + +def setup_custom_perms(parent): + '''if custom permssions are not setup for the current doctype, set them up''' + if not frappe.db.exists('Custom DocPerm', dict(parent=parent)): + copy_perms(parent) + return True + +def copy_perms(parent): + '''Copy all DocPerm in to Custom DocPerm for the given document''' + for d in frappe.get_all('DocPerm', fields='*', filters=dict(parent=parent)): + custom_perm = frappe.new_doc('Custom DocPerm') + custom_perm.update(d) + custom_perm.insert(ignore_permissions=True) + +def get_custom_perm_name(name): + '''Get the custom permission name for this DocPerm''' + if frappe.db.exists('Custom DocPerm', name): + return name + else: + original_perm = frappe.get_doc('DocPerm', name) + copy_perms(original_perm.parent) + name = frappe.db.get_value('Custom DocPerm', dict(parent=original_perm.parent, + role=original_perm.role, permlevel=original_perm.permlevel)) + + return name + def validate_and_reset(doctype, for_remove=False): from frappe.core.doctype.doctype.doctype import validate_permissions_for_doctype validate_permissions_for_doctype(doctype, for_remove) @@ -81,9 +125,10 @@ def reset(doctype): def clear_doctype_cache(doctype): frappe.clear_cache(doctype=doctype) delete_notification_count_for(doctype) - for user in frappe.db.sql_list("""select distinct tabUserRole.parent from tabUserRole, tabDocPerm - where tabDocPerm.parent = %s - and tabDocPerm.role = tabUserRole.role""", doctype): + for user in frappe.db.sql_list("""select distinct tabUserRole.parent from tabUserRole, + tabDocPerm + where tabDocPerm.parent = %s + and tabDocPerm.role = tabUserRole.role""", doctype): frappe.clear_cache(user=user) @frappe.whitelist() diff --git a/frappe/core/page/user_permissions/user_permissions.py b/frappe/core/page/user_permissions/user_permissions.py index a06a8c0c41..a9b34ca009 100644 --- a/frappe/core/page/user_permissions/user_permissions.py +++ b/frappe/core/page/user_permissions/user_permissions.py @@ -5,7 +5,8 @@ from __future__ import unicode_literals import frappe from frappe import _ import frappe.defaults -import frappe.permissions +from frappe.permissions import (can_set_user_permissions, add_user_permission, + remove_user_permission, get_valid_perms) from frappe.core.doctype.user.user import get_system_users from frappe.utils.csvutils import UnicodeWriter, read_csv_content_from_uploaded_file from frappe.defaults import clear_default @@ -19,7 +20,7 @@ def get_users_and_links(): @frappe.whitelist() def get_permissions(parent=None, defkey=None, defvalue=None): - if defkey and not frappe.permissions.can_set_user_permissions(defkey, defvalue): + if defkey and not can_set_user_permissions(defkey, defvalue): raise frappe.PermissionError conditions, values = _build_conditions(locals()) @@ -54,33 +55,23 @@ def _build_conditions(filters): @frappe.whitelist() def remove(user, name, defkey, defvalue): - if not frappe.permissions.can_set_user_permissions(defkey, defvalue): + if not can_set_user_permissions(defkey, defvalue): frappe.throw(_("Cannot remove permission for DocType: {0} and Name: {1}").format( defkey, defvalue), frappe.PermissionError) - frappe.permissions.remove_user_permission(defkey, defvalue, user, name) + remove_user_permission(defkey, defvalue, user, name) @frappe.whitelist() def add(user, defkey, defvalue): - if not frappe.permissions.can_set_user_permissions(defkey, defvalue): + if not can_set_user_permissions(defkey, defvalue): frappe.throw(_("Cannot set permission for DocType: {0} and Name: {1}").format( defkey, defvalue), frappe.PermissionError) - frappe.permissions.add_user_permission(defkey, defvalue, user, with_message=True) + add_user_permission(defkey, defvalue, user, with_message=True) def get_doctypes_for_user_permissions(): - user_roles = frappe.get_roles() - condition = "" - values = [] - if "System Manager" not in user_roles: - condition = """and exists(select `tabDocPerm`.name from `tabDocPerm` - where `tabDocPerm`.parent=`tabDocType`.name and `tabDocPerm`.`set_user_permissions`=1 - and `tabDocPerm`.role in ({roles}))""".format(roles=", ".join(["%s"]*len(user_roles))) - values = user_roles - - return frappe.db.sql_list("""select name from tabDocType - where issingle=0 and istable=0 {condition}""".format(condition=condition), - tuple(values)) + '''Get doctypes for the current user where user permissions are applicable''' + return list(set([p.parent for p in get_valid_perms() if p.set_user_permissions])) @frappe.whitelist() def get_user_permissions_csv(): @@ -105,4 +96,4 @@ def import_user_permissions(): frappe.throw(frappe._("Please upload using the same template as download.")) for row in rows[2:]: - frappe.permissions.add_user_permission(row[1], row[2], row[0]) + add_user_permission(row[1], row[2], row[0]) diff --git a/frappe/data/Framework.sql b/frappe/data/Framework.sql index b0307a13c4..cbfaf485a3 100644 --- a/frappe/data/Framework.sql +++ b/frappe/data/Framework.sql @@ -78,7 +78,6 @@ CREATE TABLE `tabDocPerm` ( `permlevel` int(11) DEFAULT '0', `role` varchar(255) DEFAULT NULL, `match` varchar(255) DEFAULT NULL, - `is_custom` int(1) NOT NULL DEFAULT 0, `read` int(1) NOT NULL DEFAULT 1, `write` int(1) NOT NULL DEFAULT 1, `create` int(1) NOT NULL DEFAULT 1, diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 5b7fa083ed..9fd6d3705d 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -207,6 +207,7 @@ class Meta(Document): self.apply_property_setters() self.sort_fields() self.get_valid_columns() + self.set_custom_permissions() def add_custom_fields(self): try: @@ -278,6 +279,14 @@ class Meta(Document): self.fields = newlist + def set_custom_permissions(self): + '''Reset `permissions` with Custom DocPerm if exists''' + if not self.istable and self.name not in ('DocType', 'DocField', 'DocPerm', 'Custom DocPerm'): + custom_perms = frappe.get_all('Custom DocPerm', fields='*', + filters=dict(parent=self.name)) + if custom_perms: + self.permissions = custom_perms + def get_fields_to_check_permissions(self, user_permission_doctypes): fields = self.get("fields", { "fieldtype":"Link", diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index 13fc5d6def..3c27fca86e 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -11,11 +11,11 @@ def import_files(module, dt=None, dn=None, force=False, pre_process=None, reset_ if type(module) is list: out = [] for m in module: - out.append(import_file(m[0], m[1], m[2], force=force, pre_process=pre_process, + out.append(import_file(m[0], m[1], m[2], force=force, pre_process=pre_process, reset_permissions=reset_permissions)) return out else: - return import_file(module, dt, dn, force=force, pre_process=pre_process, + return import_file(module, dt, dn, force=force, pre_process=pre_process, reset_permissions=reset_permissions) def import_file(module, dt, dn, force=False, pre_process=None, reset_permissions=False): @@ -32,7 +32,7 @@ def get_file_path(module, dt, dn): return path -def import_file_by_path(path, force=False, data_import=False, pre_process=None, ignore_version=None, +def import_file_by_path(path, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False): frappe.flags.in_import = True try: @@ -89,9 +89,9 @@ ignore_values = { "Print Format": ["disabled"] } -ignore_doctypes = ["Page Role", "DocPerm"] +ignore_doctypes = ["Page Role"] -def import_doc(docdict, force=False, data_import=False, pre_process=None, +def import_doc(docdict, force=False, data_import=False, pre_process=None, ignore_version=None, reset_permissions=False): frappe.flags.in_import = True diff --git a/frappe/patches.txt b/frappe/patches.txt index 2cb28fa766..a95b5c28b6 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -7,6 +7,7 @@ frappe.patches.v7_0.re_route #2016-06-27 execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2016-10-17 execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2017-01-06 execute:frappe.reload_doc('core', 'doctype', 'docperm') #2014-06-24 +execute:frappe.reload_doc('core', 'doctype', 'custom_docperm') #2014-06-24 execute:frappe.reload_doc('core', 'doctype', 'role') execute:frappe.reload_doc('core', 'doctype', 'user') execute:frappe.reload_doc('core', 'doctype', 'deleted_document') diff --git a/frappe/permissions.py b/frappe/permissions.py index e76603193b..45cf12c070 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -177,7 +177,11 @@ def get_role_permissions(meta, user=None, verbose=False): cache_key = (meta.name, user) if not frappe.local.role_permissions.get(cache_key): - perms = frappe._dict({ "apply_user_permissions": {}, "user_permission_doctypes": {}, "if_owner": {} }) + perms = frappe._dict( + apply_user_permissions={}, + user_permission_doctypes={}, + if_owner={} + ) user_roles = frappe.get_roles(user) dont_match = [] has_a_role_with_apply_user_permissions = False @@ -301,6 +305,65 @@ def has_controller_permissions(doc, ptype, user=None): # controller permissions could not decide on True or False return None +def get_doctypes_with_read(): + return list(set([p.parent for p in get_valid_perms()])) + +def get_valid_perms(doctype=None): + '''Get valid permissions for the current user from DocPerm and Custom DocPerm''' + roles = get_roles() + + perms = get_perms_for(roles) + custom_perms = get_perms_for(roles, 'Custom DocPerm') + + doctypes_with_custom_perms = list(set([d.parent for d in custom_perms])) + for p in perms: + if not p.parent in doctypes_with_custom_perms: + custom_perms.append(p) + + if doctype: + return [p for p in custom_perms if p.parent == doctype] + else: + return custom_perms + +def get_all_perms(role): + '''Returns valid permissions for a given role''' + perms = frappe.get_all('DocPerm', fields='*', filters=dict(role=role)) + custom_perms = frappe.get_all('Custom DocPerm', fields='*', filters=dict(role=role)) + doctypes_with_custom_perms = list(set(p.parent for p in custom_perms)) + + for p in perms: + if p.parent not in doctypes_with_custom_perms: + custom_perms.append(p) + + return p + +def get_roles(user=None, with_standard=True): + """get roles of current user""" + if not user: + user = frappe.session.user + + if user=='Guest': + return ['Guest'] + + def get(): + return [r[0] for r in frappe.db.sql("""select role from tabUserRole + where parent=%s and role not in ('All', 'Guest')""", (user,))] + ['All', 'Guest'] + + roles = frappe.cache().hget("roles", user, get) + + # filter standard if required + if not with_standard: + roles = filter(lambda x: x not in ['All', 'Guest', 'Administrator'], roles) + + return roles + +def get_perms_for(roles, perm_doctype='DocPerm'): + '''Get perms for given roles''' + return frappe.db.sql("""select * from `tab{doctype}` where docstatus=0 + and ifnull(permlevel,0)=0 + and role in ({roles})""".format(doctype = perm_doctype, + roles=", ".join(["%s"]*len(roles))), tuple(roles), as_dict=1) + def can_set_user_permissions(doctype, docname=None): # System Manager can always set user permissions if frappe.session.user == "Administrator" or "System Manager" in frappe.get_roles(): @@ -323,6 +386,7 @@ def set_user_permission_if_allowed(doctype, name, user, with_message=False): add_user_permission(doctype, name, user, with_message) def add_user_permission(doctype, name, user, with_message=False): + '''Add user default''' if name not in frappe.defaults.get_user_permissions(user).get(doctype, []): if not frappe.db.exists(doctype, name): frappe.throw(_("{0} {1} not found").format(_(doctype), name), frappe.DoesNotExistError) @@ -392,9 +456,7 @@ def reset_perms(doctype): from frappe.desk.notifications import delete_notification_count_for delete_notification_count_for(doctype) - frappe.db.sql("""delete from tabDocPerm where parent=%s""", doctype) - frappe.reload_doc(frappe.db.get_value("DocType", doctype, "module"), - "DocType", doctype, force=True) + frappe.db.sql("""delete from `tabCustom DocPerm` where parent=%s""", doctype) def get_linked_doctypes(dt): return list(set([dt] + [d.options for d in diff --git a/frappe/tests/test_form_load.py b/frappe/tests/test_form_load.py index 95ea03b688..bab8b1c4ee 100644 --- a/frappe/tests/test_form_load.py +++ b/frappe/tests/test_form_load.py @@ -4,6 +4,8 @@ from __future__ import unicode_literals import frappe, unittest from frappe.desk.form.load import getdoctype, getdoc +from frappe.core.page.permission_manager.permission_manager import update, reset +from frappe.permissions import get_valid_perms class TestFormLoad(unittest.TestCase): def test_load(self): @@ -21,10 +23,16 @@ class TestFormLoad(unittest.TestCase): user = frappe.get_doc('User', 'test@example.com') user.remove_roles('Website Manager') user.add_roles('Blogger') - frappe.set_user(user.name) + reset('Blog Post') frappe.db.sql('update tabDocField set permlevel=1 where fieldname="published" and parent="Blog Post"') - frappe.db.sql('update tabDocPerm set permlevel=1 where role="Website Manager" and parent="Blog Post"') + + update('Blog Post', 'Website Manager', 0, 'permlevel', 1) + + frappe.set_user(user.name) + + # print frappe.as_json(get_valid_perms('Blog Post')) + frappe.clear_cache(doctype='Blog Post') blog = frappe.db.get_value('Blog Post', {'title': '_Test Blog Post'}) @@ -41,7 +49,7 @@ class TestFormLoad(unittest.TestCase): self.assertTrue(checked, True) frappe.db.sql('update tabDocField set permlevel=0 where fieldname="published" and parent="Blog Post"') - frappe.db.sql('update tabDocPerm set permlevel=0 where role="Website Manager" and parent="Blog Post"') + reset('Blog Post') frappe.clear_cache(doctype='Blog Post') diff --git a/frappe/tests/test_permissions.py b/frappe/tests/test_permissions.py index dd022ec74d..bde6a808e2 100644 --- a/frappe/tests/test_permissions.py +++ b/frappe/tests/test_permissions.py @@ -11,6 +11,7 @@ import json import frappe.model.meta from frappe.core.page.user_permissions.user_permissions import add, remove, get_permissions from frappe.permissions import clear_user_permissions_for_doctype, get_doc_permissions +from frappe.core.page.permission_manager.permission_manager import update, reset test_records = frappe.get_test_records('Blog Post') @@ -26,8 +27,8 @@ class TestPermissions(unittest.TestCase): user = frappe.get_doc("User", "test2@example.com") user.add_roles("Blogger") - frappe.db.sql("""update `tabDocPerm` set if_owner=0 - where parent='Blog Post' and permlevel=0 and permlevel=0 and role='Blogger'""") + reset('Blogger') + reset('Blog Post') self.set_ignore_user_permissions_if_missing(0) @@ -41,12 +42,8 @@ class TestPermissions(unittest.TestCase): clear_user_permissions_for_doctype("Blog Post") clear_user_permissions_for_doctype("Blogger") - frappe.db.sql("""update `tabDocPerm` set user_permission_doctypes=null, apply_user_permissions=0 - where parent='Blog Post' and permlevel=0 and apply_user_permissions=1 - and `read`=1""") - - frappe.db.sql("""update `tabDocPerm` set if_owner=0 - where parent='Blog Post' and permlevel=0 and permlevel=0 and role='Blogger'""") + reset('Blogger') + reset('Blog Post') self.set_ignore_user_permissions_if_missing(0) @@ -204,17 +201,14 @@ class TestPermissions(unittest.TestCase): frappe.model.meta.clear_cache("Blog Post") def if_owner_setup(self): - frappe.db.sql("""update `tabDocPerm` set if_owner=1 - where parent='Blog Post' and permlevel=0 and permlevel=0 and role='Blogger'""") + update('Blog Post', 'Blogger', 0, 'if_owner', 1) frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") frappe.permissions.add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com") - frappe.db.sql("""update `tabDocPerm` set user_permission_doctypes=%s - where parent='Blog Post' and permlevel=0 and apply_user_permissions=1 - and `read`=1""", json.dumps(["Blog Category"])) + update('Blog Post', 'Blogger', 0, 'user_permission_doctypes', json.dumps(["Blog Category"])) frappe.model.meta.clear_cache("Blog Post") @@ -283,14 +277,8 @@ class TestPermissions(unittest.TestCase): def set_user_permission_doctypes(doctype, role, apply_user_permissions, user_permission_doctypes): user_permission_doctypes = None if not user_permission_doctypes else json.dumps(user_permission_doctypes) - frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=%(apply_user_permissions)s, - user_permission_doctypes=%(user_permission_doctypes)s - where parent=%(doctype)s and permlevel=0 - and `read`=1 and role=%(role)s""", { - "apply_user_permissions": apply_user_permissions, - "user_permission_doctypes": user_permission_doctypes, - "doctype": doctype, - "role": role - }) + + update(doctype, role, 0, 'apply_user_permissions', 1) + update(doctype, role, 0, 'user_permission_doctypes', user_permission_doctypes) frappe.clear_cache(doctype=doctype) diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 58f197c1d2..3be4295dfe 100755 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -7,6 +7,7 @@ import frappe, json from frappe import _dict import frappe.share from frappe.utils import cint +from frappe.permissions import get_roles, get_valid_perms class UserPermissions: """ @@ -69,10 +70,7 @@ class UserPermissions: def build_perm_map(self): """build map of permissions at level 0""" self.perm_map = {} - roles = self.get_roles() - for r in frappe.db.sql("""select * from tabDocPerm where docstatus=0 - and ifnull(permlevel,0)=0 - and role in ({roles})""".format(roles=", ".join(["%s"]*len(roles))), tuple(roles), as_dict=1): + for r in get_valid_perms(): dt = r['parent'] if not dt in self.perm_map: @@ -272,26 +270,6 @@ def add_system_manager(email, first_name=None, last_name=None, send_welcome_emai where name not in ("Administrator", "Guest", "All")""") user.add_roles(*roles) -def get_roles(user=None, with_standard=True): - """get roles of current user""" - if not user: - user = frappe.session.user - - if user=='Guest': - return ['Guest'] - - def get(): - return [r[0] for r in frappe.db.sql("""select role from tabUserRole - where parent=%s and role not in ('All', 'Guest')""", (user,))] + ['All', 'Guest'] - - roles = frappe.cache().hget("roles", user, get) - - # filter standard if required - if not with_standard: - roles = filter(lambda x: x not in ['All', 'Guest', 'Administrator'], roles) - - return roles - def get_enabled_system_users(): return frappe.db.sql("""select * from tabUser where user_type='System User' and enabled=1 and name not in ('Administrator', 'Guest')""", as_dict=1) @@ -344,7 +322,7 @@ def disable_users(limits=None): frappe.db.set_value("User", user, 'enabled', 0) from frappe.core.doctype.user.user import get_total_users - + if get_total_users() > cint(limits.get('users')): reset_simultaneous_sessions(cint(limits.get('users')))