Nested permission (#5460)
* nested permission * test for nested permission * [minor] Format code * Fix nested permission test * Fix codacy
This commit is contained in:
parent
33b9bca057
commit
95c02f94ef
4 changed files with 64 additions and 2 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue