From 67fc4a7ad4aabb609a8ba983757c00d3cd2e7021 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Wed, 17 Sep 2025 12:47:39 +0530 Subject: [PATCH 1/3] fix(QueryReport): respect user permissions in Link fields --- frappe/desk/query_report.py | 28 +++++++++++++------ .../js/frappe/views/reports/query_report.js | 4 +++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index b20cc92292..aa7598c768 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -199,10 +199,11 @@ def run( is_tree=False, parent_field=None, are_default_filters=True, + js_filters=None, ): if not user: user = frappe.session.user - validate_filters_permissions(report_name, filters, user) + validate_filters_permissions(report_name, filters, user, js_filters) report = get_report_doc(report_name) if not frappe.has_permission(report.ref_doctype, "report"): frappe.msgprint( @@ -894,25 +895,36 @@ def get_user_match_filters(doctypes, user): return match_filters -def validate_filters_permissions(report_name, filters=None, user=None): +def validate_filters_permissions(report_name, filters=None, user=None, js_filters=None): if not filters: return + # print(filters, "filters \n\n\n") + # print(js_filters, "js_filters \n\n\n") + + # print(frappe.query_reports["Trial Balance"], " query report \n\n\n") + + if isinstance(js_filters, str): + js_filters = json.loads(js_filters) + if isinstance(filters, str): filters = json.loads(filters) report = frappe.get_doc("Report", report_name) - for field in report.filters: - if field.fieldname in filters and field.fieldtype == "Link": - linked_doctype = field.options + + for field in report.filters + js_filters: + if hasattr(field, "as_dict"): + field = field.as_dict() + if field.get("fieldname") in filters and field.get("fieldtype") == "Link": + linked_doctype = field.get("options") if not has_permission( - doctype=linked_doctype, ptype="read", doc=filters[field.fieldname], user=user + doctype=linked_doctype, ptype="read", doc=filters[field.get("fieldname")], user=user ) and not has_permission( - doctype=linked_doctype, ptype="select", doc=filters[field.fieldname], user=user + doctype=linked_doctype, ptype="select", doc=filters[field.get("fieldname")], user=user ): frappe.throw( _("You do not have permission to access {0}: {1}.").format( - linked_doctype, filters[field.fieldname] + linked_doctype, filters[field.get("fieldname")] ) ) diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index 437a4179d1..a01026029a 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -719,6 +719,9 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { filters.prepared_report_name = this.prepared_report_name; } + // console.log(this.filters); + // console.log(frappe.query_reports[this.report_name].filters); + return new Promise((resolve) => { this.last_ajax = frappe.call({ method: "frappe.desk.query_report.run", @@ -730,6 +733,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { is_tree: this.report_settings.tree, parent_field: this.report_settings.parent_field, are_default_filters: are_default_filters, + js_filters: frappe.query_reports[this.report_name]?.filters, }, callback: resolve, always: () => this.page.btn_secondary.prop("disabled", false), From 94d31b5cdca48c180e2e71c49886000b3eb24730 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Wed, 17 Sep 2025 12:49:40 +0530 Subject: [PATCH 2/3] refactor: remove debigging statements --- frappe/desk/query_report.py | 5 ----- frappe/public/js/frappe/views/reports/query_report.js | 3 --- 2 files changed, 8 deletions(-) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index aa7598c768..98114eb1ca 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -899,11 +899,6 @@ def validate_filters_permissions(report_name, filters=None, user=None, js_filter if not filters: return - # print(filters, "filters \n\n\n") - # print(js_filters, "js_filters \n\n\n") - - # print(frappe.query_reports["Trial Balance"], " query report \n\n\n") - if isinstance(js_filters, str): js_filters = json.loads(js_filters) diff --git a/frappe/public/js/frappe/views/reports/query_report.js b/frappe/public/js/frappe/views/reports/query_report.js index a01026029a..23e6abe610 100644 --- a/frappe/public/js/frappe/views/reports/query_report.js +++ b/frappe/public/js/frappe/views/reports/query_report.js @@ -719,9 +719,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { filters.prepared_report_name = this.prepared_report_name; } - // console.log(this.filters); - // console.log(frappe.query_reports[this.report_name].filters); - return new Promise((resolve) => { this.last_ajax = frappe.call({ method: "frappe.desk.query_report.run", From 7c60ce811a3cfd98531e2b5b4312efd4a6a3e3d7 Mon Sep 17 00:00:00 2001 From: Ejaaz Khan Date: Wed, 17 Sep 2025 14:50:38 +0530 Subject: [PATCH 3/3] fix: check for none/empty js filters --- frappe/desk/query_report.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index 98114eb1ca..32cc80746b 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -899,6 +899,9 @@ def validate_filters_permissions(report_name, filters=None, user=None, js_filter if not filters: return + if js_filters is None: + js_filters = [] + if isinstance(js_filters, str): js_filters = json.loads(js_filters)