internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: frappe/frappe

Issue:
PostgreSQL - permission denied for schema public
<!--
Welcome to the Frappe Framework issue tracker! Before creating an issue, please heed the following:

1. This tracker should only be used to report bugs and request features / enhancements to Frappe
    - For questions and general support, use https://stackoverflow.com/questions/tagged/frappe
    - For documentation issues, refer to https://frappeframework.com/docs/user/en or the developer cheetsheet https://github.com/frappe/frappe/wiki/Developer-Cheatsheet
2. Use the search function before creating a new issue. Duplicates will be closed and directed to
   the original discussion.
3. When making a bug report, make sure you provide all required information. The easier it is for
   maintainers to reproduce, the faster it'll be fixed.
4. If you think you know what the reason for the bug is, share it with us. Maybe put in a PR 😉
-->

## Description of the issue
When PostgreSQL version 15 or greater is used, the `bench new-site` command files with insufficient permission error from PostgreSQL. This is due to the change introduced, where `PostgreSQL 15 also revokes the CREATE permission from all users except a database owner from the public (or default) schema.`

## Context information (for bug reports)

**Output of `bench version`**
```
5.19.0
```

## Steps to reproduce the issue

1. Configure Frappe to use PostgreSQL version which is 15 or greater (16.1 in my case)
2. Attempt to perform `bench new-site` (Ex: ERPNext)

### Observed result
Error from Postgres:
```
ERROR:  permission denied for schema public at character 14
```

Error from Frappe:
```
psql:/home/frappe/frappe-bench/apps/frappe/frappe/database/postgres/framework_postgres.sql:72: ERROR:  permission denied for schema public
```

### Expected result
Installation should proceed without any errors





Discussion:

Resolving patch:
diff --git a/frappe/database/postgres/setup_db.py b/frappe/database/postgres/setup_db.py
--- a/frappe/database/postgres/setup_db.py
+++ b/frappe/database/postgres/setup_db.py
@@ -13,6 +13,9 @@ def setup_database():
 	root_conn.sql(f"CREATE DATABASE `{frappe.conf.db_name}`")
 	root_conn.sql(f"CREATE user {frappe.conf.db_name} password '{frappe.conf.db_password}'")
 	root_conn.sql("GRANT ALL PRIVILEGES ON DATABASE `{0}` TO {0}".format(frappe.conf.db_name))
+	psql_version = root_conn.sql(f"SELECT VERSION()", as_dict=True)
+	if psql_version and psql_version[0].get("version", "PostgreSQL 14").split()[1] >= "15":
+		root_conn.sql("ALTER DATABASE `{0}` OWNER TO {0}".format(frappe.conf.db_name))
 	root_conn.close()
 
 


Test patch:
Repository: frappe/frappe

Issue:
Navbar icon not working
In 'website settings' under 'navbar' it is possible to set an icon for an individual navbar tab. However, when setting an icon it is not showing up on the website.



Discussion:

Resolving patch:
diff --git a/frappe/website/doctype/top_bar_item/top_bar_item.py b/frappe/website/doctype/top_bar_item/top_bar_item.py
--- a/frappe/website/doctype/top_bar_item/top_bar_item.py
+++ b/frappe/website/doctype/top_bar_item/top_bar_item.py
@@ -14,7 +14,6 @@ class TopBarItem(Document):
 	if TYPE_CHECKING:
 		from frappe.types import DF
 
-		icon: DF.AttachImage | None
 		label: DF.Data
 		open_in_new_tab: DF.Check
 		parent: DF.Data
@@ -24,4 +23,5 @@ class TopBarItem(Document):
 		right: DF.Check
 		url: DF.Data | None
 	# end: auto-generated types
+
 	pass
diff --git a/frappe/website/doctype/website_settings/website_settings.py b/frappe/website/doctype/website_settings/website_settings.py
--- a/frappe/website/doctype/website_settings/website_settings.py
+++ b/frappe/website/doctype/website_settings/website_settings.py
@@ -56,6 +56,7 @@ class WebsiteSettings(Document):
 		robots_txt: DF.Code | None
 		route_redirects: DF.Table[WebsiteRouteRedirect]
 		show_account_deletion_link: DF.Check
+		show_footer_on_login: DF.Check
 		show_language_picker: DF.Check
 		splash_image: DF.AttachImage | None
 		subdomain: DF.SmallText | None
@@ -63,8 +64,8 @@ class WebsiteSettings(Document):
 		top_bar_items: DF.Table[TopBarItem]
 		website_theme: DF.Link | None
 		website_theme_image_link: DF.Code | None
