From 275a70e9d0cb4591bd3622fbd54b4e1e6dda1271 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 20 Aug 2020 18:33:29 +0530 Subject: [PATCH] feat(minor): allow frappe.db.sql for read in server script --- frappe/tests/test_safe_exec.py | 11 +++++++++-- frappe/utils/safe_exec.py | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frappe/tests/test_safe_exec.py b/frappe/tests/test_safe_exec.py index 65657b4739..95bbae6746 100644 --- a/frappe/tests/test_safe_exec.py +++ b/frappe/tests/test_safe_exec.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -import unittest +import unittest, frappe from frappe.utils.safe_exec import safe_exec class TestSafeExec(unittest.TestCase): @@ -7,4 +7,11 @@ class TestSafeExec(unittest.TestCase): self.assertRaises(ImportError, safe_exec, 'import os') def test_internal_attributes(self): - self.assertRaises(SyntaxError, safe_exec, '().__class__.__call__') \ No newline at end of file + self.assertRaises(SyntaxError, safe_exec, '().__class__.__call__') + + def test_sql(self): + _locals = dict(out=None) + safe_exec('''out = frappe.db.sql("select name from tabDocType where name='DocType'")''', None, _locals) + self.assertEqual(_locals['out'][0][0], 'DocType') + + self.assertRaises(frappe.PermissionError, safe_exec, 'frappe.db.sql("update tabToDo set description=NULL")') \ No newline at end of file diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index d97e770d88..bae1dbd746 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -114,6 +114,7 @@ def get_safe_globals(): get_single_value = frappe.db.get_single_value, get_default = frappe.db.get_default, escape = frappe.db.escape, + sql = read_sql ) if frappe.response: @@ -132,6 +133,13 @@ def get_safe_globals(): return out +def read_sql(query, *args, **kwargs): + '''a wrapper for frappe.db.sql to allow reads''' + if query.strip().split(None, 1)[0].lower() == 'select': + return frappe.db.sql(query, *args, **kwargs) + else: + raise frappe.PermissionError('Only SELECT SQL allowed in scripting') + def _getitem(obj, key): # guard function for RestrictedPython # allow any key to be accessed as long as it does not start with underscore