From f609a478ae4863cd2d0108235035e20bd078ce03 Mon Sep 17 00:00:00 2001
From: Rushabh Mehta " + __("Loading") + "...");
+ this.body.html(" " + __("Loading") + "... "+__("Select Document Type or Role to start.")+"");
+ this.body.html(" "+__("Select Document Type or Role to start.")+" \
- " + __("Edit Role Permissions") + "\
- "+__("Help for User Permissions")+":
\
- \
-
'+
- "
' + txt + '
').appendTo(this.body); - }, - refresh: function() { - var me = this; - if(!me.filters.user) { - this.body.html(""+__("Loading")+"...
"); - return; - } - if(!me.get_user() && !me.get_doctype()) { - this.body.html(""+__("Select User or DocType to start.")+"
"); - return; - } - // get permissions - return frappe.call({ - module: "frappe.core", - page: "user_permissions", - method: "get_permissions", - args: { - parent: me.get_user(), - defkey: me.get_doctype(), - defvalue: me.get_user_permission() - }, - callback: function(r) { - me.render(r.message); - } - }); - }, - show_user_permissions_table: function() { - var me = this; - this.table = $("' - +__("These restrictions will apply for Document Types where 'Apply User Permissions' is checked for the permission rule and a field with this value is present.") - +'
').appendTo(this.body); - - $.each([[__("Allow User"), 150], [__("If Document Type"), 150], [__("Is"),150], ["", 50]], - function(i, col) { - $("').appendTo(this.body)) - .click(function() { - var d = new frappe.ui.Dialog({ - title: __("Add A New Restriction"), - fields: [ - {fieldtype:"Select", label:__("Allow User"), - options:me.options.users, reqd:1, fieldname:"user"}, - {fieldtype:"Select", label: __("If Document Type"), fieldname:"defkey", - options:me.get_link_names(), reqd:1}, - {fieldtype:"Link", label:__("Is"), fieldname:"defvalue", - options:'[Select]', reqd:1}, - {fieldtype:"Button", label: __("Add"), fieldname:"add"}, - ] - }); - if(me.get_user()) { - d.set_value("user", me.get_user()); - d.get_input("user").prop("disabled", true); - } - if(me.get_doctype()) { - d.set_value("defkey", me.get_doctype()); - d.get_input("defkey").prop("disabled", true); - } - if(me.get_user_permission()) { - d.set_value("defvalue", me.get_user_permission()); - d.get_input("defvalue").prop("disabled", true); - } - - d.fields_dict["defvalue"].get_query = function(txt) { - if(!d.get_value("defkey")) { - frappe.throw(__("Please select Document Type")); - } - - return { - doctype: d.get_value("defkey") - } - }; - - d.get_input("add").click(function() { - var args = d.get_values(); - if(!args) { - return; - } - frappe.call({ - module: "frappe.core", - page: "user_permissions", - method: "add", - args: args, - callback: function(r) { - if(r.exc) { - frappe.msgprint(__("Did not add")); - } else { - me.refresh(); - } - } - }) - d.hide(); - }); - d.show(); - }); - } -}) diff --git a/frappe/core/page/user_permissions/user_permissions.json b/frappe/core/page/user_permissions/user_permissions.json deleted file mode 100644 index ab831e1919..0000000000 --- a/frappe/core/page/user_permissions/user_permissions.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "content": null, - "creation": "2013-01-01 18:50:55", - "docstatus": 0, - "doctype": "Page", - "icon": "fa fa-user", - "idx": 1, - "modified": "2014-05-28 16:53:43.103533", - "modified_by": "Administrator", - "module": "Core", - "name": "user-permissions", - "owner": "Administrator", - "page_name": "user-permissions", - "roles": [], - "script": null, - "standard": "Yes", - "style": null, - "title": "User Permissions Manager" -} \ No newline at end of file diff --git a/frappe/core/page/user_permissions/user_permissions.py b/frappe/core/page/user_permissions/user_permissions.py deleted file mode 100644 index 98d7e90095..0000000000 --- a/frappe/core/page/user_permissions/user_permissions.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -from __future__ import unicode_literals -import frappe -from frappe import _ -import frappe.defaults -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 - -@frappe.whitelist() -def get_users_and_links(): - return { - "users": get_system_users(), - "link_fields": get_doctypes_for_user_permissions() - } - -@frappe.whitelist() -def get_permissions(parent=None, defkey=None, defvalue=None): - if defkey and not can_set_user_permissions(defkey, defvalue): - raise frappe.PermissionError - - conditions, values = _build_conditions(locals()) - - permissions = frappe.db.sql("""select name, parent, defkey, defvalue - from tabDefaultValue - where parent not in ('__default', '__global') - and substr(defkey,1,1)!='_' - and parenttype='User Permission' - {conditions} - order by parent, defkey""".format(conditions=conditions), values, as_dict=True) - - if not defkey: - out = [] - doctypes = get_doctypes_for_user_permissions() - for p in permissions: - if p.defkey in doctypes: - out.append(p) - permissions = out - - return permissions - -def _build_conditions(filters): - conditions = [] - values = {} - for key, value in filters.items(): - if filters.get(key): - conditions.append("and `{key}`=%({key})s".format(key=key)) - values[key] = value - - return "\n".join(conditions), values - -@frappe.whitelist() -def remove(user, name, 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) - - remove_user_permission(defkey, defvalue, user, name) - -@frappe.whitelist() -def add(user, 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) - - add_user_permission(defkey, defvalue, user, with_message=True) - -def get_doctypes_for_user_permissions(): - '''Get doctypes for the current user where user permissions are applicable''' - user_roles = frappe.get_roles() - - if "System Manager" in user_roles: - doctypes = set([p.parent for p in get_valid_perms()]) - else: - doctypes = set([p.parent for p in get_valid_perms() if p.set_user_permissions]) - - single_doctypes = set([d.name for d in frappe.get_all("DocType", {"issingle": 1})]) - - return sorted(doctypes.difference(single_doctypes)) - - -@frappe.whitelist() -def get_user_permissions_csv(): - out = [["User Permissions"], ["User", "Document Type", "Value"]] - out += [[a.parent, a.defkey, a.defvalue] for a in get_permissions()] - - csv = UnicodeWriter() - for row in out: - csv.writerow(row) - - frappe.response['result'] = str(csv.getvalue()) - frappe.response['type'] = 'csv' - frappe.response['doctype'] = "User Permissions" - -@frappe.whitelist() -def import_user_permissions(): - frappe.only_for("System Manager") - rows = read_csv_content_from_uploaded_file(ignore_encoding=True) - clear_default(parenttype="User Permission") - - if rows[0][0]!="User Permissions" and rows[1][0] != "User": - frappe.throw(frappe._("Please upload using the same template as download.")) - - for row in rows[2:]: - add_user_permission(row[1], row[2], row[0]) diff --git a/frappe/defaults.py b/frappe/defaults.py index b4c7ff6452..0e6e23ffdc 100644 --- a/frappe/defaults.py +++ b/frappe/defaults.py @@ -48,25 +48,10 @@ def is_a_user_permission_key(key): return ":" not in key and key != frappe.scrub(key) def get_user_permissions(user=None): - if not user: - user = frappe.session.user - - return build_user_permissions(user) - -def build_user_permissions(user): - out = frappe.cache().hget("user_permissions", user) - if out==None: - out = {} - for key, value in frappe.db.sql("""select defkey, ifnull(defvalue, '') as defvalue - from tabDefaultValue where parent=%s and parenttype='User Permission'""", (user,)): - out.setdefault(key, []).append(value) - - # add profile match - if user not in out.get("User", []): - out.setdefault("User", []).append(user) - - frappe.cache().hset("user_permissions", user, out) - return out + from frappe.core.doctype.user_permission.user_permission \ + import get_user_permissions as _get_user_permissions + '''Return frappe.core.doctype.user_permissions.user_permissions._get_user_permissions (kept for backward compatibility)''' + return _get_user_permissions(user) def get_defaults(user=None): globald = get_defaults_for() diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index 87e48b0450..ee7fffa242 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -70,7 +70,6 @@ def getdoctype(doctype, with_parent=False, cached_timestamp=None): if not docs: docs = get_meta_bundle(doctype) - frappe.response['user_permissions'] = get_user_permissions(docs) frappe.response['user_settings'] = get_user_settings(parent_dt or doctype) if cached_timestamp and docs[0].modified==cached_timestamp: @@ -102,16 +101,6 @@ def get_docinfo(doc=None, doctype=None, name=None): "rating": get_feedback_rating(doc.doctype, doc.name) } -def get_user_permissions(meta): - out = {} - all_user_permissions = frappe.defaults.get_user_permissions() - - for m in meta: - for df in m.get_fields_to_check_permissions(all_user_permissions): - out[df.options] = list(set(all_user_permissions[df.options])) - - return out - def get_attachments(dt, dn): return frappe.get_all("File", fields=["name", "file_name", "file_url", "is_private"], filters = {"attached_to_name": dn, "attached_to_doctype": dt}) diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py index cc5c394d9f..846d8101e6 100644 --- a/frappe/model/create_new.py +++ b/frappe/model/create_new.py @@ -11,6 +11,7 @@ from frappe.utils import nowdate, nowtime, now_datetime import frappe.defaults from frappe.model.db_schema import type_map import copy +from frappe.core.doctype.user_permission.user_permission import get_user_permissions def get_new_doc(doctype, parent_doc = None, parentfield = None, as_dict=False): if doctype not in frappe.local.new_doc_templates: @@ -47,7 +48,7 @@ def make_new_doc(doctype): return doc def set_user_and_static_default_values(doc): - user_permissions = frappe.defaults.get_user_permissions() + user_permissions = get_user_permissions() defaults = frappe.defaults.get_defaults() for df in doc.meta.get("fields"): @@ -103,7 +104,7 @@ def get_static_default_value(df, user_permissions): def set_dynamic_default_values(doc, parent_doc, parentfield): # these values should not be cached - user_permissions = frappe.defaults.get_user_permissions() + user_permissions = get_user_permissions() for df in frappe.get_meta(doc["doctype"]).get("fields"): if df.get("default"): diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index eeee7f4bf7..56e4cc343d 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -388,7 +388,7 @@ class DatabaseQuery(object): # apply user permissions? if role_permissions.get("apply_user_permissions", {}).get("read"): # get user permissions - user_permissions = frappe.defaults.get_user_permissions(self.user) + user_permissions = frappe.permissions.get_user_permissions(self.user) self.add_user_permissions(user_permissions, user_permission_doctypes=role_permissions.get("user_permission_doctypes").get("read")) diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 3bf49a5f6a..e242a48c88 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -11,7 +11,7 @@ from frappe.utils.file_manager import remove_all from frappe.utils.password import delete_all_passwords_for from frappe import _ from frappe.model.naming import revert_series_if_last -from frappe.utils.global_search import delete_for_document +from frappe.utils.global_search import delete_for_document def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False, flags=None, ignore_on_trash=False): @@ -158,8 +158,13 @@ def update_flags(doc, flags=None, ignore_permissions=False): def check_permission_and_not_submitted(doc): # permission - if not doc.flags.ignore_permissions and frappe.session.user!="Administrator" and (not doc.has_permission("delete") or (doc.doctype=="DocType" and not doc.custom)): - frappe.msgprint(_("User not allowed to delete {0}: {1}").format(doc.doctype, doc.name), raise_exception=True) + if (not doc.flags.ignore_permissions + and frappe.session.user!="Administrator" + and ( + not doc.has_permission("delete") + or (doc.doctype=="DocType" and not doc.custom))): + frappe.msgprint(_("User not allowed to delete {0}: {1}") + .format(doc.doctype, doc.name), raise_exception=frappe.PermissionError) # check if submitted if doc.docstatus == 1: diff --git a/frappe/patches.txt b/frappe/patches.txt index 8adf636701..3347ae8287 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -189,3 +189,4 @@ frappe.patches.v8_1.enable_allow_error_traceback_in_system_settings frappe.patches.v8_1.update_format_options_in_auto_email_report frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists frappe.patches.v8_5.delete_email_group_member_with_invalid_emails +frappe.patches.v8_x.update_user_permission diff --git a/frappe/patches/v8_x/__init__.py b/frappe/patches/v8_x/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/patches/v8_x/update_user_permission.py b/frappe/patches/v8_x/update_user_permission.py new file mode 100644 index 0000000000..4ceb26e945 --- /dev/null +++ b/frappe/patches/v8_x/update_user_permission.py @@ -0,0 +1,25 @@ +import frappe + +def execute(): + frappe.reload_doc('core', 'doctype', 'user_permission') + frappe.delete_doc('core', 'page', 'user-permissions') + for perm in frappe.db.sql(""" + select + name, parent, defkey, defvalue + from + tabDefaultValue + where + parent not in ('__default', '__global') + and + substr(defkey,1,1)!='_' + and + parenttype='User Permission' + """, as_dict=True): + frappe.get_doc(dict( + doctype='User Permission', + user=perm.parent, + allow=perm.defkey, + for_value=perm.defvalue + )).insert(ignore_permissions = True) + + frappe.db.sql('delete from tabDefaultValue where parenttype="User Permission"') diff --git a/frappe/permissions.py b/frappe/permissions.py index 13da62d366..29f223d08e 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -7,7 +7,6 @@ import frappe, copy, json from frappe import _, msgprint from frappe.utils import cint import frappe.share - rights = ("read", "write", "create", "delete", "submit", "cancel", "amend", "print", "email", "report", "import", "export", "set_user_permissions", "share") @@ -25,6 +24,9 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None): """ if not user: user = frappe.session.user + if verbose: + print('--- Checking for {0} {1} ---'.format(doctype, doc.name if doc else '-')) + if frappe.is_table(doctype): if verbose: print("Table type, always true") return True @@ -40,7 +42,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None): return False if user=="Administrator": - if verbose: print("Administrator") + if verbose: print("Allowing Administrator") return True def false_if_not_shared(): @@ -210,7 +212,10 @@ def get_role_permissions(meta, user=None, verbose=False): if p.user_permission_doctypes: # set user_permission_doctypes in perms - user_permission_doctypes = json.loads(p.user_permission_doctypes) + try: + user_permission_doctypes = json.loads(p.user_permission_doctypes) + except ValueError: + user_permission_doctypes = [] else: user_permission_doctypes = get_linked_doctypes(meta.name) @@ -247,8 +252,12 @@ def get_role_permissions(meta, user=None, verbose=False): return frappe.local.role_permissions[cache_key] +def get_user_permissions(user): + from frappe.core.doctype.user_permission.user_permission import get_user_permissions + return get_user_permissions(user) + def user_has_permission(doc, verbose=True, user=None, user_permission_doctypes=None): - from frappe.defaults import get_user_permissions + from frappe.core.doctype.user_permission.user_permission import get_user_permissions user_permissions = get_user_permissions(user) user_permission_doctypes = get_user_permission_doctypes(user_permission_doctypes, user_permissions) @@ -258,6 +267,10 @@ def user_has_permission(doc, verbose=True, user=None, user_permission_doctypes=N messages = {} + if not user_permission_doctypes: + # no doctypes restricted + end_result = True + # check multiple sets of user_permission_doctypes using OR condition for doctypes in user_permission_doctypes: result = True @@ -309,9 +322,9 @@ def has_controller_permissions(doc, ptype, user=None): def get_doctypes_with_read(): return list(set([p.parent for p in get_valid_perms()])) -def get_valid_perms(doctype=None): +def get_valid_perms(doctype=None, user=None): '''Get valid permissions for the current user from DocPerm and Custom DocPerm''' - roles = get_roles() + roles = get_roles(user) perms = get_perms_for(roles) custom_perms = get_perms_for(roles, 'Custom DocPerm') @@ -360,7 +373,8 @@ def get_roles(user=None, with_standard=True): def get_perms_for(roles, perm_doctype='DocPerm'): '''Get perms for given roles''' - return frappe.db.sql("""select * from `tab{doctype}` where docstatus=0 + 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) @@ -386,22 +400,28 @@ def set_user_permission_if_allowed(doctype, name, user, with_message=False): if get_role_permissions(frappe.get_meta(doctype), user).set_user_permissions!=1: 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, []): +def add_user_permission(doctype, name, user, apply=False): + '''Add user permission''' + from frappe.core.doctype.user_permission.user_permission import get_user_permissions + if name not in get_user_permissions(user).get(doctype, []): if not frappe.db.exists(doctype, name): frappe.throw(_("{0} {1} not found").format(_(doctype), name), frappe.DoesNotExistError) - frappe.defaults.add_default(doctype, name, user, "User Permission") - elif with_message: - msgprint(_("Permission already set")) + frappe.get_doc(dict( + doctype='User Permission', + user=user, + allow=doctype, + for_value=name, + apply_for_all_roles=apply + )).insert() -def remove_user_permission(doctype, name, user, default_value_name=None): - frappe.defaults.clear_default(key=doctype, value=name, parent=user, parenttype="User Permission", - name=default_value_name) +def remove_user_permission(doctype, name, user): + user_permission_name = frappe.db.get_value('User Permission', + dict(user=user, allow=doctype, for_value=name)) + frappe.delete_doc('User Permission', user_permission_name) def clear_user_permissions_for_doctype(doctype): - frappe.defaults.clear_default(parenttype="User Permission", key=doctype) + frappe.cache().delete_value('user_permissions') def can_import(doctype, raise_exception=False): if not ("System Manager" in frappe.get_roles() or has_permission(doctype, "import")): @@ -426,9 +446,10 @@ def apply_user_permissions(doctype, ptype, user=None): def get_user_permission_doctypes(user_permission_doctypes, user_permissions): """returns a list of list like [["User", "Blog Post"], ["User"]]""" - if cint(frappe.db.get_single_value("System Settings", "ignore_user_permissions_if_missing")): + if cint(frappe.get_system_settings('ignore_user_permissions_if_missing')): # select those user permission doctypes for which user permissions exist! - user_permission_doctypes = [list(set(doctypes).intersection(set(user_permissions.keys()))) + user_permission_doctypes = [ + list(set(doctypes).intersection(set(user_permissions.keys()))) for doctypes in user_permission_doctypes] if len(user_permission_doctypes) > 1: @@ -452,6 +473,22 @@ def get_user_permission_doctypes(user_permission_doctypes, user_permissions): return user_permission_doctypes +def update_permission_property(doctype, role, permlevel, ptype, value=None, validate=True): + '''Update a property in Custom Perm''' + from frappe.core.doctype.doctype.doctype import validate_permissions_for_doctype + out = setup_custom_perms(doctype) + + name = frappe.get_value('Custom DocPerm', dict(parent=doctype, role=role, + permlevel=permlevel)) + + frappe.db.sql(""" + update `tabCustom DocPerm` + set `{0}`=%s where name=%s""".format(ptype), (value, name)) + if validate: + validate_permissions_for_doctype(doctype) + + return out + 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)): diff --git a/frappe/public/js/frappe/defaults.js b/frappe/public/js/frappe/defaults.js index 24ba5e630e..570ae61e2a 100644 --- a/frappe/public/js/frappe/defaults.js +++ b/frappe/public/js/frappe/defaults.js @@ -77,10 +77,6 @@ frappe.defaults = { }, get_user_permissions: function() { - return frappe.defaults.user_permissions; + return frappe.boot.user_permissions; }, - set_user_permissions: function(user_permissions) { - if(!user_permissions) return; - frappe.defaults.user_permissions = $.extend(frappe.defaults.user_permissions || {}, user_permissions); - } } diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 05facf346d..a7024a9fb7 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -599,9 +599,9 @@ frappe.views.ListView = frappe.ui.BaseList.extend({ }, true); } if (frappe.model.can_set_user_permissions(this.doctype)) { - this.page.add_menu_item(__('User Permissions Manager'), function () { - frappe.set_route('user-permissions', { - doctype: me.doctype + this.page.add_menu_item(__('User Permissions'), function () { + frappe.set_route('List', 'User Permission', { + allow: me.doctype }); }, true); } diff --git a/frappe/public/js/frappe/model/create_new.js b/frappe/public/js/frappe/model/create_new.js index 04496c6238..a25c3e70ca 100644 --- a/frappe/public/js/frappe/model/create_new.js +++ b/frappe/public/js/frappe/model/create_new.js @@ -127,8 +127,10 @@ $.extend(frappe.model, { var user_default = ""; var user_permissions = frappe.defaults.get_user_permissions(); var meta = frappe.get_meta(doc.doctype); - var has_user_permissions = (df.fieldtype==="Link" && user_permissions - && df.ignore_user_permissions != 1 && user_permissions[df.options]); + var has_user_permissions = (df.fieldtype==="Link" + && user_permissions + && df.ignore_user_permissions != 1 + && user_permissions[df.options]); // don't set defaults for "User" link field using User Permissions! if (df.fieldtype==="Link" && df.options!=="User") { diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index adb2e845a6..7b22c5fd47 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -112,7 +112,6 @@ $.extend(frappe.model, { localStorage["_doctype:" + doctype] = JSON.stringify(r.docs); } frappe.model.init_doctype(doctype); - frappe.defaults.set_user_permissions(r.user_permissions); if(r.user_settings) { // remember filters and other settings from last view diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index b3762fea6f..7e0bc14a13 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -103,7 +103,7 @@ frappe.views.QueryReport = Class.extend({ doctype: "Report", name: me.report_name }; - frappe.set_route("user-permissions"); + frappe.set_route('List', 'User Permission'); }, true); } diff --git a/frappe/public/js/frappe/views/reports/reportview.js b/frappe/public/js/frappe/views/reports/reportview.js index 93d6a1f1aa..b7fd287b02 100644 --- a/frappe/public/js/frappe/views/reports/reportview.js +++ b/frappe/public/js/frappe/views/reports/reportview.js @@ -821,12 +821,12 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({ make_user_permissions: function() { var me = this; if(this.docname && frappe.model.can_set_user_permissions("Report")) { - this.page.add_menu_item(__("User Permissions Manager"), function() { + this.page.add_menu_item(__("User Permissions"), function() { frappe.route_options = { doctype: "Report", name: me.docname }; - frappe.set_route("user-permissions"); + frappe.set_route('List', 'User Permission'); }, true); } }, diff --git a/frappe/test_runner.py b/frappe/test_runner.py index a50febabf3..c4fa2f6f47 100644 --- a/frappe/test_runner.py +++ b/frappe/test_runner.py @@ -266,12 +266,12 @@ def make_test_records_for_doctype(doctype, verbose=0, force=False): frappe.local.test_objects[doctype] += test_module._make_test_records(verbose) elif hasattr(test_module, "test_records"): - frappe.local.test_objects[doctype] += make_test_objects(doctype, test_module.test_records, verbose) + frappe.local.test_objects[doctype] += make_test_objects(doctype, test_module.test_records, verbose, force) else: test_records = frappe.get_test_records(doctype) if test_records: - frappe.local.test_objects[doctype] += make_test_objects(doctype, test_records, verbose) + frappe.local.test_objects[doctype] += make_test_objects(doctype, test_records, verbose, force) elif verbose: print_mandatory_fields(doctype) diff --git a/frappe/tests/test_permissions.py b/frappe/tests/test_permissions.py index 6ad0e84f07..d54c484eba 100644 --- a/frappe/tests/test_permissions.py +++ b/frappe/tests/test_permissions.py @@ -9,9 +9,11 @@ import frappe.defaults import unittest 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.permissions import (add_user_permission, remove_user_permission, + clear_user_permissions_for_doctype, get_doc_permissions, add_permission, + get_valid_perms) from frappe.core.page.permission_manager.permission_manager import update, reset +from frappe.test_runner import make_test_records_for_doctype test_records = frappe.get_test_records('Blog Post') @@ -24,6 +26,7 @@ class TestPermissions(unittest.TestCase): user = frappe.get_doc("User", "test1@example.com") user.add_roles("Website Manager") + user.add_roles("System Manager") user = frappe.get_doc("User", "test2@example.com") user.add_roles("Blogger") @@ -36,6 +39,8 @@ class TestPermissions(unittest.TestCase): reset('Contact') reset('Salutation') + frappe.db.sql('delete from `tabUser Permission`') + self.set_ignore_user_permissions_if_missing(0) frappe.set_user("test1@example.com") @@ -78,7 +83,7 @@ class TestPermissions(unittest.TestCase): def test_user_permissions_in_doc(self): self.set_user_permission_doctypes(["Blog Category"]) - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", + add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") frappe.set_user("test2@example.com") @@ -94,7 +99,7 @@ class TestPermissions(unittest.TestCase): def test_user_permissions_in_report(self): self.set_user_permission_doctypes(["Blog Category"]) - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") + add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") frappe.set_user("test2@example.com") names = [d.name for d in frappe.get_list("Blog Post", fields=["name", "blog_category"])] @@ -103,7 +108,7 @@ class TestPermissions(unittest.TestCase): self.assertFalse("-test-blog-post" in names) def test_default_values(self): - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") + add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") frappe.set_user("test2@example.com") doc = frappe.new_doc("Blog Post") @@ -139,14 +144,14 @@ class TestPermissions(unittest.TestCase): def test_set_user_permissions(self): frappe.set_user("test1@example.com") - add("test2@example.com", "Blog Post", "-test-blog-post") + add_user_permission("Blog Post", "-test-blog-post", "test2@example.com") def test_not_allowed_to_set_user_permissions(self): frappe.set_user("test2@example.com") # this user can't add user permissions - self.assertRaises(frappe.PermissionError, add, - "test2@example.com", "Blog Post", "-test-blog-post") + self.assertRaises(frappe.PermissionError, add_user_permission, + "Blog Post", "-test-blog-post", "test2@example.com") def test_read_if_explicit_user_permissions_are_set(self): self.set_user_permission_doctypes(["Blog Post"]) @@ -165,13 +170,12 @@ class TestPermissions(unittest.TestCase): def test_not_allowed_to_remove_user_permissions(self): self.test_set_user_permissions() - defname = get_permissions("test2@example.com", "Blog Post", "-test-blog-post")[0].name frappe.set_user("test2@example.com") # user cannot remove their own user permissions - self.assertRaises(frappe.PermissionError, remove, - "test2@example.com", defname, "Blog Post", "-test-blog-post") + self.assertRaises(frappe.PermissionError, remove_user_permission, + "Blog Post", "-test-blog-post", "test2@example.com") def test_user_permissions_based_on_blogger(self): frappe.set_user("test2@example.com") @@ -181,7 +185,7 @@ class TestPermissions(unittest.TestCase): self.set_user_permission_doctypes(["Blog Post"]) frappe.set_user("test1@example.com") - add("test2@example.com", "Blog Post", "-test-blog-post") + add_user_permission("Blog Post", "-test-blog-post", "test2@example.com") frappe.set_user("test2@example.com") doc = frappe.get_doc("Blog Post", "-test-blog-post-1") @@ -199,9 +203,9 @@ class TestPermissions(unittest.TestCase): blog_post.get_field("title").set_only_once = 0 def test_user_permission_doctypes(self): - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", + add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") - frappe.permissions.add_user_permission("Blogger", "_Test Blogger 1", + add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com") frappe.set_user("test2@example.com") @@ -221,9 +225,9 @@ class TestPermissions(unittest.TestCase): def if_owner_setup(self): update('Blog Post', 'Blogger', 0, 'if_owner', 1) - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category 1", + add_user_permission("Blog Category", "_Test Blog Category 1", "test2@example.com") - frappe.permissions.add_user_permission("Blogger", "_Test Blogger 1", + add_user_permission("Blogger", "_Test Blogger 1", "test2@example.com") update('Blog Post', 'Blogger', 0, 'user_permission_doctypes', json.dumps(["Blog Category"])) @@ -231,11 +235,13 @@ class TestPermissions(unittest.TestCase): frappe.model.meta.clear_cache("Blog Post") def set_user_permission_doctypes(self, user_permission_doctypes): - set_user_permission_doctypes(doctype="Blog Post", role="Blogger", + set_user_permission_doctypes(["Blog Post"], role="Blogger", apply_user_permissions=1, user_permission_doctypes=user_permission_doctypes) def test_insert_if_owner_with_user_permissions(self): """If `If Owner` is checked for a Role, check if that document is allowed to be read, updated, submitted, etc. except be created, even if the document is restricted based on User Permissions.""" + frappe.delete_doc('Blog Post', '-test-blog-post-title') + self.set_user_permission_doctypes(["Blog Category"]) self.if_owner_setup() @@ -252,7 +258,7 @@ class TestPermissions(unittest.TestCase): self.assertRaises(frappe.PermissionError, doc.insert) frappe.set_user("Administrator") - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category", + add_user_permission("Blog Category", "_Test Blog Category", "test2@example.com") frappe.set_user("test2@example.com") @@ -273,8 +279,8 @@ class TestPermissions(unittest.TestCase): self.set_user_permission_doctypes(['Blog Category', 'Blog Post', 'Blogger']) frappe.set_user("Administrator") - frappe.permissions.add_user_permission("Blog Category", "_Test Blog Category", - "test2@example.com") + # add_user_permission("Blog Category", "_Test Blog Category", + # "test2@example.com") frappe.set_user("test2@example.com") doc = frappe.get_doc({ @@ -294,33 +300,73 @@ class TestPermissions(unittest.TestCase): self.assertTrue(doc.has_permission("write")) def test_strict_user_permissions(self): - """If `Strict User Permissions` is checked in System Settings, show records even if User Permissions are missing for a linked doctype""" - set_user_permission_doctypes(doctype="Contact", role="Sales User", + """If `Strict User Permissions` is checked in System Settings, + show records even if User Permissions are missing for a linked + doctype""" + + frappe.set_user("Administrator") + frappe.db.sql('delete from tabContact') + make_test_records_for_doctype('Contact', force=True) + + set_user_permission_doctypes("Contact", role="Sales User", apply_user_permissions=1, user_permission_doctypes=['Salutation']) - set_user_permission_doctypes(doctype="Salutation", role="All", + set_user_permission_doctypes("Salutation", role="All", apply_user_permissions=1, user_permission_doctypes=['Salutation']) - frappe.set_user("Administrator") - frappe.permissions.add_user_permission("Salutation", "Mr", "test3@example.com") + add_user_permission("Salutation", "Mr", "test3@example.com") self.set_strict_user_permissions(0) frappe.set_user("test3@example.com") - self.assertEquals(len(frappe.get_list("Contact")),2) + self.assertEquals(len(frappe.get_list("Contact")), 2) frappe.set_user("Administrator") self.set_strict_user_permissions(1) frappe.set_user("test3@example.com") - self.assertTrue(len(frappe.get_list("Contact")),1) + self.assertTrue(len(frappe.get_list("Contact")), 1) frappe.set_user("Administrator") self.set_strict_user_permissions(0) + def test_automatic_apply_user_permissions(self): + '''Test user permissions are automatically applied when a user permission + is created''' + # create a user + frappe.get_doc(dict(doctype='User', email='test_user_perm@example.com', + first_name='tester')).insert(ignore_if_duplicate=True) + frappe.get_doc(dict(doctype='Role', role_name='Test Role User Perm') + ).insert(ignore_if_duplicate=True) + + # add a permission for event + add_permission('DocType', 'Test Role User Perm') + frappe.get_doc('User', 'test_user_perm@example.com').add_roles('Test Role User Perm') -def set_user_permission_doctypes(doctype, role, apply_user_permissions, user_permission_doctypes): + + # add user permission + add_user_permission('Module Def', 'Core', 'test_user_perm@example.com', True) + + # check if user permission is applied in the new role + _perm = None + for perm in get_valid_perms('DocType', 'test_user_perm@example.com'): + if perm.role == 'Test Role User Perm': + _perm = perm + + self.assertEqual(_perm.apply_user_permissions, 1) + + # restrict by module + self.assertTrue('Module Def' in json.loads(_perm.user_permission_doctypes)) + + +def set_user_permission_doctypes(doctypes, role, apply_user_permissions, + user_permission_doctypes): user_permission_doctypes = None if not user_permission_doctypes else json.dumps(user_permission_doctypes) - update(doctype, role, 0, 'apply_user_permissions', 1) - update(doctype, role, 0, 'user_permission_doctypes', user_permission_doctypes) + if isinstance(doctypes, basestring): + doctypes = [doctypes] + + for doctype in doctypes: + update(doctype, role, 0, 'apply_user_permissions', 1) + update(doctype, role, 0, 'user_permission_doctypes', + user_permission_doctypes) - frappe.clear_cache(doctype=doctype) + frappe.clear_cache(doctype=doctype)