fix: Add authorization checks on internal functions (backport #55709) (#55726)

* fix: Add authorization checks on internal functions (#55709)

(cherry picked from commit ba936eefab)

# Conflicts:
#	erpnext/accounts/doctype/pos_profile/pos_profile.py
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
#	erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py
#	erpnext/support/doctype/issue/issue.py

* chore: conflicts

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
mergify[bot]
2026-06-08 10:16:12 +00:00
committed by GitHub
parent 497c3a5e83
commit 2ae6451f10
15 changed files with 19 additions and 35 deletions

View File

@@ -580,10 +580,12 @@ def update_account_number(name, account_name, account_number=None, from_descenda
@frappe.whitelist()
def merge_account(old, new):
_ensure_idle_system()
# Validate properties before merging
new_account = frappe.get_cached_doc("Account", new)
old_account = frappe.get_cached_doc("Account", old)
new_account.check_permission("write")
old_account.check_permission("write")
if not new_account:
throw(_("Account {0} does not exist").format(new))

View File

@@ -121,7 +121,7 @@ class BisectAccountingStatements(Document):
cur_node.save()
@frappe.whitelist()
@frappe.whitelist(methods=["POST"])
def build_tree(self):
frappe.db.delete("Bisect Nodes")

View File

@@ -314,32 +314,3 @@ def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
)
return pos_profile
@frappe.whitelist()
def set_default_profile(pos_profile, company):
modified = now()
user = frappe.session.user
if pos_profile and company:
frappe.db.sql(
""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf
set
pfu.default = 0, pf.modified = %s, pf.modified_by = %s
where
pfu.user = %s and pf.name = pfu.parent and pf.company = %s
and pfu.default = 1""",
(modified, user, user, company),
auto_commit=1,
)
frappe.db.sql(
""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf
set
pfu.default = 1, pf.modified = %s, pf.modified_by = %s
where
pfu.user = %s and pf.name = pfu.parent and pf.company = %s and pf.name = %s
""",
(modified, user, user, company, pos_profile),
auto_commit=1,
)

View File

@@ -131,6 +131,7 @@ def is_job_running(job_name: str) -> bool:
@frappe.whitelist()
def pause_job_for_doc(docname: str | None = None):
if docname:
frappe.has_permission("Process Payment Reconciliation", "write", doc=docname, throw=True)
frappe.db.set_value("Process Payment Reconciliation", docname, "status", "Paused")
log = frappe.db.get_value("Process Payment Reconciliation Log", filters={"process_pr": docname})
if log:
@@ -145,6 +146,8 @@ def trigger_job_for_doc(docname: str | None = None):
if not docname:
return
frappe.has_permission("Process Payment Reconciliation", "write", doc=docname, throw=True)
if not frappe.get_single_value("Accounts Settings", "auto_reconcile_payments"):
frappe.throw(
_("Auto Reconciliation of Payments has been disabled. Enable it through {0}").format(

View File

@@ -92,6 +92,7 @@ class ProcessPeriodClosingVoucher(Document):
@frappe.whitelist()
def start_pcv_processing(docname: str):
if frappe.db.get_value("Process Period Closing Voucher", docname, "status") in ["Queued", "Running"]:
frappe.has_permission("Process Payment Reconciliation", "write", doc=docname, throw=True)
frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Running")
ppcvd = qb.DocType("Process Period Closing Voucher Detail")

View File

@@ -518,6 +518,7 @@ def download_statements(document_name):
@frappe.whitelist()
def send_emails(document_name, from_scheduler=False, posting_date=None):
doc = frappe.get_doc("Process Statement Of Accounts", document_name)
doc.check_permission()
report = get_report_pdf(doc, consolidated=False)
if report:

View File

@@ -2008,6 +2008,7 @@ def make_stock_entry(source_name, target_doc=None):
def change_release_date(name, release_date=None):
if frappe.db.exists("Purchase Invoice", name):
pi = frappe.get_lazy_doc("Purchase Invoice", name)
pi.check_permission()
pi.db_set("release_date", release_date)

View File

@@ -1540,6 +1540,7 @@ def update_cost_center(docname, cost_center_name, cost_center_number, company, m
Renames the document by adding the number as a prefix to the current name and updates
all transaction where it was present.
"""
frappe.has_permission("Cost Center", "write", doc=docname, throw=True)
validate_field_number("Cost Center", docname, cost_center_number, company, "cost_center_number")
if cost_center_number:

View File

@@ -201,6 +201,7 @@ def refresh_scorecards():
def make_all_scorecards(docname):
sc = frappe.get_doc("Supplier Scorecard", docname)
supplier = frappe.get_doc("Supplier", sc.supplier)
supplier.check_permission("write")
start_date = getdate(supplier.creation)
end_date = get_scorecard_date(sc.period, start_date)

View File

@@ -297,7 +297,8 @@ def get_message():
@frappe.whitelist()
def set_default_supplier(item_code, supplier, company):
def set_default_supplier(item_code: str, supplier: str, company: str):
frappe.has_permission("Item", "write", doc=item_code, throw=True)
frappe.db.set_value(
"Item Default",
{"parent": item_code, "company": company},

View File

@@ -533,7 +533,7 @@ def get_lead_with_phone_number(number):
def add_lead_to_prospect(lead, prospect):
prospect = frappe.get_doc("Prospect", prospect)
prospect.append("leads", {"lead": lead})
prospect.save(ignore_permissions=True)
prospect.save()
carry_forward_communication_and_comments = frappe.db.get_single_value(
"CRM Settings", "carry_forward_communication_and_comments"

View File

@@ -717,7 +717,7 @@ def set_project_status(project, status):
frappe.throw(_("Status must be Cancelled or Completed"))
project = frappe.get_doc("Project", project)
frappe.has_permission(doc=project, throw=True)
project.check_permission("write")
for task in frappe.get_all("Task", dict(project=project.name)):
frappe.db.set_value("Task", task.name, "status", status)

View File

@@ -427,6 +427,7 @@ def deactivate_sales_person(status=None, employee=None):
@frappe.whitelist()
def create_user(employee: str, email: str | None = None, create_user_permission: int = 0) -> str:
emp = frappe.get_doc("Employee", employee)
emp.check_permission("write")
if emp.user_id:
frappe.throw(_("Employee {0} already has a linked user").format(emp.name))

View File

@@ -405,6 +405,7 @@ def sanitize_address(address):
@frappe.whitelist()
def notify_customers(delivery_trip):
delivery_trip = frappe.get_doc("Delivery Trip", delivery_trip)
delivery_trip.check_permission()
context = delivery_trip.as_dict()

View File

@@ -59,7 +59,7 @@ class StockRepostingSettings(Document):
if diff < 10:
self.end_time = get_time_str(add_to_date(self.start_time, hours=10, as_datetime=True))
@frappe.whitelist()
@frappe.whitelist(methods=["POST"])
def convert_to_item_wh_reposting(self):
"""Convert Transaction reposting to Item Warehouse based reposting if Item Based Reposting has enabled."""