fix: use correct core doctypes set in _get_filterable_fields (#37932)

This commit is contained in:
Sagar Vora 2026-03-11 11:49:48 +00:00 committed by GitHub
parent 9e93965315
commit 7a113c0aee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 38 additions and 2 deletions

View file

@ -19,6 +19,7 @@ from frappe.database.utils import (
get_doctype_name,
get_doctype_sort_info,
)
from frappe.model import CORE_DOCTYPES as PERMITTED_CORE_DOCTYPES
from frappe.model import OPTIONAL_FIELDS, get_permitted_fields
from frappe.model.base_document import DOCTYPES_FOR_DOCTYPE
from frappe.model.document import Document
@ -1040,8 +1041,8 @@ class Engine:
# for select permission on parent doctype, allow all permlevel 0 fields in filters
cache_key = (doctype, None, "_filterable_select")
if cache_key not in self.permitted_fields_cache:
if doctype in CORE_DOCTYPES:
# core doctypes have no restrictions - return all valid columns
if doctype in PERMITTED_CORE_DOCTYPES:
# no restrictions - return all valid columns
self.permitted_fields_cache[cache_key] = set(meta.get_valid_columns())
else:
permlevel_0_fields = set(meta.default_fields) | OPTIONAL_FIELDS

View file

@ -224,6 +224,7 @@ def get_permitted_fields(
meta = frappe.get_meta(doctype)
valid_columns = meta.get_valid_columns()
# note: any change here should also be made in _get_filterable_fields in query.py
if doctype in CORE_DOCTYPES:
return valid_columns

View file

@ -1037,6 +1037,40 @@ class TestQuery(IntegrationTestCase):
self.assertEqual(len(result), 1, "Should find the note when filtering by permlevel 0 field")
self.assertEqual(result[0]["name"], note.name)
def test_core_doctype_filterable_fields_with_select_permission(self):
"""Core doctypes like User should allow filtering by any field when the user
only has select permission. Regression test for #37923."""
test_role = "CoreSelectTestRole"
test_user_email = "test2@example.com"
frappe.set_user("Administrator")
test_user = frappe.get_doc("User", test_user_email)
test_user.remove_roles(test_role)
frappe.delete_doc("Role", test_role, ignore_missing=True, force=True)
frappe.get_doc({"doctype": "Role", "role_name": test_role}).insert(ignore_if_duplicate=True)
add_permission("User", test_role, 0, ptype="select")
update_permission_property("User", test_role, 0, "read", 0, validate=False)
test_user.add_roles(test_role)
def cleanup():
frappe.set_user("Administrator")
test_user.remove_roles(test_role)
frappe.delete_doc("Role", test_role, ignore_missing=True, force=True)
self.addCleanup(cleanup)
frappe.set_user(test_user_email)
# filter by user_type and enabled — the exact filters used by search_link for assignment
result = frappe.qb.get_query(
"User",
filters={"user_type": "System User", "enabled": 1},
fields=["name"],
ignore_permissions=False,
).run(as_dict=True)
self.assertTrue(len(result) > 0, "Should be able to filter User by user_type and enabled")
def test_nested_permission(self):
"""Test permission on nested doctypes"""
frappe.set_user("Administrator")