Bladeren bron

Apply User Permissions optional in script and query report, option to pass user in has_permission

version-14
Anand Doshi 11 jaren geleden
bovenliggende
commit
2b2a608bab
16 gewijzigde bestanden met toevoegingen van 190 en 76 verwijderingen
  1. +4
    -4
      frappe/__init__.py
  2. +4
    -4
      frappe/core/doctype/event/event.py
  3. +10
    -1
      frappe/core/doctype/report/report.json
  4. +5
    -5
      frappe/core/doctype/report/report.py
  5. +9
    -10
      frappe/core/doctype/todo/todo.py
  6. +3
    -4
      frappe/core/doctype/user/user.json
  7. +0
    -0
      frappe/core/report/permitted_documents_for_user/__init__.py
  8. +29
    -0
      frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.js
  9. +15
    -0
      frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.json
  10. +51
    -0
      frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py
  11. +3
    -2
      frappe/core/report/todo/todo.json
  12. +6
    -5
      frappe/model/db_query.py
  13. +2
    -1
      frappe/patches.txt
  14. +18
    -14
      frappe/permissions.py
  15. +5
    -1
      frappe/public/js/frappe/form/control.js
  16. +26
    -25
      frappe/widgets/query_report.py

+ 4
- 4
frappe/__init__.py Bestand weergeven

@@ -291,9 +291,9 @@ def get_roles(username=None):
else:
return User(username).get_roles()

def has_permission(doctype, ptype="read", doc=None):
def has_permission(doctype, ptype="read", doc=None, user=None):
import frappe.permissions
return frappe.permissions.has_permission(doctype, ptype, doc)
return frappe.permissions.has_permission(doctype, ptype, doc, user=user)

def is_table(doctype):
tables = cache().get_value("is_table")
@@ -573,13 +573,13 @@ def build_match_conditions(doctype, as_condition=True):

def get_list(doctype, filters=None, fields=None, or_filters=None, docstatus=None,
group_by=None, order_by=None, limit_start=0, limit_page_length=None,
as_list=False, debug=False, ignore_permissions=False):
as_list=False, debug=False, ignore_permissions=False, user=None):
import frappe.model.db_query
return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters,
fields=fields, docstatus=docstatus, or_filters=or_filters,
group_by=group_by, order_by=order_by, limit_start=limit_start,
limit_page_length=limit_page_length, as_list=as_list, debug=debug,
ignore_permissions=ignore_permissions)
ignore_permissions=ignore_permissions, user=user)

run_query = get_list



+ 4
- 4
frappe/core/doctype/event/event.py Bestand weergeven

@@ -27,14 +27,14 @@ def get_permission_query_conditions():
"roles": "', '".join(frappe.get_roles(frappe.session.user))
}

def has_permission(doc):
if doc.event_type=="Public" or doc.owner==frappe.session.user:
def has_permission(doc, user):
if doc.event_type=="Public" or doc.owner==user:
return True

if doc.get("event_individuals", {"person":frappe.session.user}):
if doc.get("event_individuals", {"person": user}):
return True

if doc.get("event_roles", {"role":("in", frappe.get_roles())}):
if doc.get("event_roles", {"role":("in", frappe.get_roles(user))}):
return True

return False


+ 10
- 1
frappe/core/doctype/report/report.json Bestand weergeven

@@ -61,6 +61,15 @@
"permlevel": 0,
"read_only": 0
},
{
"default": "1",
"depends_on": "eval:[\"Query Report\", \"Script Report\"].indexOf(doc.report_type)!==-1",
"fieldname": "apply_user_permissions",
"fieldtype": "Check",
"in_list_view": 0,
"label": "Apply User Permissions",
"permlevel": 0
},
{
"fieldname": "section_break_6",
"fieldtype": "Section Break",
@@ -101,7 +110,7 @@
],
"icon": "icon-table",
"idx": 1,
"modified": "2014-05-27 03:49:17.001234",
"modified": "2014-06-03 07:25:41.509885",
"modified_by": "Administrator",
"module": "Core",
"name": "Report",


