Merge pull request #35318 from AarDG10/add-custom-hook

feat(server script): parse child table list onto server script for customizations
This commit is contained in:
Aarol D'Souza 2026-02-17 23:05:32 +05:30 committed by GitHub
commit a043c26709
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 5 deletions

View file

@ -211,16 +211,21 @@ class ServerScript(Document):
safe_exec(self.script, script_filename=self.name)
def get_permission_query_conditions(self, user: str) -> list[str]:
def get_permission_query_conditions(self, user: str, active_child_tables=None) -> list[str]:
"""Specific to Permission Query Server Scripts.
Args:
user (str): Take user email to execute script and return list of conditions.
active_child_tables (list, optional): A list of child table names involved in the current SQL query.
Return:
list: Return list of conditions defined by rules in self.script.
"""
locals = {"user": user, "conditions": ""}
locals = {
"user": user,
"conditions": "",
"active_child_tables": active_child_tables or [],
}
safe_exec(self.script, None, locals, script_filename=self.name)
if locals["conditions"]:
return locals["conditions"]

View file

@ -1533,6 +1533,16 @@ class Engine:
return where_condition
def get_queried_tables(self) -> list[str]:
"""Extract all table names involved in the current query."""
tables = []
for table in self.query._from:
tables.append(table.get_sql())
for join in self.query._joins:
tables.append(join.item.get_sql())
return list(set(tables))
def get_permission_query_conditions(self, doctype: str | None = None) -> list["RawCriterion"]:
"""Add permission query conditions from hooks and server scripts"""
from frappe.core.doctype.server_script.server_script_utils import get_server_script_map
@ -1546,10 +1556,20 @@ class Engine:
if c := frappe.call(frappe.get_attr(method), self.user, doctype=doctype):
conditions.append(RawCriterion(f"({c})"))
active_child_tables = []
current_tables = self.get_queried_tables()
if len(current_tables) > 1:
main_table_name = f"tab{self.doctype}"
for table_name in current_tables:
if table_name != main_table_name:
active_child_tables.append(table_name)
# Get conditions from server scripts
if permission_script_name := get_server_script_map().get("permission_query", {}).get(doctype):
script = frappe.get_doc("Server Script", permission_script_name)
if condition := script.get_permission_query_conditions(self.user):
if condition := script.get_permission_query_conditions(
self.user, active_child_tables=active_child_tables
):
conditions.append(RawCriterion(f"({condition})"))
return conditions

View file

@ -1163,9 +1163,19 @@ from {tables}
if c := frappe.call(frappe.get_attr(method), self.user, doctype=self.doctype):
conditions.append(c)
active_child_tables = []
if len(self.tables) > 1: # only if query has multiple tables involved
main_table_name = f"tab{self.doctype}"
for table_name in self.tables:
clean_name = table_name.replace("`", "").replace('"', "")
if clean_name != main_table_name:
active_child_tables.append(clean_name)
if permission_script_name := get_server_script_map().get("permission_query", {}).get(self.doctype):
script = frappe.get_doc("Server Script", permission_script_name)
if condition := script.get_permission_query_conditions(self.user):
if condition := script.get_permission_query_conditions(
self.user, active_child_tables=active_child_tables
):
conditions.append(condition)
return " and ".join(conditions) if conditions else ""

View file

@ -990,11 +990,14 @@ class TestDBQuery(IntegrationTestCase):
from frappe.desk.doctype.dashboard_settings.dashboard_settings import (
create_dashboard_settings,
)
from frappe.model.db_query import DatabaseQuery
self.doctype = "Dashboard Settings"
self.user = "test'5@example.com"
permission_query_conditions = DatabaseQuery.get_permission_query_conditions(self)
db_query = DatabaseQuery(self.doctype, user=self.user)
permission_query_conditions = db_query.get_permission_query_conditions()
create_dashboard_settings(self.user)