From 5deabdde2110937d57e5b606e21efeecdc789415 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 20 Dec 2023 11:56:36 +0530 Subject: [PATCH] fix: skip virtual fields in perm level checks during DB Query DB Query can't access virtual fields so it should ignore all virtual fields. --- frappe/model/__init__.py | 7 ++++++- frappe/model/db_query.py | 1 + frappe/model/meta.py | 13 +++++++++++-- frappe/tests/test_db_query.py | 8 ++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 9c0282a24d..ad29e31ee4 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -194,6 +194,8 @@ def get_permitted_fields( parenttype: str | None = None, user: str | None = None, permission_type: str | None = None, + *, + ignore_virtual=False, ) -> list[str]: meta = frappe.get_meta(doctype) valid_columns = meta.get_valid_columns() @@ -209,7 +211,10 @@ def get_permitted_fields( permission_type = "select" if frappe.only_has_select_perm(doctype, user=user) else "read" if permitted_fields := meta.get_permitted_fieldnames( - parenttype=parenttype, user=user, permission_type=permission_type + parenttype=parenttype, + user=user, + permission_type=permission_type, + with_virtual_fields=not ignore_virtual, ): if permission_type == "select": return permitted_fields diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 70ecedd3c8..a20053d646 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -635,6 +635,7 @@ class DatabaseQuery: doctype=self.doctype, parenttype=self.parent_doctype, permission_type=self.permission_map.get(self.doctype), + ignore_virtual=True, ) for i, field in enumerate(self.fields): diff --git a/frappe/model/meta.py b/frappe/model/meta.py index df04dc1eda..ae4e8ea5ef 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -565,7 +565,14 @@ class Meta(Document): self.high_permlevel_fields = [df for df in self.fields if df.permlevel > 0] return self.high_permlevel_fields - def get_permitted_fieldnames(self, parenttype=None, *, user=None, permission_type="read"): + def get_permitted_fieldnames( + self, + parenttype=None, + *, + user=None, + permission_type="read", + with_virtual_fields=True, + ): """Build list of `fieldname` with read perm level and all the higher perm levels defined. Note: If permissions are not defined for DocType, return all the fields with value. @@ -590,7 +597,9 @@ class Meta(Document): permitted_fieldnames.extend( df.fieldname - for df in self.get_fieldnames_with_value(with_field_meta=True, with_virtual_fields=True) + for df in self.get_fieldnames_with_value( + with_field_meta=True, with_virtual_fields=with_virtual_fields + ) if df.permlevel in permlevel_access ) return permitted_fieldnames diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 1ef4a23f65..87f044ff39 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -753,6 +753,14 @@ class TestDBQuery(FrappeTestCase): limit=50, ) + def test_virtual_field_get_list(self): + try: + frappe.get_list("Prepared Report", ["*"]) + frappe.get_list("Scheduled Job Type", ["*"]) + except Exception as e: + print(frappe.get_traceback()) + self.fail("get_list not working with virtual field") + def test_pluck_name(self): names = DatabaseQuery("DocType").execute(filters={"name": "DocType"}, pluck="name") self.assertEqual(names, ["DocType"])