fix: added permission checks on various whitelisted functions (backport #56745) (#56946)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
This commit is contained in:
mergify[bot]
2026-07-08 18:10:27 +05:30
committed by GitHub
parent b32bfab66f
commit 7ce1289c10
4 changed files with 61 additions and 33 deletions

View File

@@ -107,7 +107,7 @@ def get_party_bank_account(party_type, party):
) )
def get_default_company_bank_account(company, party_type, party): def get_default_company_bank_account(company, party_type, party, ignore_permissions=True):
default_company_bank_account = frappe.db.get_value(party_type, party, "default_bank_account") default_company_bank_account = frappe.db.get_value(party_type, party, "default_bank_account")
if default_company_bank_account: if default_company_bank_account:
if company != frappe.get_cached_value("Bank Account", default_company_bank_account, "company"): if company != frappe.get_cached_value("Bank Account", default_company_bank_account, "company"):
@@ -118,6 +118,14 @@ def get_default_company_bank_account(company, party_type, party):
"Bank Account", {"company": company, "is_company_account": 1, "is_default": 1} "Bank Account", {"company": company, "is_company_account": 1, "is_default": 1}
) )
if not ignore_permissions:
default_company_bank_account = (
default_company_bank_account
if default_company_bank_account
and frappe.get_cached_doc("Bank Account", default_company_bank_account).has_permission("select")
else None
)
return default_company_bank_account return default_company_bank_account

View File

@@ -2712,6 +2712,9 @@ def get_party_details(company, party_type, party, date, cost_center=None):
if not frappe.db.exists(party_type, party): if not frappe.db.exists(party_type, party):
frappe.throw(_("{0} {1} does not exist").format(_(party_type), party)) frappe.throw(_("{0} {1} does not exist").format(_(party_type), party))
ptype = "select" if frappe.only_has_select_perm(party_type) else "read"
frappe.has_permission(party_type, ptype, party, throw=True)
party_account = get_party_account(party_type, party, company) party_account = get_party_account(party_type, party, company)
account_currency = get_account_currency(party_account) account_currency = get_account_currency(party_account)
_party_name = "title" if party_type == "Shareholder" else party_type.lower() + "_name" _party_name = "title" if party_type == "Shareholder" else party_type.lower() + "_name"
@@ -2719,7 +2722,7 @@ def get_party_details(company, party_type, party, date, cost_center=None):
if party_type in ["Customer", "Supplier"]: if party_type in ["Customer", "Supplier"]:
party_bank_account = get_party_bank_account(party_type, party) party_bank_account = get_party_bank_account(party_type, party)
bank_account = get_default_company_bank_account(company, party_type, party) bank_account = get_default_company_bank_account(company, party_type, party, ignore_permissions=False)
return { return {
"party_account": party_account, "party_account": party_account,

View File

@@ -428,6 +428,17 @@ def get_party_account(party_type, party=None, company=None, include_advance=Fals
Will first search in party (Customer / Supplier) record, if not found, Will first search in party (Customer / Supplier) record, if not found,
will search in group (Customer Group / Supplier Group), will search in group (Customer Group / Supplier Group),
finally will return default.""" finally will return default."""
def account_perm_check(account):
ptype = "select" if frappe.only_has_select_perm("Account") else "read"
if frappe.has_permission("Account", ptype, account):
return
# Using custom message to prevent data leak in case of `apply_strict_permission` is enabled.
frappe.throw(
_("User don't have permissions to select/read this account."), exc=frappe.PermissionError
)
if not party_type: if not party_type:
frappe.throw(_("Party Type is mandatory")) frappe.throw(_("Party Type is mandatory"))
if not company: if not company:
@@ -438,46 +449,51 @@ def get_party_account(party_type, party=None, company=None, include_advance=Fals
"default_receivable_account" if party_type == "Customer" else "default_payable_account" "default_receivable_account" if party_type == "Customer" else "default_payable_account"
) )
return frappe.get_cached_value("Company", company, default_account_name) account = frappe.get_cached_value("Company", company, default_account_name)
else:
account = frappe.db.get_value(
"Party Account", {"parenttype": party_type, "parent": party, "company": company}, "account"
)
if not account and party_type in ["Customer", "Supplier"]:
party_group_doctype = "Customer Group" if party_type == "Customer" else "Supplier Group"
group = frappe.get_cached_value(party_type, party, scrub(party_group_doctype))
account = frappe.db.get_value( account = frappe.db.get_value(
"Party Account", "Party Account", {"parenttype": party_type, "parent": party, "company": company}, "account"
{"parenttype": party_group_doctype, "parent": group, "company": company},
"account",
) )
if not account and party_type in ["Customer", "Supplier"]: if not account and party_type in ["Customer", "Supplier"]:
default_account_name = ( party_group_doctype = "Customer Group" if party_type == "Customer" else "Supplier Group"
"default_receivable_account" if party_type == "Customer" else "default_payable_account" group = frappe.get_cached_value(party_type, party, scrub(party_group_doctype))
) account = frappe.db.get_value(
account = frappe.get_cached_value("Company", company, default_account_name) "Party Account",
{"parenttype": party_group_doctype, "parent": group, "company": company},
"account",
)
existing_gle_currency = get_party_gle_currency(party_type, party, company) if not account and party_type in ["Customer", "Supplier"]:
if existing_gle_currency: default_account_name = (
if account: "default_receivable_account" if party_type == "Customer" else "default_payable_account"
account_currency = frappe.get_cached_value("Account", account, "account_currency") )
if (account and account_currency != existing_gle_currency) or not account: account = frappe.get_cached_value("Company", company, default_account_name)
account = get_party_gle_account(party_type, party, company)
# get default account on the basis of party type existing_gle_currency = get_party_gle_currency(party_type, party, company)
if not account: if existing_gle_currency:
account_type = frappe.get_cached_value("Party Type", party_type, "account_type") if account:
default_account_name = "default_" + account_type.lower() + "_account" account_currency = frappe.get_cached_value("Account", account, "account_currency")
account = frappe.get_cached_value("Company", company, default_account_name) if (account and account_currency != existing_gle_currency) or not account:
account = get_party_gle_account(party_type, party, company)
if include_advance and party_type in ["Customer", "Supplier", "Student"]: # get default account on the basis of party type
if not account:
account_type = frappe.get_cached_value("Party Type", party_type, "account_type")
default_account_name = "default_" + account_type.lower() + "_account"
account = frappe.get_cached_value("Company", company, default_account_name)
if account:
account_perm_check(account)
if include_advance and party and party_type in ["Customer", "Supplier", "Student"]:
advance_account = get_party_advance_account(party_type, party, company) advance_account = get_party_advance_account(party_type, party, company)
if advance_account: if advance_account:
account_perm_check(advance_account)
return [account, advance_account] return [account, advance_account]
else:
return [account] return [account]
return account return account

View File

@@ -462,6 +462,7 @@ class BootStrapTestData:
"new_password": "Eastern_43A1W", "new_password": "Eastern_43A1W",
"roles": [ "roles": [
{"doctype": "Has Role", "parentfield": "roles", "role": "_Test Role"}, {"doctype": "Has Role", "parentfield": "roles", "role": "_Test Role"},
{"doctype": "Has Role", "parentfield": "roles", "role": "Accounts User"},
{"doctype": "Has Role", "parentfield": "roles", "role": "System Manager"}, {"doctype": "Has Role", "parentfield": "roles", "role": "System Manager"},
], ],
}, },