* [refactor] user permissions * [fix] tests * [ux] user-permissions * [minor] cleanup system settings * [minor] end progressversion-14
@@ -17,6 +17,7 @@ from frappe.utils.change_log import get_versions | |||
from frappe.translate import get_lang_dict | |||
from frappe.email.inbox import get_email_accounts | |||
from frappe.core.doctype.feedback_trigger.feedback_trigger import get_enabled_feedback_trigger | |||
from frappe.core.doctype.user_permission.user_permission import get_user_permissions | |||
def get_bootinfo(): | |||
"""build and return boot info""" | |||
@@ -30,6 +31,7 @@ def get_bootinfo(): | |||
# system info | |||
bootinfo.sysdefaults = frappe.defaults.get_defaults() | |||
bootinfo.user_permissions = get_user_permissions() | |||
bootinfo.server_date = frappe.utils.nowdate() | |||
if frappe.session['user'] != 'Guest': | |||
@@ -3,7 +3,6 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
import frappe.defaults | |||
import frappe.permissions | |||
from frappe.model.document import Document | |||
from frappe.utils import get_fullname | |||
@@ -68,7 +67,7 @@ def get_feed_match_conditions(user=None, force=True): | |||
conditions = ['`tabCommunication`.owner="{user}" or `tabCommunication`.reference_owner="{user}"'.format(user=frappe.db.escape(user))] | |||
user_permissions = frappe.defaults.get_user_permissions(user) | |||
user_permissions = frappe.permissions.get_user_permissions(user) | |||
can_read = frappe.get_user().get_can_read() | |||
can_read_doctypes = ['"{}"'.format(doctype) for doctype in | |||
@@ -527,7 +527,7 @@ | |||
"bold": 0, | |||
"collapsible": 1, | |||
"columns": 0, | |||
"fieldname": "security", | |||
"fieldname": "permissions", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
@@ -536,10 +536,11 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Security", | |||
"label": "Permissions", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
@@ -556,10 +557,9 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "06:00", | |||
"description": "Session Expiry in Hours e.g. 06:00", | |||
"fieldname": "session_expiry", | |||
"fieldtype": "Data", | |||
"description": "If Apply User Permissions is checked for Report DocType but no User Permissions are defined for Report for a User, then all Reports are shown to that User", | |||
"fieldname": "ignore_user_permissions_if_missing", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -567,11 +567,11 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Session Expiry", | |||
"label": "Ignore User Permissions If Missing", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
@@ -588,10 +588,10 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "720:00", | |||
"description": "In Hours", | |||
"fieldname": "session_expiry_mobile", | |||
"fieldtype": "Data", | |||
"default": "0", | |||
"description": "If Apply Strict User Permission is checked and User Permission is defined for a DocType for a User, then all the documents where value of the link is blank, will not be shown to that User", | |||
"fieldname": "apply_strict_user_permissions", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -599,7 +599,7 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Session Expiry Mobile", | |||
"label": "Apply Strict User Permissions", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -614,16 +614,45 @@ | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 1, | |||
"columns": 0, | |||
"fieldname": "security", | |||
"fieldtype": "Section Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Security", | |||
"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, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "0", | |||
"description": "If enabled, the password strength will be enforced based on the Minimum Password Score value. A value of 2 being medium strong and 4 being very strong.", | |||
"fieldname": "enable_password_policy", | |||
"fieldtype": "Check", | |||
"default": "06:00", | |||
"description": "Session Expiry in Hours e.g. 06:00", | |||
"fieldname": "session_expiry", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -631,11 +660,11 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Enable Password Policy", | |||
"label": "Session Expiry", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
@@ -652,10 +681,10 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "2", | |||
"depends_on": "eval:doc.enable_password_policy==1", | |||
"fieldname": "minimum_password_score", | |||
"fieldtype": "Select", | |||
"default": "720:00", | |||
"description": "In Hours", | |||
"fieldname": "session_expiry_mobile", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -663,10 +692,9 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Minimum Password Score", | |||
"label": "Session Expiry Mobile", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "2\n4", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
@@ -685,8 +713,10 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "column_break_13", | |||
"fieldtype": "Column Break", | |||
"default": "0", | |||
"description": "If enabled, the password strength will be enforced based on the Minimum Password Score value. A value of 2 being medium strong and 4 being very strong.", | |||
"fieldname": "enable_password_policy", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -694,6 +724,7 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Enable Password Policy", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -714,9 +745,10 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Note: Multiple sessions will be allowed in case of mobile device", | |||
"fieldname": "deny_multiple_sessions", | |||
"fieldtype": "Check", | |||
"default": "2", | |||
"depends_on": "eval:doc.enable_password_policy==1", | |||
"fieldname": "minimum_password_score", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -724,9 +756,10 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Allow only one session per user", | |||
"label": "Minimum Password Score", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "2\n4", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
@@ -745,9 +778,8 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "If Apply User Permissions is checked for Report DocType but no User Permissions are defined for Report for a User, then all Reports are shown to that User", | |||
"fieldname": "ignore_user_permissions_if_missing", | |||
"fieldtype": "Check", | |||
"fieldname": "column_break_13", | |||
"fieldtype": "Column Break", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
@@ -755,7 +787,6 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Ignore User Permissions If Missing", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -776,9 +807,8 @@ | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "0", | |||
"description": "If Apply Strict User Permission is checked and User Permission is defined for a DocType for a User, then all the documents where value of the link is blank, will not be shown to that User", | |||
"fieldname": "apply_strict_user_permissions", | |||
"description": "Note: Multiple sessions will be allowed in case of mobile device", | |||
"fieldname": "deny_multiple_sessions", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
@@ -787,7 +817,7 @@ | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Apply Strict User Permissions", | |||
"label": "Allow only one session per user", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
@@ -997,7 +1027,7 @@ | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2017-06-23 07:48:10.453011", | |||
"modified": "2017-07-20 22:57:56.466867", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "System Settings", | |||
@@ -1032,4 +1062,4 @@ | |||
"sort_order": "ASC", | |||
"track_changes": 1, | |||
"track_seen": 0 | |||
} | |||
} |
@@ -35,6 +35,7 @@ class SystemSettings(Document): | |||
frappe.cache().delete_value('system_settings') | |||
frappe.cache().delete_value('time_zone') | |||
frappe.local.system_settings = {} | |||
@frappe.whitelist() | |||
def load(): | |||
@@ -0,0 +1,23 @@ | |||
/* eslint-disable */ | |||
// rename this file from _test_[name] to test_[name] to activate | |||
// and remove above this line | |||
QUnit.test("test: System Settings", function (assert) { | |||
let done = assert.async(); | |||
// number of asserts | |||
assert.expect(1); | |||
frappe.run_serially('System Settings', [ | |||
// insert a new System Settings | |||
() => frappe.tests.make([ | |||
// values to be set | |||
{key: 'value'} | |||
]), | |||
() => { | |||
assert.equal(cur_frm.doc.key, 'value'); | |||
}, | |||
() => done() | |||
]); | |||
}); |
@@ -59,9 +59,13 @@ frappe.ui.form.on('User', { | |||
frappe.route_options = { | |||
"user": doc.name | |||
}; | |||
frappe.set_route("user-permissions"); | |||
frappe.set_route('List', 'User Permission'); | |||
}, null, "btn-default") | |||
frm.add_custom_button(__('View Permitted Documents'), | |||
() => frappe.set_route('query-report', 'Permitted Documents For User', | |||
{user: frm.doc.name})); | |||
frm.toggle_display(['sb1', 'sb3', 'modules_access'], true); | |||
} | |||
@@ -0,0 +1,23 @@ | |||
/* eslint-disable */ | |||
// rename this file from _test_[name] to test_[name] to activate | |||
// and remove above this line | |||
QUnit.test("test: User Permission", function (assert) { | |||
let done = assert.async(); | |||
// number of asserts | |||
assert.expect(1); | |||
frappe.run_serially('User Permission', [ | |||
// insert a new User Permission | |||
() => frappe.tests.make([ | |||
// values to be set | |||
{key: 'value'} | |||
]), | |||
() => { | |||
assert.equal(cur_frm.doc.key, 'value'); | |||
}, | |||
() => done() | |||
]); | |||
}); |
@@ -0,0 +1,10 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2017, Frappe Technologies and Contributors | |||
# See license.txt | |||
from __future__ import unicode_literals | |||
#import frappe | |||
import unittest | |||
class TestUserPermission(unittest.TestCase): | |||
pass |
@@ -0,0 +1,10 @@ | |||
// Copyright (c) 2017, Frappe Technologies and contributors | |||
// For license information, please see license.txt | |||
frappe.ui.form.on('User Permission', { | |||
refresh: function(frm) { | |||
frm.add_custom_button(__('View Permitted Documents'), | |||
() => frappe.set_route('query-report', 'Permitted Documents For User', | |||
{user: frm.doc.user})); | |||
} | |||
}); |
@@ -0,0 +1,188 @@ | |||
{ | |||
"allow_copy": 0, | |||
"allow_guest_to_view": 0, | |||
"allow_import": 0, | |||
"allow_rename": 0, | |||
"beta": 0, | |||
"creation": "2017-07-17 14:25:27.881871", | |||
"custom": 0, | |||
"docstatus": 0, | |||
"doctype": "DocType", | |||
"document_type": "", | |||
"editable_grid": 1, | |||
"engine": "InnoDB", | |||
"fields": [ | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "user", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 1, | |||
"label": "User", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "User", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "allow", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 1, | |||
"label": "Allow", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "DocType", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "for_value", | |||
"fieldtype": "Dynamic Link", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 1, | |||
"in_standard_filter": 1, | |||
"label": "For Value", | |||
"length": 0, | |||
"no_copy": 0, | |||
"options": "allow", | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"remember_last_selected_value": 0, | |||
"report_hide": 0, | |||
"reqd": 1, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_bulk_edit": 0, | |||
"allow_on_submit": 0, | |||
"bold": 1, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "1", | |||
"description": "If you un-check this, you will have to apply manually for each Role + Document Type combination", | |||
"fieldname": "apply_for_all_roles", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_global_search": 0, | |||
"in_list_view": 0, | |||
"in_standard_filter": 0, | |||
"label": "Apply for all Roles for this User", | |||
"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 | |||
} | |||
], | |||
"has_web_view": 0, | |||
"hide_heading": 0, | |||
"hide_toolbar": 0, | |||
"idx": 0, | |||
"image_view": 0, | |||
"in_create": 0, | |||
"is_submittable": 0, | |||
"issingle": 0, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2017-07-27 22:55:58.647315", | |||
"modified_by": "Administrator", | |||
"module": "Core", | |||
"name": "User Permission", | |||
"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, | |||
"permlevel": 0, | |||
"print": 1, | |||
"read": 1, | |||
"report": 1, | |||
"role": "System Manager", | |||
"set_user_permissions": 0, | |||
"share": 1, | |||
"submit": 0, | |||
"write": 1 | |||
} | |||
], | |||
"quick_entry": 1, | |||
"read_only": 0, | |||
"read_only_onload": 0, | |||
"show_name_in_global_search": 0, | |||
"sort_field": "modified", | |||
"sort_order": "DESC", | |||
"title_field": "user", | |||
"track_changes": 1, | |||
"track_seen": 0 | |||
} |
@@ -0,0 +1,80 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright (c) 2017, Frappe Technologies and contributors | |||
# For license information, please see license.txt | |||
from __future__ import unicode_literals | |||
import frappe, json | |||
from frappe.model.document import Document | |||
from frappe.permissions import (get_valid_perms, update_permission_property) | |||
from frappe import _ | |||
class UserPermission(Document): | |||
def on_update(self): | |||
frappe.cache().delete_value('user_permissions') | |||
if self.apply_for_all_roles: | |||
self.apply_user_permissions_to_all_roles() | |||
def apply_user_permissions_to_all_roles(self): | |||
# add apply user permissions for all roles that | |||
# for this doctype | |||
def show_progress(i, l): | |||
if l > 2: | |||
frappe.publish_realtime("progress", | |||
dict(progress=[i, l], title=_('Updating...')), | |||
user=frappe.session.user) | |||
roles = frappe.get_roles(self.user) | |||
linked = frappe.db.sql('''select distinct parent from tabDocField | |||
where fieldtype="Link" and options=%s''', self.allow) | |||
for i, link in enumerate(linked): | |||
doctype = link[0] | |||
for perm in get_valid_perms(doctype, self.user): | |||
# if the role is applicable to the user | |||
show_progress(i+1, len(linked)) | |||
if perm.role in roles: | |||
if not perm.apply_user_permissions: | |||
update_permission_property(doctype, perm.role, 0, | |||
'apply_user_permissions', '1') | |||
try: | |||
user_permission_doctypes = json.loads(perm.user_permission_doctypes or '[]') | |||
except ValueError: | |||
user_permission_doctypes = [] | |||
if self.allow not in user_permission_doctypes: | |||
user_permission_doctypes.append(self.allow) | |||
update_permission_property(doctype, perm.role, 0, | |||
'user_permission_doctypes', json.dumps(user_permission_doctypes), validate=False) | |||
show_progress(len(linked), len(linked)) | |||
def on_trash(self): # pylint: disable=no-self-use | |||
frappe.cache().delete_value('user_permissions') | |||
def get_user_permissions(user=None): | |||
'''Get all users permissions for the user as a dict of doctype''' | |||
if not user: | |||
user = frappe.session.user | |||
out = frappe.cache().hget("user_permissions", user) | |||
if not out: | |||
out = {} | |||
try: | |||
for perm in frappe.get_all('User Permission', | |||
fields=['allow', 'for_value'], filters=dict(user=user)): | |||
out.setdefault(perm.allow, []).append(perm.for_value) | |||
# add profile match | |||
if user not in out.get("User", []): | |||
out.setdefault("User", []).append(user) | |||
frappe.cache().hset("user_permissions", user, out) | |||
except frappe.SQLError, e: | |||
if e.args[0]==1146: | |||
# called from patch | |||
pass | |||
return out |
@@ -21,6 +21,7 @@ frappe.pages['permission-manager'].refresh = function(wrapper) { | |||
frappe.PermissionEngine = Class.extend({ | |||
init: function(wrapper) { | |||
this.wrapper = wrapper; | |||
this.page = wrapper.page; | |||
this.body = $(this.wrapper).find(".perm-engine"); | |||
this.make(); | |||
this.refresh(); | |||
@@ -55,6 +56,10 @@ frappe.PermissionEngine = Class.extend({ | |||
.change(function() { | |||
me.refresh(); | |||
}); | |||
this.page.add_inner_button(__('Set User Permissions'), () => { | |||
return frappe.set_route('List', 'User Permission'); | |||
}); | |||
this.set_from_route(); | |||
}, | |||
set_from_route: function() { | |||
@@ -133,11 +138,11 @@ frappe.PermissionEngine = Class.extend({ | |||
refresh: function() { | |||
var me = this; | |||
if(!me.doctype_select) { | |||
this.body.html("<p class='text-muted'>" + __("Loading") + "...</div>"); | |||
this.body.html("<p class='text-muted'>" + __("Loading") + "...</p>"); | |||
return; | |||
} | |||
if(!me.get_doctype() && !me.get_role()) { | |||
this.body.html("<p class='text-muted'>"+__("Select Document Type or Role to start.")+"</div>"); | |||
this.body.html("<p class='text-muted'>"+__("Select Document Type or Role to start.")+"</p>"); | |||
return; | |||
} | |||
// get permissions | |||
@@ -247,10 +252,13 @@ frappe.PermissionEngine = Class.extend({ | |||
setup_user_permissions: function(d, role_cell) { | |||
var me = this; | |||
d.help = frappe.render('<ul class="user-permission-help small hidden" style="margin-left: -10px;">\ | |||
<li style="margin-top: 7px;"><a class="show-user-permission-doctypes grey">{%= __("Select Document Types") %}</a></li>\ | |||
<li style="margin-top: 3px;"><a class="show-user-permissions grey">{%= __("Show User Permissions") %}</a></li>\ | |||
</ul>', {}); | |||
d.help = `<ul class="user-permission-help small hidden" | |||
style="margin-left: -10px;"> | |||
<li style="margin-top: 7px;"><a class="show-user-permission-doctypes"> | |||
${__("Select Document Types")}</a></li> | |||
<li style="margin-top: 3px;"><a class="show-user-permissions"> | |||
${__("Show User Permissions")}</a></li> | |||
</ul>`; | |||
var checkbox = this.add_check(role_cell, d, "apply_user_permissions") | |||
.removeClass("col-md-4") | |||
@@ -336,8 +344,8 @@ frappe.PermissionEngine = Class.extend({ | |||
var me = this; | |||
this.body.on("click", ".show-user-permissions", function() { | |||
frappe.route_options = { doctype: me.get_doctype() || "" }; | |||
frappe.set_route("user-permissions"); | |||
frappe.route_options = { allow: me.get_doctype() || "" }; | |||
frappe.set_route('List', 'User Permission'); | |||
}); | |||
this.body.on("click", "input[type='checkbox']", function() { | |||
@@ -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.permissions import (reset_perms, get_linked_doctypes, get_all_perms, | |||
setup_custom_perms, add_permission) | |||
setup_custom_perms, add_permission, update_permission_property) | |||
from frappe.core.doctype.doctype.doctype import (clear_permissions_cache, | |||
validate_permissions_for_doctype) | |||
from frappe import _ | |||
@@ -68,18 +68,8 @@ def add(parent, role, permlevel): | |||
@frappe.whitelist() | |||
def update(doctype, role, permlevel, ptype, value=None): | |||
frappe.only_for("System Manager") | |||
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_permissions_for_doctype(doctype) | |||
return out | |||
out = update_permission_property(doctype, role, permlevel, ptype, value) | |||
return 'refresh' if out else None | |||
@frappe.whitelist() | |||
def remove(doctype, role, permlevel): | |||
@@ -1 +0,0 @@ | |||
Interface to set user defaults (DefaultValue). |
@@ -1,3 +0,0 @@ | |||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
# MIT License. See license.txt | |||
@@ -1,365 +0,0 @@ | |||
frappe.pages['user-permissions'].on_page_load = function(wrapper) { | |||
var page = frappe.ui.make_app_page({ | |||
parent: wrapper, | |||
title: __("User Permissions Manager"), | |||
icon: "fa fa-shield", | |||
single_column: true | |||
}); | |||
frappe.breadcrumbs.add("Setup"); | |||
$("<div class='user-settings' \ | |||
style='min-height: 200px; padding: 15px;'></div>\ | |||
<p style='padding: 15px; padding-bottom: 0px;'>\ | |||
<a class='view-role-permissions grey'>" + __("Edit Role Permissions") + "</a>\ | |||
</p><hr><div style='padding: 0px 15px;'>\ | |||
<h4>"+__("Help for User Permissions")+":</h4>\ | |||
<ol>\ | |||
<li>" | |||
+ __("Apart from Role based Permission Rules, you can apply User Permissions based on DocTypes.") | |||
+ "</li>" | |||
+ "<li>" | |||
+ __("These permissions will apply for all transactions where the permitted record is linked. For example, if Company C is added to User Permissions of user X, user X will only be able to see transactions that has company C as a linked value.") | |||
+ "</li>" | |||
+ "<li>" | |||
+ __("These will also be set as default values for those links, if only one such permission record is defined.") | |||
+ "</li>" | |||
+ "<li>" | |||
+ __("A user can be permitted to multiple records of the same DocType.") | |||
+ "</li>\ | |||
</ol></div>").appendTo(page.main); | |||
wrapper.user_permissions = new frappe.UserPermissions(wrapper); | |||
} | |||
frappe.pages['user-permissions'].refresh = function(wrapper) { | |||
wrapper.user_permissions.set_from_route(); | |||
} | |||
frappe.UserPermissions = Class.extend({ | |||
init: function(wrapper) { | |||
this.wrapper = wrapper; | |||
this.body = $(this.wrapper).find(".user-settings"); | |||
this.filters = {}; | |||
this.make(); | |||
this.refresh(); | |||
}, | |||
make: function() { | |||
var me = this; | |||
$(this.wrapper).find(".view-role-permissions").on("click", function() { | |||
frappe.route_options = { doctype: me.get_doctype() || "" }; | |||
frappe.set_route("permission-manager"); | |||
}) | |||
return frappe.call({ | |||
module:"frappe.core", | |||
page:"user_permissions", | |||
method: "get_users_and_links", | |||
callback: function(r) { | |||
me.options = r.message; | |||
me.filters.user = me.wrapper.page.add_field({ | |||
fieldname: "user", | |||
label: __("User"), | |||
fieldtype: "Select", | |||
options: ([__("Select User") + "..."].concat(r.message.users)).join("\n") | |||
}); | |||
me.filters.doctype = me.wrapper.page.add_field({ | |||
fieldname: "doctype", | |||
label: __("DocType"), | |||
fieldtype: "Select", | |||
options: ([__("Select DocType") + "..."].concat(me.get_link_names())).join("\n") | |||
}); | |||
me.filters.user_permission = me.wrapper.page.add_field({ | |||
fieldname: "user_permission", | |||
label: __("Name"), | |||
fieldtype: "Link", | |||
options: "[Select]" | |||
}); | |||
if(frappe.user_roles.includes("System Manager")) { | |||
me.download = me.wrapper.page.add_field({ | |||
fieldname: "download", | |||
label: __("Download"), | |||
fieldtype: "Button", | |||
icon: "fa fa-download" | |||
}); | |||
me.upload = me.wrapper.page.add_field({ | |||
fieldname: "upload", | |||
label: __("Upload"), | |||
fieldtype: "Button", | |||
icon: "fa fa-upload" | |||
}); | |||
} | |||
// bind change event | |||
$.each(me.filters, function(k, f) { | |||
f.$input.on("change", function() { | |||
me.refresh(); | |||
}); | |||
}); | |||
// change options in user_permission link | |||
me.filters.doctype.$input.on("change", function() { | |||
me.filters.user_permission.df.options = me.get_doctype(); | |||
}); | |||
me.set_from_route(); | |||
me.setup_download_upload(); | |||
} | |||
}); | |||
}, | |||
setup_download_upload: function() { | |||
var me = this; | |||
me.download.$input.on("click", function() { | |||
window.location.href = frappe.urllib.get_base_url() | |||
+ "/api/method/frappe.core.page.user_permissions.user_permissions.get_user_permissions_csv"; | |||
}); | |||
me.upload.$input.on("click", function() { | |||
var d = new frappe.ui.Dialog({ | |||
title: __("Upload User Permissions"), | |||
fields: [ | |||
{ | |||
fieldtype:"HTML", | |||
options: '<p class="text-muted"><ol>'+ | |||
"<li>"+__("Upload CSV file containing all user permissions in the same format as Download.")+"</li>"+ | |||
"<li><strong>"+__("Any existing permission will be deleted / overwritten.")+"</strong></li>"+ | |||
'</p>' | |||
}, | |||
{ | |||
fieldtype:"Attach", fieldname:"attach", | |||
} | |||
], | |||
primary_action_label: __("Upload and Sync"), | |||
primary_action: function() { | |||
var filedata = d.fields_dict.attach.get_value(); | |||
if(!filedata) { | |||
frappe.msgprint(__("Please attach a file")); | |||
return; | |||
} | |||
frappe.call({ | |||
method:"frappe.core.page.user_permissions.user_permissions.import_user_permissions", | |||
args: { | |||
filedata: filedata | |||
}, | |||
callback: function(r) { | |||
if(!r.exc) { | |||
frappe.msgprint(__("Permissions Updated")); | |||
d.hide(); | |||
} | |||
} | |||
}); | |||
} | |||
}); | |||
d.show(); | |||
}) | |||
}, | |||
get_link_names: function() { | |||
return this.options.link_fields; | |||
}, | |||
set_from_route: function() { | |||
var me = this; | |||
if(frappe.route_options && this.filters && !$.isEmptyObject(this.filters)) { | |||
$.each(frappe.route_options, function(key, value) { | |||
if(me.filters[key] && frappe.route_options[key]!=null) | |||
me.set_filter(key, value); | |||
}); | |||
frappe.route_options = null; | |||
} | |||
this.refresh(); | |||
}, | |||
set_filter: function(key, value) { | |||
this.filters[key].$input.val(value); | |||
}, | |||
get_user: function() { | |||
var user = this.filters.user.$input.val(); | |||
return user== __("Select User") + "..." ? null : user; | |||
}, | |||
get_doctype: function() { | |||
var doctype = this.filters.doctype.$input.val(); | |||
return doctype== __("Select DocType") + "..." ? null : doctype; | |||
}, | |||
get_user_permission: function() { | |||
// autosuggest hack! | |||
var user_permission = this.filters.user_permission.$input.val(); | |||
return (user_permission === "%") ? null : user_permission; | |||
}, | |||
render: function(prop_list) { | |||
var me = this; | |||
this.body.empty(); | |||
this.prop_list = prop_list; | |||
if(!prop_list || !prop_list.length) { | |||
this.add_message(__("No User Restrictions found.")); | |||
} else { | |||
this.show_user_permissions_table(); | |||
} | |||
this.show_add_user_permission(); | |||
if(this.get_user() && this.get_doctype()) { | |||
$('<button class="btn btn-default btn-sm" style="margin-left: 10px;">\ | |||
Show Allowed Documents</button>').appendTo(this.body.find(".btn-area")).on("click", function() { | |||
frappe.route_options = {doctype: me.get_doctype(), user:me.get_user() }; | |||
frappe.set_route("query-report/Permitted Documents For User"); | |||
}); | |||
} | |||
}, | |||
add_message: function(txt) { | |||
$('<p class="text-muted">' + txt + '</p>').appendTo(this.body); | |||
}, | |||
refresh: function() { | |||
var me = this; | |||
if(!me.filters.user) { | |||
this.body.html("<p class='text-muted'>"+__("Loading")+"...</p>"); | |||
return; | |||
} | |||
if(!me.get_user() && !me.get_doctype()) { | |||
this.body.html("<p class='text-muted'>"+__("Select User or DocType to start.")+"</p>"); | |||
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 = $("<table class='table table-bordered'>\ | |||
<thead><tr></tr></thead>\ | |||
<tbody></tbody>\ | |||
</table>").appendTo(this.body); | |||
$('<p class="text-muted small">' | |||
+__("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.") | |||
+'</p>').appendTo(this.body); | |||
$.each([[__("Allow User"), 150], [__("If Document Type"), 150], [__("Is"),150], ["", 50]], | |||
function(i, col) { | |||
$("<th>") | |||
.html(col[0]) | |||
.css("width", col[1]+"px") | |||
.appendTo(me.table.find("thead tr")); | |||
}); | |||
$.each(this.prop_list, function(i, d) { | |||
var row = $("<tr>").appendTo(me.table.find("tbody")); | |||
$("<td>").html('<a class="grey" href="#Form/User/'+encodeURIComponent(d.parent)+'">' | |||
+d.parent+'</a>').appendTo(row); | |||
$("<td>").html(d.defkey).appendTo(row); | |||
$("<td>").html(d.defvalue).appendTo(row); | |||
me.add_delete_button(row, d); | |||
}); | |||
}, | |||
add_delete_button: function(row, d) { | |||
var me = this; | |||
$("<button class='btn btn-sm btn-default'><i class='fa fa-remove'></i></button>") | |||
.appendTo($("<td>").appendTo(row)) | |||
.attr("data-name", d.name) | |||
.attr("data-user", d.parent) | |||
.attr("data-defkey", d.defkey) | |||
.attr("data-defvalue", d.defvalue) | |||
.click(function() { | |||
return frappe.call({ | |||
module: "frappe.core", | |||
page: "user_permissions", | |||
method: "remove", | |||
args: { | |||
name: $(this).attr("data-name"), | |||
user: $(this).attr("data-user"), | |||
defkey: $(this).attr("data-defkey"), | |||
defvalue: $(this).attr("data-defvalue") | |||
}, | |||
callback: function(r) { | |||
if(r.exc) { | |||
frappe.msgprint(__("Did not remove")); | |||
} else { | |||
me.refresh(); | |||
} | |||
} | |||
}) | |||
}); | |||
}, | |||
show_add_user_permission: function() { | |||
var me = this; | |||
$("<button class='btn btn-default btn-sm'>"+__("Add A User Restriction")+"</button>") | |||
.appendTo($('<p class="btn-area">').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(); | |||
}); | |||
} | |||
}) |
@@ -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" | |||
} |
@@ -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]) |
@@ -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() | |||
@@ -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}) | |||
@@ -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"): | |||
@@ -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")) | |||
@@ -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: | |||
@@ -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 |
@@ -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"') |
@@ -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)): | |||
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
@@ -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") { | |||
@@ -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 | |||
@@ -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); | |||
} | |||
@@ -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); | |||
} | |||
}, | |||
@@ -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) | |||
@@ -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) |