From 75b91f44ce0ab08a75f0ee978b47832376acf654 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 10 Dec 2025 15:40:58 +0530 Subject: [PATCH 1/3] feat(get_lazy_doc): add in `check_permission` parameter So as to avoid manually calling doc.check_permission() often Signed-off-by: Akhil Narang --- frappe/model/document.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/frappe/model/document.py b/frappe/model/document.py index afbca633b1..dc42232265 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -142,14 +142,16 @@ def get_doc_from_dict(data: dict[str, Any], **kwargs) -> "Document": raise ImportError(data["doctype"]) -def get_lazy_doc(doctype: str, name: str, *, for_update=None) -> "Document": +def get_lazy_doc( + doctype: str, name: str, *, for_update=None, check_permission: str | bool | None = None +) -> "Document": if doctype == "DocType": warnings.warn("DocType doesn't support lazy loading", stacklevel=1) return get_doc(doctype, name) - controller = get_lazy_controller(doctype) - if controller: - return controller(doctype, name, for_update=for_update) + if controller := get_lazy_controller(doctype): + doc = controller(doctype, name, for_update=for_update) + return get_doc_permission_check(doc, check_permission) raise ImportError(doctype) From 2dcfe07ca8dcfc4334ab648c2f599b69622f6f05 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 10 Dec 2025 15:47:32 +0530 Subject: [PATCH 2/3] refactor: make use of `check_permission` parameter for get_lazy_doc Signed-off-by: Akhil Narang --- frappe/client.py | 3 +-- frappe/desk/form/load.py | 6 ++---- frappe/desk/form/utils.py | 6 ++---- frappe/desk/notifications.py | 3 +-- frappe/handler.py | 4 +--- frappe/model/document.py | 2 +- frappe/www/printview.py | 12 ++++-------- 7 files changed, 12 insertions(+), 24 deletions(-) diff --git a/frappe/client.py b/frappe/client.py index b6d3fedb49..1f5952d76e 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -365,8 +365,7 @@ def attach_file( :param is_private: Attach file as private file (1 or 0) :param docfield: file to attach to (optional)""" - doc = frappe.get_lazy_doc(doctype, docname) - doc.check_permission() + doc = frappe.get_lazy_doc(doctype, docname, check_permission=True) file = frappe.get_doc( { diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index 49d05a6e73..c3c85c6269 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -94,8 +94,7 @@ def get_docinfo(doc=None, doctype=None, name=None): from frappe.share import _get_users as get_docshares if not doc: - doc = frappe.get_lazy_doc(doctype, name) - doc.check_permission("read") + doc = frappe.get_lazy_doc(doctype, name, check_permission=True) all_communications = _get_communications(doc.doctype, doc.name, limit=21) automated_messages = [ @@ -204,8 +203,7 @@ def get_versions(doc: "Document") -> list[dict]: def get_communications(doctype, name, start=0, limit=20): from frappe.utils import cint - doc = frappe.get_lazy_doc(doctype, name) - doc.check_permission("read") + frappe.get_lazy_doc(doctype, name).check_permission() return _get_communications(doctype, name, cint(start), cint(limit)) diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index f956428c91..45fe071b92 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -27,8 +27,7 @@ def add_comment( reference_doctype: str, reference_name: str, content: str, comment_email: str, comment_by: str ) -> "Comment": """Allow logged user with permission to read document to add a comment""" - reference_doc = frappe.get_lazy_doc(reference_doctype, reference_name) - reference_doc.check_permission() + reference_doc = frappe.get_lazy_doc(reference_doctype, reference_name, check_permission=True) comment = frappe.new_doc("Comment") comment.update( @@ -58,8 +57,7 @@ def update_comment(name, content): frappe.throw(_("Comment can only be edited by the owner"), frappe.PermissionError) if doc.reference_doctype and doc.reference_name: - reference_doc = frappe.get_lazy_doc(doc.reference_doctype, doc.reference_name) - reference_doc.check_permission() + reference_doc = frappe.get_lazy_doc(doc.reference_doctype, doc.reference_name, check_permission=True) doc.content = extract_images_from_html(reference_doc, content, is_private=True) else: diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py index 11b2b979ae..bacf2b0f77 100644 --- a/frappe/desk/notifications.py +++ b/frappe/desk/notifications.py @@ -264,8 +264,7 @@ def get_open_count(doctype: str, name: str, items=None): def _get_linked_document_counts(doctype: str, name: str, items=None): - doc = frappe.get_lazy_doc(doctype, name) - doc.check_permission() + doc = frappe.get_lazy_doc(doctype, name, check_permission=True) meta = doc.meta links = meta.get_dashboard_data() diff --git a/frappe/handler.py b/frappe/handler.py index 0a02e70af7..3169dc7ed4 100644 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -211,15 +211,13 @@ def check_write_permission(doctype: str | None = None, name: str | None = None): return try: - doc = frappe.get_lazy_doc(doctype, name) + frappe.get_lazy_doc(doctype, name, check_permission="write") except frappe.DoesNotExistError: # doc has not been inserted yet, name is set to "new-some-doctype" # If doc inserts fine then only this attachment will be linked see file/utils.py:relink_mismatched_files frappe.new_doc(doctype).check_permission("write") return - doc.check_permission("write") - @frappe.whitelist(allow_guest=True) def download_file(file_url: str): diff --git a/frappe/model/document.py b/frappe/model/document.py index dc42232265..5c35aa200e 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -147,7 +147,7 @@ def get_lazy_doc( ) -> "Document": if doctype == "DocType": warnings.warn("DocType doesn't support lazy loading", stacklevel=1) - return get_doc(doctype, name) + return get_doc(doctype, name, check_permission=check_permission) if controller := get_lazy_controller(doctype): doc = controller(doctype, name, for_update=for_update) diff --git a/frappe/www/printview.py b/frappe/www/printview.py index f27aaea32d..e7d5390652 100644 --- a/frappe/www/printview.py +++ b/frappe/www/printview.py @@ -340,11 +340,9 @@ def get_html_and_style( """Return `html` and `style` of print format, used in PDF etc.""" if isinstance(name, str): - document = frappe.get_lazy_doc(doc, name) + document = frappe.get_lazy_doc(doc, name, check_permission=True) else: - document = frappe.get_doc(json.loads(doc)) - - document.check_permission() + document = frappe.get_doc(json.loads(doc), check_permission=True) print_format = get_print_format_doc(print_format, meta=document.meta) set_link_titles(document) @@ -371,11 +369,9 @@ def get_rendered_raw_commands(doc: str, name: str | None = None, print_format: s """Return Rendered Raw Commands of print format, used to send directly to printer.""" if isinstance(name, str): - document = frappe.get_lazy_doc(doc, name) + document = frappe.get_lazy_doc(doc, name, check_permission=True) else: - document = frappe.get_doc(json.loads(doc)) - - document.check_permission() + document = frappe.get_doc(json.loads(doc), check_permission=True) print_format = get_print_format_doc(print_format, meta=document.meta) From ef6a0bffc2ee0b73d84395c761ea18e48f5b5244 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 10 Dec 2025 16:52:37 +0530 Subject: [PATCH 3/3] fix: update overloaded get_doc() signature Signed-off-by: Akhil Narang --- frappe/model/document.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/model/document.py b/frappe/model/document.py index 5c35aa200e..459446ac8c 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -59,7 +59,9 @@ def get_doc(doctype: str, /) -> _SingleDocument: @overload -def get_doc(doctype: str, name: str, /, *, for_update: bool | None = None) -> "Document": +def get_doc( + doctype: str, name: str, /, *, for_update: bool | None = None, check_permission: str | bool | None = None +) -> "Document": """Retrieve DocType from DB, doctype and name must be positional argument.""" pass