Nested permission (#5460)

* nested permission

* test for nested permission

* [minor] Format code

* Fix nested permission test

* Fix codacy
This commit is contained in:
Suraj Shetty 2018-04-20 18:07:55 +05:30 committed by Faris Ansari
parent 33b9bca057
commit 95c02f94ef
4 changed files with 64 additions and 2 deletions

View file

@ -27,7 +27,13 @@ def get_user_permissions(user=None):
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)
meta = frappe.get_meta(perm.allow)
if not perm.allow in out:
out[perm.allow] = []
out[perm.allow].append(perm.for_value)
if meta.is_nested_set():
out[perm.allow].extend(frappe.db.get_descendants(perm.allow, perm.for_value))
frappe.cache().hset("user_permissions", user, out)
except frappe.SQLError as e:

View file

@ -948,6 +948,12 @@ class Database:
return s
def get_descendants(self, doctype, name):
'''Return descendants of the current record'''
lft, rgt = self.get_value(doctype, name, ('lft', 'rgt'))
return self.sql_list('''select name from `tab{doctype}`
where lft > {lft} and rgt < {rgt}'''.format(doctype=doctype, lft=lft, rgt=rgt))
def enqueue_jobs_after_commit():
if frappe.flags.enqueue_after_commit and len(frappe.flags.enqueue_after_commit) > 0:
for job in frappe.flags.enqueue_after_commit:

View file

@ -403,6 +403,9 @@ class Meta(Document):
module_name = module_name, doctype_name = doctype, suffix=suffix)
return None
def is_nested_set(self):
return self.has_field('lft') and self.has_field('rgt')
doctype_table_fields = [
frappe._dict({"fieldname": "fields", "options": "DocField"}),
frappe._dict({"fieldname": "permissions", "options": "DocPerm"})

View file

@ -6,6 +6,7 @@ import frappe, unittest
from frappe.model.db_query import DatabaseQuery
from frappe.desk.reportview import get_filters_cond
from frappe.permissions import add_user_permission, clear_user_permissions_for_doctype
class TestReportview(unittest.TestCase):
def test_basic(self):
@ -133,6 +134,40 @@ class TestReportview(unittest.TestCase):
"datediff(modified, creation) as date_diff"], limit_start=0, limit_page_length=1)
self.assertTrue('date_diff' in data[0])
def test_nested_permission(self):
clear_user_permissions_for_doctype("File")
delete_test_file_hierarchy() # delete already existing folders
from frappe.core.doctype.file.file import create_new_folder
frappe.set_user('Administrator')
create_new_folder('level1-A', 'Home')
create_new_folder('level2-A', 'Home/level1-A')
create_new_folder('level2-B', 'Home/level1-A')
create_new_folder('level3-A', 'Home/level1-A/level2-A')
create_new_folder('level1-B', 'Home')
create_new_folder('level2-A', 'Home/level1-B')
# user permission for only one root folder
add_user_permission('File', 'Home/level1-A', 'test2@example.com')
from frappe.core.page.permission_manager.permission_manager import update
update('File', 'All', 0, 'if_owner', 0) # to avoid if_owner filter
frappe.set_user('test2@example.com')
data = DatabaseQuery("File").execute()
# children of root folder (for which we added user permission) should be accessible
self.assertTrue({"name": "Home/level1-A/level2-A"} in data)
self.assertTrue({"name": "Home/level1-A/level2-B"} in data)
self.assertTrue({"name": "Home/level1-A/level2-A/level3-A"} in data)
# other folders should not be accessible
self.assertFalse({"name": "Home/level1-B"} in data)
self.assertFalse({"name": "Home/level1-B/level2-B"} in data)
update('File', 'All', 0, 'if_owner', 1)
frappe.set_user('Administrator')
def create_event(subject="_Test Event", starts_on=None):
""" create a test event """
@ -145,4 +180,16 @@ def create_event(subject="_Test Event", starts_on=None):
"starts_on": get_datetime(starts_on),
}).insert(ignore_permissions=True)
return event
return event
def delete_test_file_hierarchy():
files_to_delete = [
'Home/level1-A/level2-A/level3-A',
'Home/level1-A/level2-A',
'Home/level1-A/level2-B',
'Home/level1-A',
'Home/level1-B/level2-A',
'Home/level1-B'
]
for file_name in files_to_delete:
frappe.delete_doc('File', file_name)