From 5c7b5835829c51b89d967cd1a93c794b80dfc10d Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Sat, 24 Dec 2022 12:32:51 +0530 Subject: [PATCH 01/12] fix(commands): require ngrok auth token in `site_config.json` to use ngrok command * ngrok authtoken is now required to use the host_header feature --- frappe/commands/site.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 1c0207ce4b..191be60c31 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -1128,6 +1128,14 @@ def start_ngrok(context, bind_tls): site = get_site(context) frappe.init(site=site) + ngrok_auth_token = frappe.conf.ngrok_auth_token + if not ngrok_auth_token: + frappe.errprint( + "'ngrok_auth_token' not found in site config. Please register for a free ngrok account at: https://dashboard.ngrok.com/signup and place the obtained authtoken in site_config.json file." + ) + exit(0) + ngrok.set_auth_token(ngrok_auth_token) + port = frappe.conf.http_port or frappe.conf.webserver_port tunnel = ngrok.connect(addr=str(port), host_header=site, bind_tls=bind_tls) print(f"Public URL: {tunnel.public_url}") From b9a6db3c08645a813e1fb44246fba73104b9aa40 Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Sat, 24 Dec 2022 12:45:24 +0530 Subject: [PATCH 02/12] refactor: `ngrok_auth_token` -> `ngrok_authtoken` * to be consistent with ngrok's naming convention --- frappe/commands/site.py | 96 +++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 27 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 191be60c31..91e439dfeb 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -109,7 +109,8 @@ def new_site( "--with-public-files", help="Restores the public files of the site, given path to its tar file" ) @click.option( - "--with-private-files", help="Restores the private files of the site, given path to its tar file" + "--with-private-files", + help="Restores the private files of the site, given path to its tar file", ) @click.option( "--force", @@ -191,7 +192,8 @@ def _restore( fg="red", ) click.secho( - "Use `bench partial-restore` to restore a partial backup to an existing site.", fg="yellow" + "Use `bench partial-restore` to restore a partial backup to an existing site.", + fg="yellow", ) _backup.decryption_rollback() sys.exit(1) @@ -199,11 +201,15 @@ def _restore( except UnicodeDecodeError: _backup.decryption_rollback() if encryption_key: - click.secho("Encrypted backup file detected. Decrypting using provided key.", fg="yellow") + click.secho( + "Encrypted backup file detected. Decrypting using provided key.", fg="yellow" + ) _backup.backup_decryption(encryption_key) else: - click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") + click.secho( + "Encrypted backup file detected. Decrypting using site config.", fg="yellow" + ) encryption_key = get_or_generate_backup_encryption_key() _backup.backup_decryption(encryption_key) @@ -222,7 +228,8 @@ def _restore( fg="red", ) click.secho( - "Use `bench partial-restore` to restore a partial backup to an existing site.", fg="yellow" + "Use `bench partial-restore` to restore a partial backup to an existing site.", + fg="yellow", ) _backup.decryption_rollback() sys.exit(1) @@ -324,7 +331,8 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None): # Check for full backup file if "Partial Backup" not in header: click.secho( - "Full backup file detected.Use `bench restore` to restore a Frappe Site.", fg="red" + "Full backup file detected.Use `bench restore` to restore a Frappe Site.", + fg="red", ) _backup.decryption_rollback() sys.exit(1) @@ -332,11 +340,15 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None): except UnicodeDecodeError: _backup.decryption_rollback() if encryption_key: - click.secho("Encrypted backup file detected. Decrypting using provided key.", fg="yellow") + click.secho( + "Encrypted backup file detected. Decrypting using provided key.", fg="yellow" + ) key = encryption_key else: - click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") + click.secho( + "Encrypted backup file detected. Decrypting using site config.", fg="yellow" + ) key = get_or_generate_backup_encryption_key() _backup.backup_decryption(key) @@ -355,7 +367,8 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None): # Check for Full backup file. if "Partial Backup" not in header: click.secho( - "Full Backup file detected.Use `bench restore` to restore a Frappe Site.", fg="red" + "Full Backup file detected.Use `bench restore` to restore a Frappe Site.", + fg="red", ) _backup.decryption_rollback() sys.exit(1) @@ -387,17 +400,26 @@ def reinstall( ): "Reinstall site ie. wipe all data and start over" site = get_site(context) - _reinstall(site, admin_password, db_root_username, db_root_password, yes, verbose=context.verbose) + _reinstall( + site, admin_password, db_root_username, db_root_password, yes, verbose=context.verbose + ) def _reinstall( - site, admin_password=None, db_root_username=None, db_root_password=None, yes=False, verbose=False + site, + admin_password=None, + db_root_username=None, + db_root_password=None, + yes=False, + verbose=False, ): from frappe.installer import _new_site from frappe.utils.synchronization import filelock if not yes: - click.confirm("This will wipe your database. Are you sure you want to reinstall?", abort=True) + click.confirm( + "This will wipe your database. Are you sure you want to reinstall?", abort=True + ) try: frappe.init(site=site) frappe.connect() @@ -487,7 +509,9 @@ def list_apps(context, format): apps = frappe.get_single("Installed Applications").installed_applications if apps: - name_len, ver_len = (max(len(x.get(y)) for x in apps) for y in ["app_name", "app_version"]) + name_len, ver_len = ( + max(len(x.get(y)) for x in apps) for y in ["app_name", "app_version"] + ) template = f"{{0:{name_len}}} {{1:{ver_len}}} {{2}}" installed_applications = [ @@ -528,7 +552,9 @@ def add_system_manager(context, email, first_name, last_name, send_welcome_email for site in context.sites: frappe.connect(site=site) try: - frappe.utils.user.add_system_manager(email, first_name, last_name, send_welcome_email, password) + frappe.utils.user.add_system_manager( + email, first_name, last_name, send_welcome_email, password + ) frappe.db.commit() finally: frappe.destroy() @@ -554,7 +580,9 @@ def add_user_for_sites( for site in context.sites: frappe.connect(site=site) try: - add_new_user(email, first_name, last_name, user_type, send_welcome_email, password, add_role) + add_new_user( + email, first_name, last_name, user_type, send_welcome_email, password, add_role + ) frappe.db.commit() finally: frappe.destroy() @@ -719,7 +747,10 @@ def use(site, sites_path="."): @click.option("--backup-path-private-files", default=None, help="Set path for saving private file") @click.option("--backup-path-conf", default=None, help="Set path for saving config file") @click.option( - "--ignore-backup-conf", default=False, is_flag=True, help="Ignore excludes/includes set in config" + "--ignore-backup-conf", + default=False, + is_flag=True, + help="Ignore excludes/includes set in config", ) @click.option("--verbose", default=False, is_flag=True, help="Add verbosity") @click.option("--compress", default=False, is_flag=True, help="Compress private and public files") @@ -772,9 +803,13 @@ def backup( print(frappe.get_traceback()) exit_code = 1 continue - if frappe.get_system_settings("encrypt_backup") and frappe.get_site_config().encryption_key: + if ( + frappe.get_system_settings("encrypt_backup") + and frappe.get_site_config().encryption_key + ): click.secho( - "Backup encryption is turned on. Please note the backup encryption key.", fg="yellow" + "Backup encryption is turned on. Please note the backup encryption key.", + fg="yellow", ) odb.print_summary() @@ -835,7 +870,9 @@ def uninstall(context, app, dry_run, yes, no_backup, force): frappe.init(site=site) frappe.connect() with filelock("uninstall_app"): - remove_app(app_name=app, dry_run=dry_run, yes=yes, no_backup=no_backup, force=force) + remove_app( + app_name=app, dry_run=dry_run, yes=yes, no_backup=no_backup, force=force + ) finally: frappe.destroy() if not context.sites: @@ -1128,13 +1165,14 @@ def start_ngrok(context, bind_tls): site = get_site(context) frappe.init(site=site) - ngrok_auth_token = frappe.conf.ngrok_auth_token - if not ngrok_auth_token: - frappe.errprint( - "'ngrok_auth_token' not found in site config. Please register for a free ngrok account at: https://dashboard.ngrok.com/signup and place the obtained authtoken in site_config.json file." + ngrok_authtoken = frappe.conf.ngrok_authtoken + if not ngrok_authtoken: + click.echo( + f"{click.style('ngrok_authtoken', bold=True)} not found in site config. Please register for a free ngrok account at: https://dashboard.ngrok.com/signup and place the obtained authtoken in site_config.json file.\n", + err=True, ) - exit(0) - ngrok.set_auth_token(ngrok_auth_token) + sys.exit(1) + ngrok.set_auth_token(ngrok_authtoken) port = frappe.conf.http_port or frappe.conf.webserver_port tunnel = ngrok.connect(addr=str(port), host_header=site, bind_tls=bind_tls) @@ -1354,7 +1392,9 @@ def trim_tables(context, dry_run, format, no_backup): trimmed_data = trim_tables(dry_run=dry_run, quiet=format == "json") if format == "table" and not dry_run: - click.secho(f"The following data have been removed from {frappe.local.site}", fg="green") + click.secho( + f"The following data have been removed from {frappe.local.site}", fg="green" + ) handle_data(trimmed_data, format=format) finally: @@ -1369,7 +1409,9 @@ def handle_data(data: dict, format="json"): else: from frappe.utils.commands import render_table - data = [["DocType", "Fields"]] + [[table, ", ".join(columns)] for table, columns in data.items()] + data = [["DocType", "Fields"]] + [ + [table, ", ".join(columns)] for table, columns in data.items() + ] render_table(data) From 048de262fd665a49b27d9a7202d1ff0d3fbb345b Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Thu, 29 Dec 2022 11:05:46 +0530 Subject: [PATCH 03/12] fix: don't set default in list view for fields not allowed --- frappe/core/doctype/doctype/doctype.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index e3f8ffd503..e1bb23b388 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -195,10 +195,12 @@ class DocType(Document): def set_default_in_list_view(self): """Set default in-list-view for first 4 mandatory fields""" + not_allowed_in_list_view = get_fields_not_allowed_in_list_view(self.meta) + if not [d.fieldname for d in self.fields if d.in_list_view]: cnt = 0 for d in self.fields: - if d.reqd and not d.hidden and not d.fieldtype in table_fields: + if d.reqd and not d.hidden and not d.fieldtype in not_allowed_in_list_view: d.in_list_view = 1 cnt += 1 if cnt == 4: @@ -1446,10 +1448,7 @@ def validate_fields(meta): fields = meta.get("fields") fieldname_list = [d.fieldname for d in fields] - not_allowed_in_list_view = list(copy.copy(no_value_fields)) - not_allowed_in_list_view.append("Attach Image") - if meta.istable: - not_allowed_in_list_view.remove("Button") + not_allowed_in_list_view = get_fields_not_allowed_in_list_view(meta) for d in fields: if not d.permlevel: @@ -1490,6 +1489,14 @@ def validate_fields(meta): check_image_field(meta) +def get_fields_not_allowed_in_list_view(meta) -> list[str]: + not_allowed_in_list_view = list(copy.copy(no_value_fields)) + not_allowed_in_list_view.append("Attach Image") + if meta.istable: + not_allowed_in_list_view.remove("Button") + return not_allowed_in_list_view + + def validate_permissions_for_doctype(doctype, for_remove=False, alert=False): """Validates if permissions are set correctly.""" doctype = frappe.get_doc("DocType", doctype) From f1553c479c9a98fa8a91f9f8f1eca773312892a4 Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Thu, 29 Dec 2022 16:20:07 +0530 Subject: [PATCH 04/12] fix(test): override fields of test doctype if passed --- frappe/core/doctype/doctype/test_doctype.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 2e74fd3a6a..916c29ebff 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -759,8 +759,7 @@ def new_doctype( } ) - if fields: - for f in fields: - doc.append("fields", f) + if fields and len(fields) > 0: + doc.set("fields", fields) return doc From e96ce833439d559bdd741398aae804d03562f31d Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Thu, 29 Dec 2022 16:22:06 +0530 Subject: [PATCH 05/12] test: not in list view by default for not allowed mandatory field types --- frappe/core/doctype/doctype/test_doctype.py | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 916c29ebff..e8226d4f9d 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -722,6 +722,28 @@ class TestDocType(FrappeTestCase): self.assertEqual(frappe.get_meta(doctype).get_field(field).default, "DELETETHIS") frappe.delete_doc("DocType", doctype) + def test_not_in_list_view_for_not_allowed_mandatory_field(self): + doctype = new_doctype( + fields=[ + { + "fieldname": "cover_image", + "fieldtype": "Attach Image", + "label": "Cover Image", + "reqd": 1, # mandatory + }, + { + "fieldname": "book_name", + "fieldtype": "Data", + "label": "Book Name", + "reqd": 1, # mandatory + }, + ], + ).insert() + + self.assertFalse(doctype.fields[0].in_list_view) + self.assertTrue(doctype.fields[1].in_list_view) + frappe.delete_doc("DocType", doctype.name) + def new_doctype( name: str | None = None, From 31d1bd6cc767aa670871f9fb20b292ea7aaeeef1 Mon Sep 17 00:00:00 2001 From: phot0n Date: Fri, 30 Dec 2022 19:27:17 +0530 Subject: [PATCH 06/12] chore: linter --- frappe/commands/site.py | 53 ++++++++++------------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 91e439dfeb..2f111200e5 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -201,15 +201,11 @@ def _restore( except UnicodeDecodeError: _backup.decryption_rollback() if encryption_key: - click.secho( - "Encrypted backup file detected. Decrypting using provided key.", fg="yellow" - ) + click.secho("Encrypted backup file detected. Decrypting using provided key.", fg="yellow") _backup.backup_decryption(encryption_key) else: - click.secho( - "Encrypted backup file detected. Decrypting using site config.", fg="yellow" - ) + click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") encryption_key = get_or_generate_backup_encryption_key() _backup.backup_decryption(encryption_key) @@ -340,15 +336,11 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None): except UnicodeDecodeError: _backup.decryption_rollback() if encryption_key: - click.secho( - "Encrypted backup file detected. Decrypting using provided key.", fg="yellow" - ) + click.secho("Encrypted backup file detected. Decrypting using provided key.", fg="yellow") key = encryption_key else: - click.secho( - "Encrypted backup file detected. Decrypting using site config.", fg="yellow" - ) + click.secho("Encrypted backup file detected. Decrypting using site config.", fg="yellow") key = get_or_generate_backup_encryption_key() _backup.backup_decryption(key) @@ -400,9 +392,7 @@ def reinstall( ): "Reinstall site ie. wipe all data and start over" site = get_site(context) - _reinstall( - site, admin_password, db_root_username, db_root_password, yes, verbose=context.verbose - ) + _reinstall(site, admin_password, db_root_username, db_root_password, yes, verbose=context.verbose) def _reinstall( @@ -417,9 +407,7 @@ def _reinstall( from frappe.utils.synchronization import filelock if not yes: - click.confirm( - "This will wipe your database. Are you sure you want to reinstall?", abort=True - ) + click.confirm("This will wipe your database. Are you sure you want to reinstall?", abort=True) try: frappe.init(site=site) frappe.connect() @@ -509,9 +497,7 @@ def list_apps(context, format): apps = frappe.get_single("Installed Applications").installed_applications if apps: - name_len, ver_len = ( - max(len(x.get(y)) for x in apps) for y in ["app_name", "app_version"] - ) + name_len, ver_len = (max(len(x.get(y)) for x in apps) for y in ["app_name", "app_version"]) template = f"{{0:{name_len}}} {{1:{ver_len}}} {{2}}" installed_applications = [ @@ -552,9 +538,7 @@ def add_system_manager(context, email, first_name, last_name, send_welcome_email for site in context.sites: frappe.connect(site=site) try: - frappe.utils.user.add_system_manager( - email, first_name, last_name, send_welcome_email, password - ) + frappe.utils.user.add_system_manager(email, first_name, last_name, send_welcome_email, password) frappe.db.commit() finally: frappe.destroy() @@ -580,9 +564,7 @@ def add_user_for_sites( for site in context.sites: frappe.connect(site=site) try: - add_new_user( - email, first_name, last_name, user_type, send_welcome_email, password, add_role - ) + add_new_user(email, first_name, last_name, user_type, send_welcome_email, password, add_role) frappe.db.commit() finally: frappe.destroy() @@ -803,10 +785,7 @@ def backup( print(frappe.get_traceback()) exit_code = 1 continue - if ( - frappe.get_system_settings("encrypt_backup") - and frappe.get_site_config().encryption_key - ): + if frappe.get_system_settings("encrypt_backup") and frappe.get_site_config().encryption_key: click.secho( "Backup encryption is turned on. Please note the backup encryption key.", fg="yellow", @@ -870,9 +849,7 @@ def uninstall(context, app, dry_run, yes, no_backup, force): frappe.init(site=site) frappe.connect() with filelock("uninstall_app"): - remove_app( - app_name=app, dry_run=dry_run, yes=yes, no_backup=no_backup, force=force - ) + remove_app(app_name=app, dry_run=dry_run, yes=yes, no_backup=no_backup, force=force) finally: frappe.destroy() if not context.sites: @@ -1392,9 +1369,7 @@ def trim_tables(context, dry_run, format, no_backup): trimmed_data = trim_tables(dry_run=dry_run, quiet=format == "json") if format == "table" and not dry_run: - click.secho( - f"The following data have been removed from {frappe.local.site}", fg="green" - ) + click.secho(f"The following data have been removed from {frappe.local.site}", fg="green") handle_data(trimmed_data, format=format) finally: @@ -1409,9 +1384,7 @@ def handle_data(data: dict, format="json"): else: from frappe.utils.commands import render_table - data = [["DocType", "Fields"]] + [ - [table, ", ".join(columns)] for table, columns in data.items() - ] + data = [["DocType", "Fields"]] + [[table, ", ".join(columns)] for table, columns in data.items()] render_table(data) From 0e9d16820b6342294559fb6c9c8acffc05001109 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 2 Jan 2023 11:35:21 +0530 Subject: [PATCH 07/12] fix: For Update for child table (#19436) --- frappe/model/document.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/model/document.py b/frappe/model/document.py index 773ee4a764..7222cf4ad6 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -178,6 +178,7 @@ class Document(BaseDocument): "*", as_dict=True, order_by="idx asc", + for_update=self.flags.for_update, ) or [] ) From 4d048cd651b2250031918e706e327124a3fa681e Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 2 Jan 2023 11:50:25 +0530 Subject: [PATCH 08/12] fix: type hint for image view closes https://github.com/frappe/frappe/issues/19426 --- frappe/core/api/file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/api/file.py b/frappe/core/api/file.py index c2354516a8..e3e6a9de08 100644 --- a/frappe/core/api/file.py +++ b/frappe/core/api/file.py @@ -13,7 +13,7 @@ def unzip_file(name: str): @frappe.whitelist() -def get_attached_images(doctype: str, names: list[str]) -> frappe._dict: +def get_attached_images(doctype: str, names: list[str] | str) -> frappe._dict: """get list of image urls attached in form returns {name: ['image.jpg', 'image.png']}""" From 5ece1d7c394a80f2d63828601afe517c08cc676c Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 2 Jan 2023 12:01:32 +0530 Subject: [PATCH 09/12] fix: Allow everyone to read geo data (#19451) This is static data present in code, no need to apply permissions. closes https://github.com/frappe/frappe/issues/19394 --- frappe/geo/country_info.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frappe/geo/country_info.py b/frappe/geo/country_info.py index 2aefa27170..3267149d4c 100644 --- a/frappe/geo/country_info.py +++ b/frappe/geo/country_info.py @@ -5,6 +5,7 @@ import json # all country info import os +from functools import lru_cache import frappe from frappe.utils.momentjs import get_all_timezones @@ -27,8 +28,13 @@ def get_all(): return all_data -@frappe.whitelist() +@frappe.whitelist(allow_guest=True) def get_country_timezone_info(): + return _get_country_timezone_info() + + +@lru_cache(maxsize=2) +def _get_country_timezone_info(): return {"country_info": get_all(), "all_timezones": get_all_timezones()} From 16eeedc28c1a070be87ac9278d5f24d44413e15b Mon Sep 17 00:00:00 2001 From: phot0n Date: Mon, 2 Jan 2023 16:12:21 +0530 Subject: [PATCH 10/12] feat(minor): add use-default-authtoken to ngrok command --- frappe/commands/site.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/frappe/commands/site.py b/frappe/commands/site.py index 2f111200e5..fbbdde8e03 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -1134,8 +1134,14 @@ def stop_recording(context): @click.option( "--bind-tls", is_flag=True, default=False, help="Returns a reference to the https tunnel." ) +@click.option( + "--use-default-authtoken", + is_flag=True, + default=False, + help="Use the auth token present in ngrok's config.", +) @pass_context -def start_ngrok(context, bind_tls): +def start_ngrok(context, bind_tls, use_default_authtoken): """Start a ngrok tunnel to your local development server.""" from pyngrok import ngrok @@ -1143,13 +1149,15 @@ def start_ngrok(context, bind_tls): frappe.init(site=site) ngrok_authtoken = frappe.conf.ngrok_authtoken - if not ngrok_authtoken: - click.echo( - f"{click.style('ngrok_authtoken', bold=True)} not found in site config. Please register for a free ngrok account at: https://dashboard.ngrok.com/signup and place the obtained authtoken in site_config.json file.\n", - err=True, - ) - sys.exit(1) - ngrok.set_auth_token(ngrok_authtoken) + if not use_default_authtoken: + if not ngrok_authtoken: + click.echo( + f"\n{click.style('ngrok_authtoken', fg='yellow')} not found in site config.\n" + "Please register for a free ngrok account at: https://dashboard.ngrok.com/signup and place the obtained authtoken in the site config.", + ) + sys.exit(1) + + ngrok.set_auth_token(ngrok_authtoken) port = frappe.conf.http_port or frappe.conf.webserver_port tunnel = ngrok.connect(addr=str(port), host_header=site, bind_tls=bind_tls) From 2937b09a220cb2f061a396083cddc8e23a0186a0 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 2 Jan 2023 16:32:27 +0530 Subject: [PATCH 11/12] fix: hide tooltip content on webform --- frappe/public/scss/website/web_form.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/public/scss/website/web_form.scss b/frappe/public/scss/website/web_form.scss index 8ecf753384..e1ca8b8f58 100644 --- a/frappe/public/scss/website/web_form.scss +++ b/frappe/public/scss/website/web_form.scss @@ -18,6 +18,10 @@ .page_content { max-width: 800px; margin: auto; + + .tooltip-content { + display: none; + } h1 { font-size: 2.25rem; From 81066d7562e54d71831497a57aa24a84a3d2b0c3 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 2 Jan 2023 15:30:09 +0530 Subject: [PATCH 12/12] fix: only allow system manager to create email templates --- frappe/email/doctype/email_template/email_template.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frappe/email/doctype/email_template/email_template.json b/frappe/email/doctype/email_template/email_template.json index c6ec971da4..00f1428475 100644 --- a/frappe/email/doctype/email_template/email_template.json +++ b/frappe/email/doctype/email_template/email_template.json @@ -57,18 +57,16 @@ ], "icon": "fa fa-comment", "links": [], - "modified": "2022-01-04 14:12:50.321633", + "modified": "2023-01-02 03:56:48.437280", "modified_by": "Administrator", "module": "Email", "name": "Email Template", + "naming_rule": "Set by user", "owner": "Administrator", "permissions": [ { - "create": 1, "read": 1, - "role": "All", - "share": 1, - "write": 1 + "role": "All" }, { "create": 1, @@ -85,5 +83,6 @@ ], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file