-
 	# end: auto-generated types
+
 	def validate(self):
 		self.validate_top_bar_items()
 		self.validate_footer_items()
diff --git a/frappe/www/login.py b/frappe/www/login.py
--- a/frappe/www/login.py
+++ b/frappe/www/login.py
@@ -37,6 +37,7 @@ def get_context(context):
 	context["hide_login"] = True  # dont show login link on login page again.
 	context["provider_logins"] = []
 	context["disable_signup"] = cint(frappe.get_website_settings("disable_signup"))
+	context["show_footer_on_login"] = cint(frappe.get_website_settings("show_footer_on_login"))
 	context["disable_user_pass_login"] = cint(frappe.get_system_settings("disable_user_pass_login"))
 	context["logo"] = frappe.get_website_settings("app_logo") or frappe.get_hooks("app_logo_url")[-1]
 	context["app_name"] = (


Test patch:
Repository: frappe/frappe

Issue:
bug: user_info for Administrator getting set twice
## Description of the issue
https://github.com/frappe/frappe/blob/730e906dfdf0b6658a9810edf45808174922c391/frappe/boot.py#L267-L275

When logged in as Administrator the user_info in frappe.boot.user_info in frontend is getting set twice for Administrator user, one using "Administrator" name and another by Administrator's email, for e.g. `admin@example.com`. Consequently, if another user shares the same email address that the Administrator user has in their User record, the user_info for that specific user isn't added in frappe.boot.user_info. This issue arises because the key already exists in frappe.boot.user_info due to the earlier addition of user_info for the Administrator user.

This situation leads to a problem: if a document record is generated by the aforementioned user with a matching email, when the Administrator user accesses the document, it falsely displays that the "Administrator" created or modified the document. In reality, the document was originally created or modified by the other user. It's important to note that this bug exclusively affects the Administrator's view of the document. For all other users, the document appropriately attributes its creation or modification to the actual user who performed those actions.

@surajshetty3416, can you please look into this.

### Observed result
When Administrator is viewing the document record:

![image](https://github.com/frappe/frappe/assets/40106895/11e978c8-61f9-47cf-b509-e25c4c0d78a6)

When other users are viewing the same document record:

![image](https://github.com/frappe/frappe/assets/40106895/f6b2c3b1-0983-46ef-93e5-bd16b52fcb80)

### Additional information

Frappe Version: v14.45.0





Discussion:

Resolving patch:
diff --git a/frappe/boot.py b/frappe/boot.py
--- a/frappe/boot.py
+++ b/frappe/boot.py
@@ -270,9 +270,6 @@ def get_user_info():
 	user_info = frappe._dict()
 	add_user_info(frappe.session.user, user_info)
 
-	if frappe.session.user == "Administrator" and user_info.Administrator.email:
-		user_info[user_info.Administrator.email] = user_info.Administrator
-
 	return user_info
 
 


Test patch:
Repository: frappe/frappe

Issue:
Navbar icon not working
In 'website settings' under 'navbar' it is possible to set an icon for an individual navbar tab. However, when setting an icon it is not showing up on the website.



Discussion:

Resolving patch:
diff --git a/frappe/website/doctype/top_bar_item/top_bar_item.py b/frappe/website/doctype/top_bar_item/top_bar_item.py
--- a/frappe/website/doctype/top_bar_item/top_bar_item.py
+++ b/frappe/website/doctype/top_bar_item/top_bar_item.py
@@ -14,7 +14,6 @@ class TopBarItem(Document):
 	if TYPE_CHECKING:
 		from frappe.types import DF
 
-		icon: DF.AttachImage | None
 		label: DF.Data
 		open_in_new_tab: DF.Check
 		parent: DF.Data
@@ -24,4 +23,5 @@ class TopBarItem(Document):
 		right: DF.Check
 		url: DF.Data | None
 	# end: auto-generated types
+
 	pass
diff --git a/frappe/website/doctype/website_settings/website_settings.py b/frappe/website/doctype/website_settings/website_settings.py
--- a/frappe/website/doctype/website_settings/website_settings.py
+++ b/frappe/website/doctype/website_settings/website_settings.py
@@ -56,6 +56,7 @@ class WebsiteSettings(Document):
 		robots_txt: DF.Code | None
 		route_redirects: DF.Table[WebsiteRouteRedirect]
 		show_account_deletion_link: DF.Check
+		show_footer_on_login: DF.Check
 		show_language_picker: DF.Check
 		splash_image: DF.AttachImage | None
 		subdomain: DF.SmallText | None
@@ -64,6 +65,7 @@ class WebsiteSettings(Document):
 		website_theme: DF.Link | None
 		website_theme_image_link: DF.Code | None
 	# end: auto-generated types
+
 	def validate(self):
 		self.validate_top_bar_items()
 		self.validate_footer_items()
diff --git a/frappe/www/login.py b/frappe/www/login.py
--- a/frappe/www/login.py
+++ b/frappe/www/login.py
@@ -37,6 +37,7 @@ def get_context(context):
 	context["hide_login"] = True  # dont show login link on login page again.
 	context["provider_logins"] = []
 	context["disable_signup"] = cint(frappe.get_website_settings("disable_signup"))
+	context["show_footer_on_login"] = cint(frappe.get_website_settings("show_footer_on_login"))
 	context["disable_user_pass_login"] = cint(frappe.get_system_settings("disable_user_pass_login"))
 	context["logo"] = frappe.get_website_settings("app_logo") or frappe.get_hooks("app_logo_url")[-1]
 	context["app_name"] = (


Test patch:
Repository: frappe/frappe

Issue:
Email display name is converted to all lowercase
https://github.com/frappe/frappe/blob/53b074c16a0cf5de74e37f0fd87e2df9b113726f/frappe/core/doctype/communication/communication.py#L212

This results in emails sent to:

"Herr Dr. Hans Mustermann" \<mustermann@example.com\>

get received with:

herr dr. hans mustermann

as name.

It might be considered offensive in some cultures, especially those with a salutation of Dr. etc.




Discussion:

Resolving patch:
diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py
--- a/frappe/core/doctype/communication/communication.py
+++ b/frappe/core/doctype/communication/communication.py
@@ -306,7 +306,7 @@ def _get_emails_list(emails=None, exclude_displayname=False):
 		emails = split_emails(emails) if isinstance(emails, str) else (emails or [])
 		if exclude_displayname:
 			return [email.lower() for email in {parse_addr(email)[1] for email in emails} if email]
-		return [email.lower() for email in set(emails) if email]
+		return [email for email in set(emails) if email]
 
 	def to_list(self, exclude_displayname=True):
 		"""Return `to` list."""


Test patch:
Repository: frappe/frappe

Issue:
v15: Workspace name, title & label - symbols wrongly encoded by escape_html
`test & test` becomes `test &amp; test`

https://github.com/frappe/frappe/blob/6f36c0fa0ba48356e1b077df5fc97c08193d5b87/frappe/public/js/frappe/views/workspace/workspace.js#L1214C2-L1214C2


Discussion:

Resolving patch:
diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py
--- a/frappe/desk/doctype/workspace/workspace.py
+++ b/frappe/desk/doctype/workspace/workspace.py
@@ -11,6 +11,7 @@
 from frappe.model.document import Document
 from frappe.model.rename_doc import rename_doc
 from frappe.modules.export_file import delete_folder, export_to_files
+from frappe.utils import strip_html
 
 
 class Workspace(Document):
@@ -65,6 +66,8 @@ class Workspace(Document):
 		title: DF.Data
 	# end: auto-generated types
 	def validate(self):
+		self.title = strip_html(self.title)
+
 		if self.public and not is_workspace_manager() and not disable_saving_as_public():
 			frappe.throw(_("You need to be Workspace Manager to edit this document"))
 		if self.has_value_changed("title"):
@@ -275,6 +278,8 @@ def save_page(title, public, new_widgets, blocks):
 	pages = frappe.get_all("Workspace", filters=filters)
 	if pages:
 		doc = frappe.get_doc("Workspace", pages[0])
+	else:
+		frappe.throw(_("Workspace not found"), frappe.DoesNotExistError)
 
 	doc.content = blocks
 
diff --git a/frappe/patches/v15_0/sanitize_workspace_titles.py b/frappe/patches/v15_0/sanitize_workspace_titles.py
new file mode 100644
--- /dev/null
+++ b/frappe/patches/v15_0/sanitize_workspace_titles.py
@@ -0,0 +1,25 @@
+import frappe
+from frappe.desk.doctype.workspace.workspace import update_page
+from frappe.utils import strip_html
+from frappe.utils.html_utils import unescape_html
+
+
+def execute():
+	workspaces_to_update = frappe.get_all(
+		"Workspace",
+		filters={"module": ("is", "not set")},
+		fields=["name", "title", "icon", "indicator_color", "parent_page as parent", "public"],
+	)
+	for workspace in workspaces_to_update:
+		new_title = strip_html(unescape_html(workspace.title))
+
+		if new_title == workspace.title:
+			continue
+
+		workspace.title = new_title
+		try:
+			update_page(**workspace)
+			frappe.db.commit()
+
+		except Exception:
+			frappe.db.rollback()


Test patch:
Repository: frappe/frappe

Issue:
Restoring encrypted backup failure
## Description of the issue

- Trying to restore an encrypted backup for a site fails if the `gpg` package is not installed and the default failure message is thrown which is ` Decryption failed due to invalid encryption key ` even with the correct encryption key. A better error message would help here.

- Even though the decryption fails, the logic to add the `.gpg` extension still runs and the old name changes so re-running the restore command doesn't work unless the user manually changes the name back to the old one before re-attempting the restore. 



Discussion:

Resolving patch:
diff --git a/frappe/utils/backups.py b/frappe/utils/backups.py
--- a/frappe/utils/backups.py
+++ b/frappe/utils/backups.py
@@ -661,13 +661,15 @@ def decrypt_backup(file_path: str, passphrase: str):
 			decrypted_file=file_path,
 		)
 	frappe.utils.execute_in_shell(command)
-	yield
-	if os.path.exists(file_path + ".gpg"):
-		if os.path.exists(file_path):
-			os.remove(file_path)
-		if os.path.exists(file_path.rstrip(".gz")):
-			os.remove(file_path.rstrip(".gz"))
-		os.rename(file_path + ".gpg", file_path)
+	try:
+		yield
+	finally:
+		if os.path.exists(file_path_with_ext):
+			if os.path.exists(file_path):
+				os.remove(file_path)
+			if os.path.exists(file_path.rstrip(".gz")):
+				os.remove(file_path.rstrip(".gz"))
+			os.rename(file_path_with_ext, file_path)
 
 
 def backup(


Test patch:
Repository: frappe/frappe

Issue:
`money_in_words`: Why is the result of num2words translated again?
# Issue

In French, **100** is called _Cent_. However, because of the extra translation **100** becomes _Centime_ instead (one _centime_ is <sup>1</sup>/<sub>100th</sub> of a € which is extra confusing). It's like saying "$100" = "cents dollar" or "₹ 100" = "Paise Rupee", makes no sense.

# Discussion
`in_words(…).title()` already gives back a translated string, is it really needed to translate it again? Is it a feature required by some languages?

https://github.com/frappe/frappe/blob/63e2e2db56e6639d96b376863cde35a38ef8afc0/frappe/utils/data.py#L1518-L1530

```diff
Suggested change
- _(in_words(fraction, in_million).title())
+   in_words(fraction, in_million).title()
```

Original PR [#3358](https://github.com/frappe/frappe/pull/3358/files#diff-593e371f8b132db49a3762060b70e1a32493b58ae5673086132ecba513938c74R457-R461) by @tundebabzy.



Discussion:

Resolving patch:
diff --git a/frappe/utils/data.py b/frappe/utils/data.py
--- a/frappe/utils/data.py
+++ b/frappe/utils/data.py
@@ -1518,18 +1518,12 @@ def money_in_words(
 		out = _(main_currency, context="Currency") + " " + _("Zero")
 	# 0.XX
 	elif main == "0":
-		out = _(in_words(fraction, in_million).title()) + " " + fraction_currency
+		out = in_words(fraction, in_million).title() + " " + fraction_currency
 	else:
-		out = _(main_currency, context="Currency") + " " + _(in_words(main, in_million).title())
+		out = _(main_currency, context="Currency") + " " + in_words(main, in_million).title()
 		if cint(fraction):
 			out = (
-				out
-				+ " "
-				+ _("and")
-				+ " "
-				+ _(in_words(fraction, in_million).title())
-				+ " "
-				+ fraction_currency
+				out + " " + _("and") + " " + in_words(fraction, in_million).title() + " " + fraction_currency
 			)
 
 	return _("{0} only.", context="Money in words").format(out)


Test patch:
Repository: frappe/frappe

Issue:
Hook for frappe.conf
People want to use secret manager to avoid storing anything in config files. Right now we have no mechanism to inject these in config. 

Possible solution: Hooks inside site config to extend the config. 

Hooks can look like this. 

```js
// site_config.json
{
   "extend_config": "vault.config.fetch_secrets",
}
```

We can then modify `get_site_config` to update `frappe.conf` with additional keys received from hooks. Hooks can technically do arbitrary side-effects too if they want to :shrug: 

Those who write this hook should ensure that they are almost instant. If they make a network call then that overhead will be added to _every request._ 

Note: This weird hook structure is required because normal hooks can only run after connecting to DB and fetching installed apps list. 




Discussion:

Resolving patch:
diff --git a/frappe/__init__.py b/frappe/__init__.py
--- a/frappe/__init__.py
+++ b/frappe/__init__.py
@@ -17,6 +17,7 @@
 import json
 import os
 import re
+import traceback
 import warnings
 from collections.abc import Callable
 from typing import TYPE_CHECKING, Any, Literal, Optional, TypeAlias, overload
@@ -435,6 +436,18 @@ def db_default_ports(db_type):
 		os.environ.get("FRAPPE_DB_USER") or config.get("db_user") or config.get("db_name")
 	)
 
+	# Allow externally extending the config with hooks
+	if extra_config := config.get("extra_config"):
+		if isinstance(extra_config, str):
+			extra_config = [extra_config]
+		for hook in extra_config:
+			try:
+				module, method = hook.rsplit(".", 1)
+				config |= getattr(importlib.import_module(module), method)()
+			except Exception:
+				print(f"Config hook {hook} failed")
+				traceback.print_exc()
+
 	return config
 
 


Test patch:
Repository: frappe/frappe

Issue:
Console import progress off-by-one
## Description of the issue
Data import utility displays incorrect progress in console mode due to off-by-one error since `frappe.publish_realtime()` takes 1-indexed progress while `update_progress_bar()` takes 0-indexed.


## Steps to reproduce the issue
Import any import file as is intended to be used.
```
frappe.core.doctype.data_import.data_import import import_file

import_file(doctype, file_path, 'insert' or 'update', console=True)
```

### Observed result
```
Importing 4 records                 : [==================================================] 125%
Successfully imported 4 records out of 4
```
### Expected result
```
Importing 4 records                 : [==================================================] 100%
Successfully imported 4 records out of 4
```



Discussion:

Resolving patch:
diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py
--- a/frappe/core/doctype/data_import/importer.py
+++ b/frappe/core/doctype/data_import/importer.py
@@ -149,8 +149,8 @@ def import_data(self):
 
 					if self.console:
 						update_progress_bar(
-							f"Importing {total_payload_count} records",
-							current_index,
+							f"Importing {self.doctype}: {total_payload_count} records",
+							current_index - 1,
 							total_payload_count,
 						)
 					elif total_payload_count > 5:


Test patch:
Repository: frappe/frappe

Issue:
Feature: Add ability to specify queue on webhooks
## Usecase
With webhooks being a great tool for publishing data on doc event's, when working with more `scalable systems` we often face cases where we are limited with the capability of using webhooks parallelly.  

## Solution
Having an ability to select **default** and **custom** queues for webhook can help with integrations.


## Benefits

- Parallel processing of events 
- More scalability 
- Distributed event propagation
- Independent/Async doc events
- High throughput and Horizontal scale



Discussion:

Resolving patch:
diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py
--- a/frappe/integrations/doctype/webhook/__init__.py
+++ b/frappe/integrations/doctype/webhook/__init__.py
@@ -8,7 +8,7 @@ def get_all_webhooks():
 	# query webhooks
 	webhooks_list = frappe.get_all(
 		"Webhook",
-		fields=["name", "condition", "webhook_docevent", "webhook_doctype"],
+		fields=["name", "condition", "webhook_docevent", "webhook_doctype", "background_jobs_queue"],
 		filters={"enabled": True},
 	)
 
@@ -104,4 +104,5 @@ def flush_webhook_execution_queue():
 			doc=instance.doc,
 			webhook=instance.webhook,
 			now=frappe.flags.in_test,
+			queue=instance.webhook.background_jobs_queue or "default",
 		)
diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py
--- a/frappe/integrations/doctype/webhook/webhook.py
+++ b/frappe/integrations/doctype/webhook/webhook.py
@@ -13,6 +13,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
+from frappe.utils.background_jobs import get_queues_timeout
 from frappe.utils.jinja import validate_template
 from frappe.utils.safe_exec import get_safe_globals
 
@@ -30,6 +31,7 @@ class Webhook(Document):
 		from frappe.integrations.doctype.webhook_header.webhook_header import WebhookHeader
 		from frappe.types import DF
 
+		background_jobs_queue: DF.Autocomplete | None
 		condition: DF.SmallText | None
 		enable_security: DF.Check
 		enabled: DF.Check
@@ -252,3 +254,11 @@ def get_webhook_data(doc, webhook):
 		data = json.loads(data)
 
 	return data
+
+
+@frappe.whitelist()
+def get_all_queues():
+	"""Fetches all workers and returns a list of available queue names."""
+	frappe.only_for("System Manager")
+
+	return get_queues_timeout().keys()


Test patch: