Procházet zdrojové kódy

fix: Check for fieldlevel permission for report query (#12163)

Co-authored-by: Prssanna Desai <prssud@gmail.com>
version-14
Suraj Shetty před 4 roky
committed by GitHub
rodič
revize
6f774d6d0c
V databázi nebyl nalezen žádný známý klíč pro tento podpis ID GPG klíče: 4AEE18F83AFDEB23
3 změnil soubory, kde provedl 124 přidání a 8 odebrání
  1. +26
    -7
      frappe/desk/reportview.py
  2. +19
    -0
      frappe/model/meta.py
  3. +79
    -1
      frappe/tests/test_db_query.py

+ 26
- 7
frappe/desk/reportview.py Zobrazit soubor

@@ -54,6 +54,12 @@ def get_form_params():

fields = data["fields"]

if ((isinstance(fields, string_types) and fields == "*")
or (isinstance(fields, (list, tuple)) and len(fields) == 1 and fields[0] == "*")):
parenttype = data.doctype
data["fields"] = frappe.db.get_table_columns(parenttype)
fields = data["fields"]

for field in fields:
key = field.split(" as ")[0]

@@ -61,21 +67,24 @@ def get_form_params():
if key.startswith('sum('): continue
if key.startswith('avg('): continue

if "." in key:
parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`")
else:
parenttype = data.doctype
fieldname = field.strip("`")
parenttype, fieldname = get_parent_dt_and_field(key, data)

df = frappe.get_meta(parenttype).get_field(fieldname)
if fieldname == "*":
# * inside list is not allowed with other fields
fields.remove(field)

meta = frappe.get_meta(parenttype)
df = meta.get_field(fieldname)

fieldname = df.fieldname if df else None
report_hide = df.report_hide if df else None

# remove the field from the query if the report hide flag is set and current view is Report
if report_hide and is_report:
fields.remove(field)

if df and fieldname in [df.fieldname for df in meta.get_high_permlevel_fields()]:
if df.get('permlevel') not in meta.get_permlevel_access(parenttype=data.doctype) and field in fields:
fields.remove(field)

# queries must always be server side
data.query = None
@@ -83,6 +92,16 @@ def get_form_params():

return data

def get_parent_dt_and_field(field, data):
if "." in field:
parenttype, fieldname = field.split(".")[0][4:-1], field.split(".")[1].strip("`")
else:
parenttype = data.doctype
fieldname = field.strip("`")

return parenttype, fieldname


def compress(data, args = {}):
"""separate keys and values"""
from frappe.desk.query_report import add_total_row


+ 19
- 0
frappe/model/meta.py Zobrazit soubor

@@ -450,6 +450,25 @@ class Meta(Document):

return self.high_permlevel_fields

def get_permlevel_access(self, permission_type='read', parenttype=None):
has_access_to = []
roles = frappe.get_roles()
for perm in self.get_permissions(parenttype):
if perm.role in roles and perm.permlevel > 0 and perm.get(permission_type):
if perm.permlevel not in has_access_to:
has_access_to.append(perm.permlevel)

return has_access_to

def get_permissions(self, parenttype=None):
if self.istable and parenttype:
# use parent permissions
permissions = frappe.get_meta(parenttype).permissions
else:
permissions = self.get('permissions', [])

return permissions

def get_dashboard_data(self):
'''Returns dashboard setup related to this doctype.



+ 79
- 1
frappe/tests/test_db_query.py Zobrazit soubor

@@ -7,9 +7,14 @@ import frappe, unittest
from frappe.model.db_query import DatabaseQuery
from frappe.desk.reportview import get_filters_cond

from frappe.core.page.permission_manager.permission_manager import update, reset, add
from frappe.permissions import add_user_permission, clear_user_permissions_for_doctype
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.handler import execute_cmd

test_dependencies = ['User', 'Blog Post']
from frappe.utils.testutils import add_custom_field, clear_custom_fields

test_dependencies = ['User', 'Blog Post', 'Blog Category', 'Blogger']

class TestReportview(unittest.TestCase):
def test_basic(self):
@@ -355,6 +360,79 @@ class TestReportview(unittest.TestCase):
owners = DatabaseQuery("DocType").execute(filters={"name": "DocType"}, pluck="owner")
self.assertEqual(owners, ["Administrator"])

def test_reportview_get(self):
user = frappe.get_doc("User", "test@example.com")
add_child_table_to_blog_post()

user_roles = frappe.get_roles()
user.remove_roles(*user_roles)
user.add_roles("Blogger")

make_property_setter("Blog Post", "published", "permlevel", 1, "Int")
reset("Blog Post")
add("Blog Post", "Website Manager", 1)
update("Blog Post", "Website Manager", 1, "write", 1)

frappe.set_user(user.name)

frappe.local.request = frappe._dict()
frappe.local.request.method = "POST"

frappe.local.form_dict = frappe._dict({
"doctype": "Blog Post",
"fields": ["published", "title", "`tabTest Child`.`test_field`"],
})

# even if * is passed, fields which are not accessible should be filtered out
response = execute_cmd("frappe.desk.reportview.get")
self.assertListEqual(response["keys"], ["title"])
frappe.local.form_dict = frappe._dict({
"doctype": "Blog Post",
"fields": ["*"],
})

response = execute_cmd("frappe.desk.reportview.get")
self.assertNotIn("published", response["keys"])

frappe.set_user("Administrator")
user.add_roles("Website Manager")
frappe.set_user(user.name)

frappe.set_user("Administrator")

# Admin should be able to see access all fields
frappe.local.form_dict = frappe._dict({
"doctype": "Blog Post",
"fields": ["published", "title", "`tabTest Child`.`test_field`"],
})

response = execute_cmd("frappe.desk.reportview.get")
self.assertListEqual(response["keys"], ['published', 'title', 'test_field'])

# reset user roles
user.remove_roles("Blogger", "Website Manager")
user.add_roles(*user_roles)


def add_child_table_to_blog_post():
child_table = frappe.get_doc({
'doctype': 'DocType',
'istable': 1,
'custom': 1,
'name': 'Test Child',
'module': 'Custom',
'autoname': 'Prompt',
'fields': [{
'fieldname': 'test_field',
'fieldtype': 'Data',
'permlevel': 1
}],
})

child_table.insert(ignore_permissions=True, ignore_if_duplicate=True)
clear_custom_fields('Blog Post')
add_custom_field('Blog Post', 'child_table', 'Table', child_table.name)

def create_event(subject="_Test Event", starts_on=None):
""" create a test event """



Načítá se…
Zrušit
Uložit