Skip to content

Commit

Permalink
Merge branch 'version-14' of https://github.com/frappe/frappe into ve…
Browse files Browse the repository at this point in the history
…rsion-14
  • Loading branch information
aliriocastro committed Oct 13, 2024
2 parents 50e478f + 43099de commit 468f3a9
Show file tree
Hide file tree
Showing 109 changed files with 957 additions and 556 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:

- name: Run Semgrep rules
run: |
pip install semgrep==0.97.0
pip install semgrep
semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
deps-vulnerable-check:
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ context("Navigation", () => {
cy.get("@reload").get(".page-card .btn-primary").contains("Login").click();
cy.location("pathname").should("eq", "/login");
cy.login();
cy.visit("/app");
cy.reload().as("reload");
cy.location("pathname").should("eq", "/app/todo");
});
});
11 changes: 7 additions & 4 deletions frappe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
)
from .utils.lazy_loader import lazy_import

__version__ = "14.77.1"
__version__ = "14.82.1"
__title__ = "Frappe Framework"

controllers = {}
Expand Down Expand Up @@ -791,7 +791,7 @@ def is_whitelisted(method):
summary = _("You are not permitted to access this resource.")
detail = _("Function {0} is not whitelisted.").format(bold(f"{method.__module__}.{method.__name__}"))
msg = f"<details><summary>{summary}</summary>{detail}</details>"
throw(msg, PermissionError, title="Method Not Allowed")
throw(msg, PermissionError, title=_("Method Not Allowed"))

if is_guest and method not in xss_safe_methods:
# strictly sanitize form_dict
Expand Down Expand Up @@ -2253,8 +2253,11 @@ def log_error(title=None, message=None, reference_doctype=None, reference_name=N


def get_desk_link(doctype, name):
html = '<a href="/app/Form/{doctype}/{name}" style="font-weight: bold;">{doctype_local} {name}</a>'
return html.format(doctype=doctype, name=name, doctype_local=_(doctype))
meta = get_meta(doctype)
title = get_value(doctype, name, meta.get_title_field())

html = '<a href="/app/Form/{doctype}/{name}" style="font-weight: bold;">{doctype_local} {title_local}</a>'
return html.format(doctype=doctype, name=name, doctype_local=_(doctype), title_local=_(title))


def bold(text):
Expand Down
3 changes: 2 additions & 1 deletion frappe/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ def handle_exception(e):
and (frappe.local.is_ajax or "application/json" in accept_header)
or (frappe.local.request.path.startswith("/api/") and not accept_header.startswith("text"))
)
allow_traceback = frappe.get_system_settings("allow_error_traceback") if frappe.db else False

if not frappe.session.user:
# If session creation fails then user won't be unset. This causes a lot of code that
Expand Down Expand Up @@ -350,7 +351,7 @@ def handle_exception(e):
else:
traceback = "<pre>" + escape_html(frappe.get_traceback()) + "</pre>"
# disable traceback in production if flag is set
if frappe.local.flags.disable_traceback and not frappe.local.dev_server:
if frappe.local.flags.disable_traceback or not allow_traceback and not frappe.local.dev_server:
traceback = ""

