Skip to content

Commit

Permalink
feat: update v15 dec 23
Browse files Browse the repository at this point in the history
  • Loading branch information
sibikumarkuppusamy committed Dec 26, 2024
1 parent 2bb52ef commit e842362
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 13 deletions.
3 changes: 3 additions & 0 deletions frappe/database/db_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ def restore_database(verbose: bool, target: str, source: str, user: str, passwor
# Newer versions of MariaDB add in a line that'll break on older versions, so remove it
command.extend(["sed", r"'/\/\*M\{0,1\}!999999\\- enable the sandbox mode \*\//d'", "|"])

# Remove view security definers
command.extend(["sed", r"'/\/\*![0-9]* DEFINER=[^ ]* SQL SECURITY DEFINER \*\//d'", "|"])

# Generate the restore command
bin, args, bin_name = get_command(
socket=frappe.conf.db_socket,
Expand Down
1 change: 1 addition & 0 deletions frappe/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,4 +570,5 @@
"insert_queue_for_*", # Deferred Insert
"recorder-*", # Recorder
"global_search_queue",
"monitor-transactions",
]
3 changes: 3 additions & 0 deletions frappe/model/base_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
table_fields,
)
from frappe.model.docstatus import DocStatus
from frappe.model.dynamic_links import invalidate_distinct_link_doctypes
from frappe.model.naming import set_new_name
from frappe.model.utils.link_count import notify_link_count
from frappe.modules import load_doctype_module
Expand Down Expand Up @@ -831,6 +832,8 @@ def get_msg(df, docname):
if not doctype:
frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))

invalidate_distinct_link_doctypes(df.parent, df.options, doctype)

# MySQL is case insensitive. Preserve case of the original docname in the Link Field.

# get a map of values ot fetch along with this link query
Expand Down
3 changes: 2 additions & 1 deletion frappe/model/db_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
get_time,
get_timespan_date_range,
make_filter_tuple,
sanitize_column,
)
from frappe.utils.data import DateTimeLikeObject, get_datetime, getdate, sbool

Expand Down Expand Up @@ -600,7 +601,7 @@ def build_filter_conditions(self, filters, conditions: list, ignore_permissions=

for f in filters:
if isinstance(f, str):
conditions.append(f)
conditions.append(sanitize_column(f))
else:
conditions.append(self.prepare_filter_condition(f))

Expand Down
42 changes: 39 additions & 3 deletions frappe/model/dynamic_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ def get_dynamic_link_map(for_delete=False):
dynamic_link_map.setdefault(meta.name, []).append(df)
else:
try:
links = frappe.db.sql_list(
"""select distinct `{options}` from `tab{parent}`""".format(**df)
)
links = fetch_distinct_link_doctypes(df.parent, df.options)
for doctype in links:
dynamic_link_map.setdefault(doctype, []).append(df)
except frappe.db.TableMissingError:
Expand All @@ -61,3 +59,41 @@ def get_dynamic_links():
for query in dynamic_link_queries:
df += frappe.db.sql(query, as_dict=True)
return df


def _dynamic_link_map_key(doctype, fieldname):
return f"dynamic_link_map::{doctype}::{fieldname}"


def fetch_distinct_link_doctypes(doctype: str, fieldname: str):
"""Return all unique doctypes a dynamic link is linking against.
Note:
- results are cached and can *possibly be outdated*
- cache gets updated when a document with different document link is discovered
- raw queries adding dynamic link won't update this cache
- cache miss can often be VERY expensive on large table.
"""

key = _dynamic_link_map_key(doctype, fieldname)
doctypes = frappe.cache.get_value(key)

if doctypes is None:
doctypes = frappe.db.sql(f"""select distinct `{fieldname}` from `tab{doctype}`""", pluck=True)
frappe.cache.set_value(key, doctypes, expires_in_sec=12 * 60 * 60)

return doctypes


def invalidate_distinct_link_doctypes(doctype: str, fieldname: str, linked_doctype: str):
"""If new linked doctype is discovered for a dynamic link then cache is evicted."""

key = _dynamic_link_map_key(doctype, fieldname)
doctypes = frappe.cache.get_value(key)

if doctypes is None or not isinstance(doctypes, list):
return

if linked_doctype not in doctypes:
# Note: Do NOT "update" cache because it can lead to concurrency bugs.
frappe.cache.delete_value(key)
frappe.db.after_commit.add(lambda: frappe.cache.delete_value(key))
2 changes: 1 addition & 1 deletion frappe/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def flush():
logs = frappe.cache.lrange(MONITOR_REDIS_KEY, 0, -1)
if logs:
logs = list(map(frappe.safe_decode, logs))
with open(log_file(), "a", os.O_NONBLOCK) as f:
with open(log_file(), "a") as f:
f.write("\n".join(logs))
f.write("\n")
# Remove fetched entries from cache
Expand Down
2 changes: 1 addition & 1 deletion frappe/public/js/frappe/ui/field_group.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout {

if (invalid.length && check_invalid) {
frappe.msgprint({
title: __("Inavlid Values"),
title: __("Invalid Values"),
message:
__("Following fields have invalid values:") +
"<br><br><ul><li>" +
Expand Down
2 changes: 1 addition & 1 deletion frappe/tests/test_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ def test_web_view_link_authentication(self):

# without key
url_without_key = f"/ToDo/{todo.name}"
self.assertEqual(self.get(url_without_key).status, "403 FORBIDDEN")
self.assertEqual(self.get(url_without_key).status, "404 NOT FOUND")

# Logged-in user can access the page without key
self.assertEqual(self.get(url_without_key, "Administrator").status, "200 OK")
Expand Down
4 changes: 3 additions & 1 deletion frappe/utils/print_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ def read_multi_pdf(output: PdfWriter) -> bytes:


@frappe.whitelist(allow_guest=True)
def download_pdf(doctype, name, format=None, doc=None, no_letterhead=0, language=None, letterhead=None):
def download_pdf(
doctype: str, name: str, format=None, doc=None, no_letterhead=0, language=None, letterhead=None
):
doc = doc or frappe.get_doc(doctype, name)
validate_print_permission(doc)

Expand Down
13 changes: 8 additions & 5 deletions frappe/www/printview.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,15 +350,18 @@ def get_rendered_raw_commands(doc: str, name: str | None = None, print_format: s


def validate_print_permission(doc):
if frappe.has_website_permission(doc):
return

for ptype in ("read", "print"):
if frappe.has_permission(doc.doctype, ptype, doc) or frappe.has_website_permission(doc):
if frappe.has_permission(doc.doctype, ptype, doc):
return

key = frappe.form_dict.key
if key and isinstance(key, str):
if (key := frappe.form_dict.key) and isinstance(key, str):
validate_key(key, doc)
else:
raise frappe.PermissionError(_("You do not have permission to view this document"))
return

frappe.throw(_("{0} {1} not found").format(_(doc.doctype), doc.name), frappe.DoesNotExistError)


def validate_key(key, doc):
Expand Down

0 comments on commit e842362

Please sign in to comment.