Merge branch 'develop' into workflow-button-icon

This commit is contained in:
Shariq Ansari 2022-12-07 19:28:43 +05:30 committed by GitHub
commit 7345da5dbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 21 deletions

View file

@ -9,33 +9,33 @@ from frappe.utils.jinja import validate_template
class EmailTemplate(Document):
@property
def response_(self):
return self.response_html if self.use_html else self.response
def validate(self):
if self.use_html:
validate_template(self.response_html)
else:
validate_template(self.response)
validate_template(self.subject)
validate_template(self.response_)
def get_formatted_subject(self, doc):
return frappe.render_template(self.subject, doc)
def get_formatted_response(self, doc):
if self.use_html:
return frappe.render_template(self.response_html, doc)
return frappe.render_template(self.response, doc)
return frappe.render_template(self.response_, doc)
def get_formatted_email(self, doc):
if isinstance(doc, str):
doc = json.loads(doc)
return {"subject": self.get_formatted_subject(doc), "message": self.get_formatted_response(doc)}
return {
"subject": self.get_formatted_subject(doc),
"message": self.get_formatted_response(doc),
}
@frappe.whitelist()
def get_email_template(template_name, doc):
"""Returns the processed HTML of a email template with the given doc"""
if isinstance(doc, str):
doc = json.loads(doc)
email_template = frappe.get_doc("Email Template", template_name)
return email_template.get_formatted_email(doc)

View file

@ -109,7 +109,7 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control
"title",
__(
"This value is fetched from {0}'s {1} field",
me.df.fetch_from.split(".")
me.df.fetch_from.split(".").map((value) => __(frappe.unscrub(value)))
)
);
}

View file

@ -104,9 +104,8 @@ def patch_query_execute():
# frame1: execute_query()
# frame2: frame that called `query.run()`
#
# if frame2 is server script it wont have a filename and hence
# if frame2 is server script <serverscript> is set as the filename
# it shouldn't be allowed.
# p.s. stack() returns `"<unknown>"` as filename if not a file.
pass
else:
raise frappe.PermissionError("Only SELECT SQL allowed in scripting")

View file

@ -75,3 +75,10 @@ class TestSafeExec(FrappeTestCase):
def test_unsafe_objects(self):
unsafe_global = {"frappe": frappe}
self.assertRaises(SyntaxError, safe_exec, """frappe.msgprint("Hello")""", unsafe_global)
def test_attrdict(self):
# jinja
frappe.render_template("{% set my_dict = _dict() %} {{- my_dict.works -}}")
# RestrictedPython
safe_exec("my_dict = _dict()")

View file

@ -4828,3 +4828,4 @@ CSV Quoting,Anführungszeichen,
CSV Preview,Vorschau,
Non-numeric,Nicht-numerische,
Minimal,Minimal,
This value is fetched from {0}'s {1} field,Dieser Wert ergibt sich aus dem Feld {1} von {0},

1 A4 A4
4828 CSV Preview Vorschau
4829 Non-numeric Nicht-numerische
4830 Minimal Minimal
4831 This value is fetched from {0}'s {1} field Dieser Wert ergibt sich aus dem Feld {1} von {0}

View file

@ -60,7 +60,7 @@ def validate_template(html):
frappe.throw(frappe._("Syntax error in template"))
def render_template(template, context, is_path=None, safe_render=True):
def render_template(template, context=None, is_path=None, safe_render=True):
"""Render a template using Jinja
:param template: path or HTML containing the jinja template
@ -76,6 +76,9 @@ def render_template(template, context, is_path=None, safe_render=True):
if not template:
return ""
if context is None:
context = {}
if is_path or guess_is_path(template):
return get_jenv().get_template(template).render(context)
else:

View file

@ -8,6 +8,7 @@ from functools import lru_cache
import RestrictedPython.Guards
from RestrictedPython import compile_restricted, safe_globals
from RestrictedPython.transformer import RestrictingNodeTransformer
import frappe
import frappe.exceptions
@ -45,6 +46,14 @@ class NamespaceDict(frappe._dict):
return ret
class FrappeTransformer(RestrictingNodeTransformer):
def check_name(self, node, name, *args, **kwargs):
if name == "_dict":
return
return super().check_name(node, name, *args, **kwargs)
def safe_exec(script, _globals=None, _locals=None, restrict_commit_rollback=False):
# server scripts can be disabled via site_config.json
# they are enabled by default
@ -69,7 +78,11 @@ def safe_exec(script, _globals=None, _locals=None, restrict_commit_rollback=Fals
with safe_exec_flags(), patched_qb():
# execute script compiled by RestrictedPython
exec(compile_restricted(script), exec_globals, _locals) # pylint: disable=exec-used
exec(
compile_restricted(script, filename="<serverscript>", policy=FrappeTransformer),
exec_globals,
_locals,
)
return exec_globals, _locals
@ -106,6 +119,7 @@ def get_safe_globals():
as_json=frappe.as_json,
dict=dict,
log=frappe.log,
_dict=frappe._dict,
args=form_dict,
frappe=NamespaceDict(
call=call_whitelisted_function,
@ -116,7 +130,6 @@ def get_safe_globals():
time_format=time_format,
format_date=frappe.utils.data.global_date_format,
form_dict=form_dict,
as_dict=frappe._dict,
bold=frappe.bold,
copy_doc=frappe.copy_doc,
errprint=frappe.errprint,

View file

@ -62,10 +62,6 @@ class WebsiteTheme(Document):
def generate_bootstrap_theme(self):
from subprocess import PIPE, Popen
self.theme_scss = frappe.render_template(
"frappe/website/doctype/website_theme/website_theme_template.scss", self.as_dict()
)
# create theme file in site public files folder
folder_path = abspath(frappe.utils.get_files_path("website_theme", is_private=False))
# create folder if not exist