+ 5
- 5
frappe/core/doctype/report/report.py Bestand weergeven

@@ -12,26 +12,26 @@ class Report(Document):
"""only administrator can save standard report"""
if not self.module:
self.module = frappe.db.get_value("DocType", self.ref_doctype, "module")
if not self.is_standard:
self.is_standard = "No"
if frappe.session.user=="Administrator" and getattr(conf, 'developer_mode',0)==1:
self.is_standard = "Yes"

if self.is_standard == "Yes" and frappe.session.user!="Administrator":
frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."),
frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."),
raise_exception=True)

if self.report_type in ("Query Report", "Script Report") \
and frappe.session.user!="Administrator":
frappe.msgprint(_("Only Administrator allowed to create Query / Script Reports"),
raise_exception=True)
def on_update(self):
self.export_doc()
def export_doc(self):
from frappe.modules.export_file import export_to_files
if self.is_standard == 'Yes' and (conf.get('developer_mode') or 0) == 1:
export_to_files(record_list=[['Report', self.name]],
export_to_files(record_list=[['Report', self.name]],
record_module=self.module)

+ 9
- 10
frappe/core/doctype/todo/todo.py Bestand weergeven

@@ -14,24 +14,24 @@ class ToDo(Document):
cur_status = frappe.db.get_value("ToDo", self.name, "status")
if cur_status != self.status:
self.add_comment(frappe._("Assignment Status Changed"))
def add_comment(self, text):
if not self.reference_type and self.reference_name:
return
comment = frappe.get_doc({
"doctype":"Comment",
"comment_by": frappe.session.user,
"comment_doctype": self.reference_type,
"comment_docname": self.reference_name,
"comment": """<div>{text}:
"comment": """<div>{text}:
<a href='#Form/ToDo/{name}'>{status}: {description}</a></div>""".format(text=text,
status = frappe._(self.status),
name = self.name,
description = self.description)
}).insert(ignore_permissions=True)
# todo is viewable if either owner or assigned_to or System Manager in roles

def get_permission_query_conditions():
@@ -39,10 +39,9 @@ def get_permission_query_conditions():
return None
else:
return """(tabToDo.owner = '{user}' or tabToDo.assigned_by = '{user}')""".format(user=frappe.session.user)
def has_permission(doc):
if "System Manager" in frappe.get_roles():
def has_permission(doc, user):
if "System Manager" in frappe.get_roles(user):
return True
else:
return doc.owner==frappe.session.user or doc.assigned_by==frappe.session.user
return doc.owner==user or doc.assigned_by==user

+ 3
- 4
frappe/core/doctype/user/user.json Bestand weergeven

@@ -475,14 +475,13 @@
},
{
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"report": 1,
"report": 0,
"role": "All",
"submit": 0,
"write": 0


+ 0
- 0
frappe/core/report/permitted_documents_for_user/__init__.py Bestand weergeven


+ 29
- 0
frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.js Bestand weergeven

@@ -0,0 +1,29 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.query_reports["Permitted Documents For User"] = {
"filters": [
{
"fieldname": "user",
"label": __("User"),
"fieldtype": "Link",
"options": "User",
"reqd": 1
},
{
"fieldname": "doctype",
"label": __("DocType"),
"fieldtype": "Link",
"options": "DocType",
"reqd": 1,
"get_query": function() {
return {
"query": "frappe.core.report.permitted_documents_for_user.permitted_documents_for_user.query_doctypes",
"filters": {
"user": frappe.query_report.filters_by_name.user.get_value()
}
}
}
}
]
}

+ 15
- 0
frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.json Bestand weergeven

@@ -0,0 +1,15 @@
{
"apply_user_permissions": 1,
"creation": "2014-06-03 05:20:35.218263",
"docstatus": 0,
"doctype": "Report",
"is_standard": "Yes",
"modified": "2014-06-03 07:18:17.218526",
"modified_by": "Administrator",
"module": "Core",
"name": "Permitted Documents For User",
"owner": "Administrator",
"ref_doctype": "User",
"report_name": "Permitted Documents For User",
"report_type": "Script Report"
}

+ 51
- 0
frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py Bestand weergeven

@@ -0,0 +1,51 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe
from frappe import _, throw
import frappe.utils.user
from frappe.permissions import check_admin_or_system_manager

def execute(filters=None):
user, doctype = filters.get("user"), filters.get("doctype")
validate(user, doctype)

columns, fields = get_columns_and_fields(doctype)
data = frappe.get_list(doctype, fields=fields, as_list=True, user=user)

return columns, data

def validate(user, doctype):
# check if current user is System Manager
check_admin_or_system_manager()

if not user:
throw(_("Please specify user"))

if not doctype:
throw(_("Please specify doctype"))

def get_columns_and_fields(doctype):
columns = ["Name:Link/{}:200".format(doctype)]
fields = ["name"]
for df in frappe.get_meta(doctype).fields:
if df.in_list_view:
fields.append(df.fieldname)
fieldtype = "Link/{}".format(df.options) if df.fieldtype=="Link" else df.fieldtype
columns.append("{label}:{fieldtype}:{width}".format(label=df.label, fieldtype=fieldtype, width=df.width or 100))

return columns, fields

def query_doctypes(doctype, txt, searchfield, start, page_len, filters):
user = filters.get("user")
user_obj = frappe.utils.user.User(user)
user_obj.build_permissions()
can_read = user_obj.can_read

out = []
for dt in can_read:
if txt.lower().replace("%", "") in dt.lower():
out.append([dt])

return out

+ 3
- 2
frappe/core/report/todo/todo.json Bestand weergeven

@@ -1,10 +1,11 @@
{
"creation": "2013-02-25 14:26:30.000000",
"apply_user_permissions": 1,
"creation": "2013-02-25 14:26:30",
"docstatus": 0,
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2014-03-07 15:30:27.000000",
"modified": "2014-06-03 07:18:17.374222",
"modified_by": "Administrator",
"module": "Core",
"name": "ToDo",


+ 6
- 5
frappe/model/db_query.py Bestand weergeven

@@ -17,12 +17,13 @@ class DatabaseQuery(object):
self.conditions = []
self.ignore_permissions = False
self.fields = ["name"]
self.user = None

def execute(self, query=None, filters=None, fields=None, or_filters=None,
docstatus=None, group_by=None, order_by=None, limit_start=0,
limit_page_length=20, as_list=False, with_childnames=False, debug=False,
ignore_permissions=False):
if not frappe.has_permission(self.doctype, "read"):
ignore_permissions=False, user=None):
if not frappe.has_permission(self.doctype, "read", user=user):
raise frappe.PermissionError

if fields:
@@ -38,7 +39,7 @@ class DatabaseQuery(object):
self.debug = debug
self.as_list = as_list
self.ignore_permissions = ignore_permissions
self.user = user or frappe.session.user

if query:
return self.run_custom_query(query)
@@ -216,10 +217,10 @@ class DatabaseQuery(object):
if not self.tables: self.extract_tables()

# apply user permissions?
role_permissions = frappe.permissions.get_role_permissions(frappe.get_meta(self.doctype))
role_permissions = frappe.permissions.get_role_permissions(frappe.get_meta(self.doctype), user=self.user)
if role_permissions.get("apply_user_permissions", {}).get("read"):
# get user permissions
user_permissions = frappe.defaults.get_user_permissions()
user_permissions = frappe.defaults.get_user_permissions(self.user)
self.add_user_permissions(user_permissions)

if as_condition:


+ 2
- 1
frappe/patches.txt Bestand weergeven

@@ -5,7 +5,7 @@ execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2014-01-24
execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2014-03-01
execute:frappe.reload_doc('core', 'doctype', 'docperm') #2013-13-26
execute:frappe.reload_doc('core', 'doctype', 'page') #2013-13-26
execute:frappe.reload_doc('core', 'doctype', 'report') #2013-13-26
execute:frappe.reload_doc('core', 'doctype', 'report') #2014-06-03
execute:frappe.reload_doc('core', 'doctype', 'version') #2014-02-21
execute:frappe.db.sql("alter table `tabSessions` modify `user` varchar(255), engine=InnoDB")
execute:frappe.db.sql("delete from `tabDocField` where parent='0'")
@@ -33,3 +33,4 @@ frappe.patches.v4_0.update_custom_field_insert_after
frappe.patches.v4_0.set_user_permissions
frappe.patches.v4_0.create_custom_field_for_owner_match
frappe.patches.v4_0.enable_scheduler_in_system_settings
execute:frappe.db.sql("update tabReport set apply_user_permissions=1") #2014-06-03

+ 18
- 14
frappe/permissions.py Bestand weergeven

@@ -9,13 +9,16 @@ from frappe.utils import cint
rights = ("read", "write", "create", "delete", "submit", "cancel", "amend",
"print", "email", "report", "import", "export", "set_user_permissions")

def check_admin_or_system_manager():
if ("System Manager" not in frappe.get_roles()) and \
(frappe.session.user!="Administrator"):
def check_admin_or_system_manager(user=None):
if not user: user = frappe.session.user

if ("System Manager" not in frappe.get_roles(user)) and (user!="Administrator"):
frappe.throw(_("Not permitted"), frappe.PermissionError)

def has_permission(doctype, ptype="read", doc=None, verbose=True):
def has_permission(doctype, ptype="read", doc=None, verbose=True, user=None):
"""check if user has permission"""
if not user: user = frappe.session.user

if frappe.is_table(doctype):
return True

@@ -27,10 +30,10 @@ def has_permission(doctype, ptype="read", doc=None, verbose=True):
if ptype=="import" and not cint(meta.allow_import):
return False

if frappe.session.user=="Administrator":
if user=="Administrator":
return True

role_permissions = get_role_permissions(meta)
role_permissions = get_role_permissions(meta, user=user)
if not role_permissions.get(ptype):
return False

@@ -38,17 +41,16 @@ def has_permission(doctype, ptype="read", doc=None, verbose=True):
if isinstance(doc, basestring):
doc = frappe.get_doc(meta.name, doc)

if not user_has_permission(doc, verbose=verbose):
if not user_has_permission(doc, verbose=verbose, user=user):
return False

if not has_controller_permissions(doc):
if not has_controller_permissions(doc, user=user):
return False

return True

def get_role_permissions(meta, user=None):
if not user:
user = frappe.session.user
if not user: user = frappe.session.user
cache_key = (meta.name, user)

if not frappe.local.role_permissions.get(cache_key):
@@ -71,9 +73,9 @@ def get_role_permissions(meta, user=None):

return frappe.local.role_permissions[cache_key]

def user_has_permission(doc, verbose=True):
def user_has_permission(doc, verbose=True, user=None):
from frappe.defaults import get_user_permissions
user_permissions = get_user_permissions()
user_permissions = get_user_permissions(user)
user_permissions_keys = user_permissions.keys()

def check_user_permission(d):
@@ -99,9 +101,11 @@ def user_has_permission(doc, verbose=True):

return _user_has_permission

def has_controller_permissions(doc):
def has_controller_permissions(doc, user=None):
if not user: user = frappe.session.user

for method in frappe.get_hooks("has_permission").get(doc.doctype, []):
if not frappe.call(frappe.get_attr(method), doc=doc):
if not frappe.call(frappe.get_attr(method), doc=doc, user=user):
return False

return True


+ 5
- 1
frappe/public/js/frappe/form/control.js Bestand weergeven

@@ -894,7 +894,11 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
select: function(event, ui) {
me.autocomplete_open = false;
if(ui.item.make_new) {
me.frm.new_doc(me.df.options, me);
if (me.frm) {
me.frm.new_doc(me.df.options, me);
} else {
new_doc(me.df.options);
}
return false;
}



+ 26
- 25
frappe/widgets/query_report.py Bestand weergeven

@@ -16,58 +16,58 @@ def get_report_doc(report_name):
doc = frappe.get_doc("Report", report_name)
if not doc.has_permission("read"):
raise frappe.PermissionError("You don't have access to: {report}".format(report=report_name))
if not frappe.has_permission(doc.ref_doctype, "report"):
raise frappe.PermissionError("You don't have access to get a report on: {doctype}".format(
doctype=doc.ref_doctype))
return doc

@frappe.whitelist()
def get_script(report_name):
report = get_report_doc(report_name)
module = frappe.db.get_value("DocType", report.ref_doctype, "module")
module_path = get_module_path(module)
report_folder = os.path.join(module_path, "report", scrub(report.name))
script_path = os.path.join(report_folder, scrub(report.name) + ".js")
script = None
if os.path.exists(script_path):
with open(script_path, "r") as script:
script = script.read()
if not script and report.javascript:
script = report.javascript
if not script:
script = "frappe.query_reports['%s']={}" % report_name
# load translations
if frappe.lang != "en":
frappe.response["__messages"] = frappe.get_lang_dict("report", report_name)
return script

@frappe.whitelist()
def run(report_name, filters=()):
report = get_report_doc(report_name)
if filters and isinstance(filters, basestring):
filters = json.loads(filters)

if not frappe.has_permission(report.ref_doctype, "report"):
frappe.msgprint(_("Must have report permission to access this report."),
frappe.msgprint(_("Must have report permission to access this report."),
raise_exception=True)
if report.report_type=="Query Report":
if not report.query:
frappe.msgprint(_("Must specify a Query to run"), raise_exception=True)
if not report.query.lower().startswith("select"):
frappe.msgprint(_("Query must be a SELECT"), raise_exception=True)
result = [list(t) for t in frappe.db.sql(report.query, filters)]
columns = [c[0] for c in frappe.db.get_description()]
else:
@@ -76,17 +76,18 @@ def run(report_name, filters=()):
method_name = frappe.local.module_app[scrub(module)] + "." + scrub(module) \
+ ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute"
columns, result = frappe.get_attr(method_name)(frappe._dict(filters))
result = get_filtered_data(report.ref_doctype, columns, result)

if report.apply_user_permissions:
result = get_filtered_data(report.ref_doctype, columns, result)

if cint(report.add_total_row) and result:
result = add_total_row(result, columns)
return {
"result": result,
"columns": columns
}
def add_total_row(result, columns):
total_row = [""]*len(columns)
has_percent = []
@@ -98,14 +99,14 @@ def add_total_row(result, columns):
total_row[i] = flt(total_row[i]) + flt(row[i])
if col[1] == "Percent" and i not in has_percent:
has_percent.append(i)
for i in has_percent:
total_row[i] = total_row[i] / len(result)
first_col = columns[0].split(":")
if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float", "Percent"]:
total_row[0] = "Total"
result.append(total_row)
return result

@@ -114,12 +115,12 @@ def get_filtered_data(ref_doctype, columns, data):

linked_doctypes = get_linked_doctypes(columns)
match_filters = get_user_match_filters(linked_doctypes, ref_doctype)
if match_filters:
matched_columns = get_matched_columns(linked_doctypes, match_filters)
for row in data:
match = True
if not ("owner" in match_filters and matched_columns.get("user", None)==match_filters["owner"]):
for col, idx in matched_columns.items():
if row[idx] not in match_filters[col]:
@@ -165,4 +166,4 @@ def get_matched_columns(linked_doctypes, match_filters):
if link_field in match_filters:
col_idx_map[link_field] = idx

return col_idx_map
return col_idx_map

Laden…
Annuleren
Opslaan