frappe.respond_as_web_page(
Expand Down
11 changes: 2 additions & 9 deletions frappe/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,16 +378,9 @@ def add_layouts(bootinfo):


def get_desk_settings():
role_list = frappe.get_all("Role", fields=["*"], filters=dict(name=["in", frappe.get_roles()]))
desk_settings = {}
from frappe.core.doctype.user.user import desk_properties

from frappe.core.doctype.role.role import desk_properties

for role in role_list:
for key in desk_properties:
desk_settings[key] = desk_settings.get(key) or role.get(key)

return desk_settings
return frappe.get_value("User", frappe.session.user, desk_properties, as_dict=True)


def get_notification_settings():
Expand Down
26 changes: 16 additions & 10 deletions frappe/commands/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,19 +679,11 @@ def migrate(context, skip_failing=False, skip_search_index=False):


@click.command("migrate-to")
@click.argument("frappe_provider")
@pass_context
def migrate_to(context, frappe_provider):
def migrate_to():
"Migrates site to the specified provider"
from frappe.integrations.frappe_providers import migrate_to

for site in context.sites:
frappe.init(site=site)
frappe.connect()
migrate_to(site, frappe_provider)
frappe.destroy()
if not context.sites:
raise SiteNotSpecifiedError
migrate_to()


@click.command("run-patch")
Expand Down Expand Up @@ -874,6 +866,7 @@ def backup(
@pass_context
def remove_from_installed_apps(context, app):
"Remove app from site's installed-apps list"
ensure_app_not_frappe(app)
from frappe.installer import remove_from_installed_apps

for site in context.sites:
Expand Down Expand Up @@ -902,6 +895,7 @@ def remove_from_installed_apps(context, app):
@pass_context
def uninstall(context, app, dry_run, yes, no_backup, force):
"Remove app and linked modules from site"
ensure_app_not_frappe(app)
from frappe.installer import remove_app

for site in context.sites:
Expand Down Expand Up @@ -1456,6 +1450,18 @@ def add_new_user(
update_password(user=user.name, pwd=password)


def ensure_app_not_frappe(app: str) -> None:
"""
Ensure that the app name passed is not 'frappe'
:param app: Name of the app
:return: Nothing
"""
if app == "frappe":
click.secho("You cannot remove or uninstall the app `frappe`", fg="red")
sys.exit(1)


commands = [
add_system_manager,
add_user_for_sites,
Expand Down
41 changes: 23 additions & 18 deletions frappe/contacts/doctype/contact/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,30 @@ frappe.ui.form.on("Contact", {
});
}

if (frm.doc.links) {
frappe.call({
method: "frappe.contacts.doctype.contact.contact.address_query",
args: { links: frm.doc.links },
callback: function (r) {
if (r && r.message) {
frm.set_query("address", function () {
return {
filters: {
name: ["in", r.message],
},
};
});
}
},
});
if (frm.doc.links && frm.doc.links.length > 0) {
const filtered_links = frm.doc.links.filter(
(link) => link.link_doctype && link.link_name
);

if (filtered_links.length > 0) {
frappe.call({
method: "frappe.contacts.doctype.contact.contact.address_query",
args: { links: filtered_links },
callback: function (r) {
if (r && r.message) {
frm.set_query("address", function () {
return {
filters: {
name: ["in", r.message],
},
};
});
}
},
});
}

for (let i in frm.doc.links) {
let link = frm.doc.links[i];
for (const link of filtered_links) {
frm.add_custom_button(
__("{0}: {1}", [__(link.link_doctype), __(link.link_name)]),
function () {
Expand Down
4 changes: 3 additions & 1 deletion frappe/core/doctype/comment/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@


class Comment(Document):
no_feed_on_delete = True

def after_insert(self):
notify_mentions(self.reference_doctype, self.reference_name, self.content)
self.notify_change("add")

def validate(self):
if not self.comment_email:
self.comment_email = frappe.session.user
self.content = frappe.utils.sanitize_html(self.content)
self.content = frappe.utils.sanitize_html(self.content, always_sanitize=True)

def on_update(self):
update_comment_in_doc(self)
Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/data_import/data_import.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ frappe.ui.form.on("Data Import", {
html += other_warnings
.map((warning) => {
let header = "";
if (warning.col) {
if (columns && warning.col) {
let column_number = `<span class="text-uppercase">${__("Column {0}", [
warning.col,
])}</span>`;
Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/data_import/data_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def get_preview_from_template(data_import, import_file=None, google_sheets_url=N


@frappe.whitelist()
def form_start_import(data_import):
def form_start_import(data_import: str):
return frappe.get_doc("Data Import", data_import).start_import()


Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/data_import_log/data_import_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@


class DataImportLog(Document):
pass
no_feed_on_delete = True
2 changes: 1 addition & 1 deletion frappe/core/doctype/deleted_document/deleted_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class DeletedDocument(Document):
pass
no_feed_on_delete = True

@staticmethod
def clear_old_logs(days=180):
Expand Down
10 changes: 9 additions & 1 deletion frappe/core/doctype/docfield/docfield.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"allow_on_submit",
"ignore_user_permissions",
"allow_bulk_edit",
"make_attachment_public",
"column_break_13",
"permlevel",
"ignore_xss_filter",
Expand Down Expand Up @@ -560,13 +561,20 @@
"fieldname": "sort_options",
"fieldtype": "Check",
"label": "Sort Options"
},
{
"default": "0",
"depends_on": "eval:['Attach', 'Attach Image'].includes(doc.fieldtype)",
"fieldname": "make_attachment_public",
"fieldtype": "Check",
"label": "Make Attachment Public (by default)"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-05-28 15:55:44.007917",
"modified": "2024-10-01 07:26:16.380090",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
Expand Down
13 changes: 9 additions & 4 deletions frappe/core/doctype/file/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def autoname(self):

def before_insert(self):
self.set_folder_name()
self.set_is_private()
self.set_file_name()
self.validate_attachment_limit()
self.set_file_type()
Expand All @@ -73,12 +74,11 @@ def before_insert(self):
self.flags.new_file = True
frappe.local.rollback_observers.append(self)

self.validate_duplicate_entry() # Hash is generated in save_file

def after_insert(self):
if not self.is_folder:
self.create_attachment_record()
self.set_is_private()
self.set_file_name()
self.validate_duplicate_entry()

def validate(self):
if self.is_folder:
Expand Down Expand Up @@ -410,7 +410,12 @@ def _delete_file_on_disk(self):
"""If file not attached to any other record, delete it"""
on_disk_file_not_shared = self.content_hash and not frappe.get_all(
"File",
filters={"content_hash": self.content_hash, "name": ["!=", self.name]},
filters={
"content_hash": self.content_hash,
"name": ["!=", self.name],
# NOTE: Some old Files might share file_urls while not sharing the is_private value
# "is_private": self.is_private,
},
limit=1,
)
if on_disk_file_not_shared:
Expand Down
Loading

0 comments on commit 468f3a9

Please sign in to comment.