From e1aa309b878fa4985d18d8cbf209f295ae0a3224 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 24 Oct 2019 17:29:56 +0530 Subject: [PATCH 01/26] fix: do not append table names for mysql methods --- frappe/model/db_query.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 29fa44d208..722dadaea3 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -19,6 +19,8 @@ from frappe.model.utils.user_settings import get_user_settings, update_user_sett from frappe.utils import flt, cint, get_time, make_filter_tuple, get_filter, add_to_date, cstr, nowdate from frappe.model.meta import get_table_columns +MYSQL_METHODS = ('COUNT(', 'AVG(', 'SUM') + class DatabaseQuery(object): def __init__(self, doctype, user=None): self.doctype = doctype @@ -286,7 +288,7 @@ class DatabaseQuery(object): If the fieldname is not explicitly mentioned, set the default table''' if len(self.tables) > 1: for i, f in enumerate(self.fields): - if '.' not in f: + if '.' not in f and not sum([int(method in f.upper()) for method in MYSQL_METHODS]): self.fields[i] = '{0}.{1}'.format(self.tables[0], f) def set_optional_columns(self): From d93b060f225dedd33b7cf407cb08f407a2ca1fb5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 24 Oct 2019 18:43:24 +0530 Subject: [PATCH 02/26] refactor: improved for readability --- frappe/model/db_query.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 722dadaea3..e109c26cfc 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -19,8 +19,6 @@ from frappe.model.utils.user_settings import get_user_settings, update_user_sett from frappe.utils import flt, cint, get_time, make_filter_tuple, get_filter, add_to_date, cstr, nowdate from frappe.model.meta import get_table_columns -MYSQL_METHODS = ('COUNT(', 'AVG(', 'SUM') - class DatabaseQuery(object): def __init__(self, doctype, user=None): self.doctype = doctype @@ -286,10 +284,17 @@ class DatabaseQuery(object): def set_field_tables(self): '''If there are more than one table, the fieldname must not be ambiguous. If the fieldname is not explicitly mentioned, set the default table''' + def _in_standard_sql_methods(field): + methods = ('COUNT(', 'AVG(', 'SUM(') + for method in methods: + if method in field.upper(): + return True + return False + if len(self.tables) > 1: - for i, f in enumerate(self.fields): - if '.' not in f and not sum([int(method in f.upper()) for method in MYSQL_METHODS]): - self.fields[i] = '{0}.{1}'.format(self.tables[0], f) + for idx, field in enumerate(self.fields): + if '.' not in field and not _in_standard_sql_methods(field): + self.fields[idx] = '{0}.{1}'.format(self.tables[0], field) def set_optional_columns(self): """Removes optional columns like `_user_tags`, `_comments` etc. if not in table""" From c0d69a04c44f39e644e390e5e7a55eac74337e11 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 24 Oct 2019 19:47:53 +0530 Subject: [PATCH 03/26] feat: added tests --- frappe/desk/listview.py | 5 ++++- frappe/model/db_query.py | 3 ++- frappe/tests/test_db_query.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 3dc795191a..327298fb59 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -45,7 +45,10 @@ def get_group_by_count(doctype, current_filters, field): order by count desc limit 50""".format(subquery_condition = subquery_condition), as_dict=True) - else : + else: + print(current_filters) + print(field) + print('count(*) as count', '`{}` as name'.format(field)) return frappe.db.get_list(doctype, filters=current_filters, group_by=field, diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index e109c26cfc..043207b89c 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -285,9 +285,10 @@ class DatabaseQuery(object): '''If there are more than one table, the fieldname must not be ambiguous. If the fieldname is not explicitly mentioned, set the default table''' def _in_standard_sql_methods(field): + # return False methods = ('COUNT(', 'AVG(', 'SUM(') for method in methods: - if method in field.upper(): + if field.upper().startswith(method): return True return False diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 18c19cbf3e..cb72c7461b 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -6,6 +6,8 @@ import frappe, unittest from frappe.model.db_query import DatabaseQuery from frappe.desk.reportview import get_filters_cond +from pymysql.ProgrammingError + from frappe.permissions import add_user_permission, clear_user_permissions_for_doctype test_dependencies = ['User', 'Blog Post'] @@ -332,6 +334,16 @@ class TestReportview(unittest.TestCase): self.assertTrue({'name': 'Prepared Report'} in res) self.assertFalse({'name': 'Property Setter'} in res) + def test_set_field_tables(self): + # Tests _in_standard_sql_methods method in test_set_field_tables + # The following query will break if the above method is broken + data = frappe.db.get_list(doctype, + filters=[['Web Form Field', 'reqd', '=', 1]], + group_by='amount_field', + fields=['count(*) as count `amount_field` as name'], + order_by='count desc', + limit=50, + ) def create_event(subject="_Test Event", starts_on=None): """ create a test event """ From e293ea228992b49760f3fc19d23b69e2f7bae320 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Fri, 25 Oct 2019 11:35:11 +0530 Subject: [PATCH 04/26] style: removed unused import --- frappe/tests/test_db_query.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index cb72c7461b..3776777cf7 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -6,7 +6,6 @@ import frappe, unittest from frappe.model.db_query import DatabaseQuery from frappe.desk.reportview import get_filters_cond -from pymysql.ProgrammingError from frappe.permissions import add_user_permission, clear_user_permissions_for_doctype From 47abe300c4112c5a5fab3e79e7355f71b7d21307 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Sun, 27 Oct 2019 17:32:30 +0530 Subject: [PATCH 05/26] style: removed print statements --- frappe/desk/listview.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 327298fb59..fd0833eb51 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -46,9 +46,6 @@ def get_group_by_count(doctype, current_filters, field): count desc limit 50""".format(subquery_condition = subquery_condition), as_dict=True) else: - print(current_filters) - print(field) - print('count(*) as count', '`{}` as name'.format(field)) return frappe.db.get_list(doctype, filters=current_filters, group_by=field, From 5f5202d360e8578bc5ba1dd910c89af681acd79a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Sun, 27 Oct 2019 17:34:39 +0530 Subject: [PATCH 06/26] fix: doctype in test --- frappe/tests/test_db_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 3776777cf7..20676a89e2 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -336,7 +336,7 @@ class TestReportview(unittest.TestCase): def test_set_field_tables(self): # Tests _in_standard_sql_methods method in test_set_field_tables # The following query will break if the above method is broken - data = frappe.db.get_list(doctype, + data = frappe.db.get_list("Web Form", filters=[['Web Form Field', 'reqd', '=', 1]], group_by='amount_field', fields=['count(*) as count `amount_field` as name'], From 08b992d547ec209deb0f02d826c45b03767b5588 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 29 Oct 2019 10:07:39 +0530 Subject: [PATCH 07/26] style: removed loop to check standard SQL --- frappe/model/db_query.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 043207b89c..27997ac569 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -285,12 +285,8 @@ class DatabaseQuery(object): '''If there are more than one table, the fieldname must not be ambiguous. If the fieldname is not explicitly mentioned, set the default table''' def _in_standard_sql_methods(field): - # return False methods = ('COUNT(', 'AVG(', 'SUM(') - for method in methods: - if field.upper().startswith(method): - return True - return False + return field.startswith(methods) if len(self.tables) > 1: for idx, field in enumerate(self.fields): From 00d21a2ac55a88ec802e7290209fd067a0bc6c1b Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 29 Oct 2019 10:17:52 +0530 Subject: [PATCH 08/26] fix: tests for db_query --- frappe/model/db_query.py | 4 ++-- frappe/tests/test_db_query.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 27997ac569..b7feee82f4 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -285,8 +285,8 @@ class DatabaseQuery(object): '''If there are more than one table, the fieldname must not be ambiguous. If the fieldname is not explicitly mentioned, set the default table''' def _in_standard_sql_methods(field): - methods = ('COUNT(', 'AVG(', 'SUM(') - return field.startswith(methods) + methods = ('count(', 'avg(', 'sum(') + return field.lower().startswith(methods) if len(self.tables) > 1: for idx, field in enumerate(self.fields): diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 20676a89e2..f4855965f0 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -339,7 +339,7 @@ class TestReportview(unittest.TestCase): data = frappe.db.get_list("Web Form", filters=[['Web Form Field', 'reqd', '=', 1]], group_by='amount_field', - fields=['count(*) as count `amount_field` as name'], + fields=['count(*) as count', '`amount_field` as name'], order_by='count desc', limit=50, ) From 50cee0f32e70e239a69dab1a0de1b880564a73e0 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 4 Nov 2019 11:45:32 +0530 Subject: [PATCH 09/26] fix(naming): empty string isnt accepted for rename --- frappe/model/naming.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 6fc09e19c8..46e38aa867 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -199,7 +199,7 @@ def get_default_naming_series(doctype): def validate_name(doctype, name, case=None, merge=False): if not name: - return 'No Name Specified for %s' % doctype + frappe.throw(_("No Name Specified for {0}").format(doctype)) if name.startswith('New '+doctype): frappe.throw(_('There were some errors setting the name, please contact the administrator'), frappe.NameError) if case == 'Title Case': From 539fe0aaa092d69c908a4d19ba6e5899904a8c05 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 4 Nov 2019 11:47:52 +0530 Subject: [PATCH 10/26] chore(style): consistencies in formatting --- frappe/model/naming.py | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 46e38aa867..78d2c462e1 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -43,13 +43,13 @@ def set_new_name(doc): # if the autoname option is 'field:' and no name was derived, we need to # notify - if autoname.startswith('field:') and not doc.name: + if autoname.startswith("field:") and not doc.name: fieldname = autoname[6:] frappe.throw(_("{0} is required").format(doc.meta.get_label(fieldname))) # at this point, we fall back to name generation with the hash option - if not doc.name or autoname == 'hash': - doc.name = make_autoname('hash', doc.doctype) + if not doc.name or autoname == "hash": + doc.name = make_autoname("hash", doc.doctype) doc.name = validate_name( doc.doctype, @@ -65,15 +65,15 @@ def set_name_from_naming_options(autoname, doc): _autoname = autoname.lower() - if _autoname.startswith('field:'): + if _autoname.startswith("field:"): doc.name = _field_autoname(autoname, doc) - elif _autoname.startswith('naming_series:'): + elif _autoname.startswith("naming_series:"): set_name_by_naming_series(doc) - elif _autoname.startswith('prompt'): + elif _autoname.startswith("prompt"): _prompt_autoname(autoname, doc) - elif _autoname.startswith('format:'): + elif _autoname.startswith("format:"): doc.name = _format_autoname(autoname, doc) - elif '#' in autoname: + elif "#" in autoname: doc.name = make_autoname(autoname, doc=doc) def set_name_by_naming_series(doc): @@ -84,9 +84,9 @@ def set_name_by_naming_series(doc): if not doc.naming_series: frappe.throw(frappe._("Naming Series mandatory")) - doc.name = make_autoname(doc.naming_series+'.#####', '', doc) + doc.name = make_autoname(doc.naming_series+".#####", "", doc) -def make_autoname(key='', doctype='', doc=''): +def make_autoname(key="", doctype="", doc=""): """ Creates an autoname from the given key: @@ -200,11 +200,11 @@ def get_default_naming_series(doctype): def validate_name(doctype, name, case=None, merge=False): if not name: frappe.throw(_("No Name Specified for {0}").format(doctype)) - if name.startswith('New '+doctype): - frappe.throw(_('There were some errors setting the name, please contact the administrator'), frappe.NameError) - if case == 'Title Case': + if name.startswith("New "+doctype): + frappe.throw(_("There were some errors setting the name, please contact the administrator"), frappe.NameError) + if case == "Title Case": name = name.title() - if case == 'UPPER CASE': + if case == "UPPER CASE": name = name.upper() name = name.strip() @@ -219,13 +219,13 @@ def validate_name(doctype, name, case=None, merge=False): return name -def append_number_if_name_exists(doctype, value, fieldname='name', separator='-', filters=None): +def append_number_if_name_exists(doctype, value, fieldname="name", separator="-", filters=None): if not filters: filters = dict() filters.update({fieldname: value}) exists = frappe.db.exists(doctype, filters) - regex = '^{value}{separator}\d+$'.format(value=re.escape(value), separator=separator) + regex = "^{value}{separator}\d+$".format(value=re.escape(value), separator=separator) if exists: last = frappe.db.sql("""SELECT `{fieldname}` FROM `tab{doctype}` @@ -251,10 +251,10 @@ def _set_amended_name(doc): am_id = 1 am_prefix = doc.amended_from if frappe.db.get_value(doc.doctype, doc.amended_from, "amended_from"): - am_id = cint(doc.amended_from.split('-')[-1]) + 1 - am_prefix = '-'.join(doc.amended_from.split('-')[:-1]) # except the last hyphen + am_id = cint(doc.amended_from.split("-")[-1]) + 1 + am_prefix = "-".join(doc.amended_from.split("-")[:-1]) # except the last hyphen - doc.name = am_prefix + '-' + str(am_id) + doc.name = am_prefix + "-" + str(am_id) return doc.name @@ -264,7 +264,7 @@ def _field_autoname(autoname, doc, skip_slicing=None): `autoname` field starts with 'field:' """ fieldname = autoname if skip_slicing else autoname[6:] - name = (cstr(doc.get(fieldname)) or '').strip() + name = (cstr(doc.get(fieldname)) or "").strip() return name @@ -285,7 +285,7 @@ def _format_autoname(autoname, doc): Example pattern: 'format:LOG-{MM}-{fieldname1}-{fieldname2}-{#####}' """ - first_colon_index = autoname.find(':') + first_colon_index = autoname.find(":") autoname_value = autoname[first_colon_index + 1:] def get_param_value_for_match(match): @@ -295,6 +295,6 @@ def _format_autoname(autoname, doc): return parse_naming_series([trimmed_param], doc=doc) # Replace braced params with their parsed value - name = re.sub(r'(\{[\w | #]+\})', get_param_value_for_match, autoname_value) + name = re.sub(r"(\{[\w | #]+\})", get_param_value_for_match, autoname_value) return name From 1c450877b0a9052229e72eee4e1fd9beaf47b2a2 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 4 Nov 2019 15:53:53 +0530 Subject: [PATCH 11/26] fix(security): XSS in display area --- frappe/public/js/frappe/form/controls/base_input.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/base_input.js b/frappe/public/js/frappe/form/controls/base_input.js index 365ff364d5..e0a572d476 100644 --- a/frappe/public/js/frappe/form/controls/base_input.js +++ b/frappe/public/js/frappe/form/controls/base_input.js @@ -119,9 +119,12 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ } else { value = this.value || value; } - this.disp_area && $(this.disp_area) - .html(frappe.format(value, this.df, {no_icon:true, inline:true}, - this.doc || (this.frm && this.frm.doc))); + if (this.df.fieldtype === 'Data') { + value = frappe.utils.escape_html(value); + } + let doc = this.doc || (this.frm && this.frm.doc); + let display_value = frappe.format(value, this.df, {no_icon:true, inline:true}, doc); + this.disp_area && $(this.disp_area).html(display_value); }, bind_change_event: function() { @@ -184,4 +187,4 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ $(this.disp_area).toggleClass("bold", !!(this.df.bold || this.df.reqd)); } } -}); \ No newline at end of file +}); From ba9eb671d69ae424d212a643fdcdb68dba2c9b17 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 4 Nov 2019 23:26:54 +0530 Subject: [PATCH 12/26] fix: add notify param to notify_assignment in share.py --- frappe/public/js/frappe/form/sidebar/share.js | 1 + frappe/share.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/form/sidebar/share.js b/frappe/public/js/frappe/form/sidebar/share.js index 3cb5257e78..79d6d28945 100644 --- a/frappe/public/js/frappe/form/sidebar/share.js +++ b/frappe/public/js/frappe/form/sidebar/share.js @@ -141,6 +141,7 @@ frappe.ui.form.Share = Class.extend({ read: $(d.body).find(".add-share-read").prop("checked") ? 1 : 0, write: $(d.body).find(".add-share-write").prop("checked") ? 1 : 0, share: $(d.body).find(".add-share-share").prop("checked") ? 1 : 0, + notify: 1, }, btn: this, callback: function(r) { diff --git a/frappe/share.py b/frappe/share.py index 3875870949..314386a298 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -10,7 +10,7 @@ from frappe.desk.doctype.notification_log.notification_log import enqueue_create from frappe.utils import cint @frappe.whitelist() -def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=None): +def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=None, notify=0): """Share the given document with a user.""" if not user: user = frappe.session.user @@ -42,7 +42,7 @@ def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=No }) doc.save(ignore_permissions=True) - notify_assignment(user, doctype, name, everyone) + notify_assignment(user, doctype, name, everyone, notify=notify) follow_document(doctype, name, user) @@ -147,9 +147,9 @@ def check_share_permission(doctype, name): if not frappe.has_permission(doctype, ptype="share", doc=name): frappe.throw(_("No permission to {0} {1} {2}".format("share", doctype, name)), frappe.PermissionError) -def notify_assignment(shared_by, doctype, doc_name, everyone): +def notify_assignment(shared_by, doctype, doc_name, everyone, notify=0): - if not (shared_by and doctype and doc_name) or everyone: return + if not (shared_by and doctype and doc_name) or everyone or not notify: return from frappe.utils import get_fullname From 9fc2309b4742ae03c75397c34de6ca4cb31b80a0 Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 4 Nov 2019 23:27:56 +0530 Subject: [PATCH 13/26] style: hide 'Mark as Read in xs screen --- frappe/public/js/frappe/ui/notifications/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/notifications/notifications.js b/frappe/public/js/frappe/ui/notifications/notifications.js index 034ecd7af6..36d2891928 100644 --- a/frappe/public/js/frappe/ui/notifications/notifications.js +++ b/frappe/public/js/frappe/ui/notifications/notifications.js @@ -299,7 +299,7 @@ frappe.ui.Notifications = class Notifications {
${timestamp}
- + `; From 67faa597f664a23d9f3afb0600945ad7cb81e29f Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 4 Nov 2019 23:39:30 +0530 Subject: [PATCH 14/26] fix: formatting --- frappe/share.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/share.py b/frappe/share.py index 314386a298..03311bed4a 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -149,7 +149,8 @@ def check_share_permission(doctype, name): def notify_assignment(shared_by, doctype, doc_name, everyone, notify=0): - if not (shared_by and doctype and doc_name) or everyone or not notify: return + if not (shared_by and doctype and doc_name) or everyone or not notify: + return from frappe.utils import get_fullname From 66e54114cb269c1333914aea688c848f47efa784 Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 5 Nov 2019 00:15:09 +0530 Subject: [PATCH 15/26] fix: tests --- frappe/desk/doctype/notification_log/test_notification_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/doctype/notification_log/test_notification_log.py b/frappe/desk/doctype/notification_log/test_notification_log.py index 9431336aad..fe7d56c081 100644 --- a/frappe/desk/doctype/notification_log/test_notification_log.py +++ b/frappe/desk/doctype/notification_log/test_notification_log.py @@ -28,7 +28,7 @@ class TestNotificationLog(unittest.TestCase): todo = get_todo() user = get_user() - frappe.share.add('ToDo', todo.name, user) + frappe.share.add('ToDo', todo.name, user, notify=1) log_type = frappe.db.get_value('Notification Log', { 'document_type': 'ToDo', 'document_name': todo.name From a14e8a4859fb80c0084d8310aac8baa9f8408afa Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 6 Nov 2019 01:13:37 +0530 Subject: [PATCH 16/26] fix: addfilter operations for tags --- frappe/patches/v12_0/copy_to_parent_for_tags.py | 6 ++++++ frappe/public/js/frappe/ui/filters/filter.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 frappe/patches/v12_0/copy_to_parent_for_tags.py diff --git a/frappe/patches/v12_0/copy_to_parent_for_tags.py b/frappe/patches/v12_0/copy_to_parent_for_tags.py new file mode 100644 index 0000000000..1135f9076b --- /dev/null +++ b/frappe/patches/v12_0/copy_to_parent_for_tags.py @@ -0,0 +1,6 @@ +import frappe + +def execute(): + + frappe.db.sql("UPDATE `tabTag Link` SET parenttype=document_type") + frappe.db.sql("UPDATE `tabTag Link` SET parent=document_name") \ No newline at end of file diff --git a/frappe/public/js/frappe/ui/filters/filter.js b/frappe/public/js/frappe/ui/filters/filter.js index 7923d57ad4..cbfce608cd 100644 --- a/frappe/public/js/frappe/ui/filters/filter.js +++ b/frappe/public/js/frappe/ui/filters/filter.js @@ -177,7 +177,7 @@ frappe.ui.Filter = class { if (doctype === "Tag Link" || fieldname === "_user_tags") { original_docfield = {fieldname: "tag", fieldtype: "Data", label: "Tags", parent: "Tag Link"}; doctype = "Tag Link"; - condition = "="; + condition = condition; } if(!original_docfield) { From 60a3da2fae428a2d5974b2de0d749f83fda30fcd Mon Sep 17 00:00:00 2001 From: Himanshu Date: Wed, 6 Nov 2019 10:36:10 +0530 Subject: [PATCH 17/26] Update filter.js --- frappe/public/js/frappe/ui/filters/filter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/filters/filter.js b/frappe/public/js/frappe/ui/filters/filter.js index cbfce608cd..5fda43375d 100644 --- a/frappe/public/js/frappe/ui/filters/filter.js +++ b/frappe/public/js/frappe/ui/filters/filter.js @@ -177,7 +177,6 @@ frappe.ui.Filter = class { if (doctype === "Tag Link" || fieldname === "_user_tags") { original_docfield = {fieldname: "tag", fieldtype: "Data", label: "Tags", parent: "Tag Link"}; doctype = "Tag Link"; - condition = condition; } if(!original_docfield) { From 23ed4e44771c18f2f4ef0a04bceb246aa894aac5 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 6 Nov 2019 12:31:07 +0530 Subject: [PATCH 18/26] style: Fix key spacing --- frappe/public/js/frappe/form/controls/base_input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/controls/base_input.js b/frappe/public/js/frappe/form/controls/base_input.js index e0a572d476..8a8ac271c7 100644 --- a/frappe/public/js/frappe/form/controls/base_input.js +++ b/frappe/public/js/frappe/form/controls/base_input.js @@ -123,7 +123,7 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ value = frappe.utils.escape_html(value); } let doc = this.doc || (this.frm && this.frm.doc); - let display_value = frappe.format(value, this.df, {no_icon:true, inline:true}, doc); + let display_value = frappe.format(value, this.df, { no_icon: true, inline: true }, doc); this.disp_area && $(this.disp_area).html(display_value); }, From 51158b79599930cc6be516ee7e6d9c42cd22169b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 6 Nov 2019 15:38:38 +0530 Subject: [PATCH 19/26] fix: add to patches.txt --- frappe/patches.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/patches.txt b/frappe/patches.txt index e107449dea..d4aaec5bfc 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -256,3 +256,4 @@ frappe.patches.v12_0.update_global_search execute:frappe.reload_doc('desk', 'doctype', 'notification_settings') frappe.patches.v12_0.setup_tags frappe.patches.v12_0.update_auto_repeat_status_and_not_submittable +frappe.patches.v12_0.copy_to_parent_for_tags From 12ffba815ab337f007b49ec07c636fcc9bd8f3ad Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 6 Nov 2019 16:39:33 +0530 Subject: [PATCH 20/26] fix(auth): do not force standard users to reset password --- frappe/auth.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/auth.py b/frappe/auth.py index c3b00970e8..468f45c53e 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -219,6 +219,10 @@ class LoginManager: if not self.user: return + from frappe.core.doctype.user.user import STANDARD_USERS + if self.user in STANDARD_USERS: + return False + reset_pwd_after_days = cint(frappe.db.get_single_value("System Settings", "force_user_to_reset_password")) From 2a751b13b947bccb074a9169d6ed530b38f30a13 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 6 Nov 2019 18:34:33 +0530 Subject: [PATCH 21/26] fix: return value in autocomplete validate if 'valid_values' list is empty --- frappe/public/js/frappe/form/controls/autocomplete.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/public/js/frappe/form/controls/autocomplete.js b/frappe/public/js/frappe/form/controls/autocomplete.js index d4a21fc32c..026cdbec25 100644 --- a/frappe/public/js/frappe/form/controls/autocomplete.js +++ b/frappe/public/js/frappe/form/controls/autocomplete.js @@ -101,6 +101,9 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ validate(value) { let valid_values = this.awesomplete._list.map(d => d.value); + if (!valid_values.length) { + return value; + } if (valid_values.includes(value)) { return value; } else { From 83e8288104189f9d4eefa69dd1a0272aac45ca09 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 6 Nov 2019 19:55:04 +0530 Subject: [PATCH 22/26] fix: email account permission issue while sending an email --- frappe/core/doctype/communication/communication.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 2be07cadd2..74d7fa1654 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -381,7 +381,7 @@ def parse_email(communication, email_strings): a doctype and docname ie in the format `admin+doctype+docname@example.com`, the email is parsed and doctype and docname is extracted and timeline link is added. """ - if not frappe.get_list("Email Account", filters={"enable_automatic_linking": 1}): + if not frappe.get_all("Email Account", filters={"enable_automatic_linking": 1}): return delimiter = "+" @@ -406,7 +406,7 @@ def get_email_without_link(email): returns email address without doctype links returns admin@example.com for email admin+doctype+docname@example.com """ - if not frappe.get_list("Email Account", filters={"enable_automatic_linking": 1}): + if not frappe.get_all("Email Account", filters={"enable_automatic_linking": 1}): return email email_id = email.split("@")[0].split("+")[0] From cc2797a08e9b89f87d9419d47ee3f8c74d3ee3a5 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Thu, 7 Nov 2019 12:36:38 +0530 Subject: [PATCH 23/26] 1. do not run server side script if site is in migrate state 2. do not process enegery points if site is in migrate state --- frappe/core/doctype/server_script/server_script_utils.py | 3 +++ frappe/social/doctype/energy_point_rule/energy_point_rule.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/server_script/server_script_utils.py b/frappe/core/doctype/server_script/server_script_utils.py index e327401331..0399dea106 100644 --- a/frappe/core/doctype/server_script/server_script_utils.py +++ b/frappe/core/doctype/server_script/server_script_utils.py @@ -31,6 +31,9 @@ def run_server_script_for_doc_event(doc, event): if frappe.flags.in_install: return + if frappe.flags.in_migrate: + return + scripts = get_server_script_map().get(doc.doctype, {}).get(EVENT_MAP[event], None) if scripts: # run all scripts for this doctype + event diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.py b/frappe/social/doctype/energy_point_rule/energy_point_rule.py index 1386fc7cbf..38995887f0 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -82,7 +82,10 @@ class EnergyPointRule(Document): def process_energy_points(doc, state): if (frappe.flags.in_patch or frappe.flags.in_install - or not is_energy_point_enabled()): + or frappe.flags.in_migrate): + return + + if not is_energy_point_enabled(): return old_doc = doc.get_doc_before_save() From 8d6d6d5d23649a10cab17f04b8fa102809ce3f11 Mon Sep 17 00:00:00 2001 From: Arjit Gupta Date: Thu, 7 Nov 2019 14:06:26 +0530 Subject: [PATCH 24/26] chore: Fix typo in docstrings (#8764) Corrected typo in documentation of find() and find_all() --- frappe/core/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/core/utils.py b/frappe/core/utils.py index e4c349da93..55767ffe34 100644 --- a/frappe/core/utils.py +++ b/frappe/core/utils.py @@ -41,7 +41,7 @@ def find(list_of_dict, match_function): Usage: list_of_dict = [{'name': 'Suraj'}, {'name': 'Aditya'}] - required_dict = find(list_of_dict, lamda d: d['name'] == 'Aditya') + required_dict = find(list_of_dict, lambda d: d['name'] == 'Aditya') ''' for entry in list_of_dict: @@ -60,10 +60,10 @@ def find_all(list_of_dict, match_function): {'color': 'blue', 'shape': 'triangle'} ] - red_shapes = find_all(colored_shapes, lamda d: d['color'] == 'red') + red_shapes = find_all(colored_shapes, lambda d: d['color'] == 'red') ''' found = [] for entry in list_of_dict: if match_function(entry): found.append(entry) - return found \ No newline at end of file + return found From 2dac4f8432a876fb8914c3efb22e63eb79649a04 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 7 Nov 2019 17:12:11 +0530 Subject: [PATCH 25/26] fix(db.sql): Print query in debug mode (#8767) --- frappe/database/database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/database/database.py b/frappe/database/database.py index 1e6a85236e..f5055571ff 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -174,6 +174,7 @@ class Database(object): self.log_touched_tables(query) if debug: + frappe.errprint(self._cursor.mogrify(query, values)) time_end = time() frappe.errprint(("Execution time: {0} sec").format(round(time_end - time_start, 2))) From be15eec09e4bc5f61fc1554ad1dfcfe092ae33b4 Mon Sep 17 00:00:00 2001 From: thefalconx33 Date: Fri, 8 Nov 2019 15:54:09 +0530 Subject: [PATCH 26/26] fix: error while enqueuing jobs related to notification log --- .../notification_log/notification_log.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index 4efcaa558b..f58c14d363 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -25,6 +25,16 @@ def get_permission_query_conditions(for_user): return '''(`tabNotification Log`.for_user = '{user}')'''.format(user=for_user) +def get_title(doctype, docname, title_field=None): + if not title_field: + title_field = frappe.get_meta(doctype).get_title_field() + title = docname if title_field == "name" else \ + frappe.db.get_value(doctype, docname, title_field) + return title + +def get_title_html(title): + return '{0}'.format(title) + def enqueue_create_notification(users, doc): ''' During installation of new site, enqueue_create_notification tries to connect to Redis. @@ -101,16 +111,6 @@ def get_email_header(doc): }[doc.type or 'Default'] -def get_title(doctype, docname, title_field=None): - if not title_field: - title_field = frappe.get_meta(doctype).get_title_field() - title = docname if title_field == "name" else \ - frappe.db.get_value(doctype, docname, title_field) - return title - -def get_title_html(title): - return '{0}'.format(title) - @frappe.whitelist() def mark_as_seen(docname): if docname: