@@ -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 | |||
@@ -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 | |||
@@ -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", | |||
@@ -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) |
@@ -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 |
@@ -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 +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() | |||
} | |||
} | |||
} | |||
} | |||
] | |||
} |
@@ -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" | |||
} |
@@ -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 |
@@ -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", | |||
@@ -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: | |||
@@ -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 |
@@ -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 | |||
@@ -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; | |||
} | |||
@@ -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 |