From d7026b8a262e4e2360313ff7d123db938fd97c02 Mon Sep 17 00:00:00 2001 From: Corentin Flr <10946971+cogk@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:40:12 +0100 Subject: [PATCH 1/3] fix(meta)!: Allow level 0 fields when a doc has been shared with user --- frappe/model/meta.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 0e80a0957c3..99e6d2f7406 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -595,6 +595,10 @@ def get_permitted_fieldnames( self.get_permlevel_access(permission_type=permission_type, parenttype=parenttype, user=user) ) + if 0 not in permlevel_access and permission_type in ("read", "select"): + if frappe.share.get_shared(self.name, user, rights=[permission_type], limit=1): + permlevel_access.add(0) + permitted_fieldnames.extend( df.fieldname for df in self.get_fieldnames_with_value( From 06bd8b9e9c436697d98324cf1c30ed13608dce4b Mon Sep 17 00:00:00 2001 From: Corentin Flr <10946971+cogk@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:06:54 +0100 Subject: [PATCH 2/3] test: Add test for get_list of shared document --- frappe/core/doctype/docshare/test_docshare.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/frappe/core/doctype/docshare/test_docshare.py b/frappe/core/doctype/docshare/test_docshare.py index 125e829d9b3..3b6ec0c396b 100644 --- a/frappe/core/doctype/docshare/test_docshare.py +++ b/frappe/core/doctype/docshare/test_docshare.py @@ -56,6 +56,24 @@ def test_doc_permission(self): with self.assertRowsRead(1): self.assertTrue(self.event.has_permission()) + def test_list_permission(self): + frappe.set_user(self.user) + with self.assertRaises(frappe.PermissionError): + frappe.get_list("Web Page") + + frappe.set_user("Administrator") + doc = frappe.new_doc("Web Page") + doc.update({"title": "test document for docshare permissions"}) + doc.insert() + frappe.share.add("Web Page", doc.name, self.user) + + frappe.set_user(self.user) + self.assertEqual(len(frappe.get_list("Web Page")), 1) + + doc.delete(ignore_permissions=True) + with self.assertRaises(frappe.PermissionError): + frappe.get_list("Web Page") + def test_share_permission(self): frappe.share.add("Event", self.event.name, self.user, write=1, share=1) From d2d1b14cc64adbe251424a0ac0fe9ab20cef7b96 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 29 Jan 2024 19:41:53 +0530 Subject: [PATCH 3/3] fix: Always allow meta/standard fields in perm level Perm levels CANNOT applied on these fields so these should ALWAYS be allowed. --- frappe/model/__init__.py | 8 ++++---- frappe/tests/test_model_utils.py | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 2dad3df4fd8..d3d120c872e 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -230,6 +230,9 @@ def get_permitted_fields( if permission_type is None: permission_type = "select" if frappe.only_has_select_perm(doctype, user=user) else "read" + meta_fields = meta.default_fields.copy() + optional_meta_fields = [x for x in optional_fields if x in valid_columns] + if permitted_fields := meta.get_permitted_fieldnames( parenttype=parenttype, user=user, @@ -239,15 +242,12 @@ def get_permitted_fields( if permission_type == "select": return permitted_fields - meta_fields = meta.default_fields.copy() - optional_meta_fields = [x for x in optional_fields if x in valid_columns] - if meta.istable: meta_fields.extend(child_table_fields) return meta_fields + permitted_fields + optional_meta_fields - return [] + return meta_fields + optional_meta_fields def is_default_field(fieldname: str) -> bool: diff --git a/frappe/tests/test_model_utils.py b/frappe/tests/test_model_utils.py index 61828ef500c..72f57768084 100644 --- a/frappe/tests/test_model_utils.py +++ b/frappe/tests/test_model_utils.py @@ -36,10 +36,10 @@ def test_get_permitted_fields(self): todo_all_columns = frappe.get_meta("ToDo").get_valid_columns() self.assertListEqual(todo_all_fields, todo_all_columns) - # Guest should have access to no fields in ToDo + # Guest should have access to no non-std fields in ToDo with set_user("Guest"): guest_permitted_fields = get_permitted_fields("ToDo") - self.assertEqual(guest_permitted_fields, []) + self.assertNotIn("description", guest_permitted_fields) # everyone should have access to all fields of core doctypes with set_user("Guest"): @@ -55,15 +55,14 @@ def test_get_permitted_fields(self): "Installed Application", parenttype="Installed Applications" ) child_all_fields = frappe.get_meta("Installed Application").get_valid_columns() - self.assertEqual(without_parent_fields, []) self.assertLess(len(without_parent_fields), len(with_parent_fields)) self.assertSequenceEqual(set(with_parent_fields), set(child_all_fields)) - # guest has access to no fields + # guest has access to no non-std fields with set_user("Guest"): - self.assertEqual(get_permitted_fields("Installed Application"), []) - self.assertEqual( - get_permitted_fields("Installed Application", parenttype="Installed Applications"), [] + self.assertNotIn("app_name", get_permitted_fields("Installed Application")) + self.assertNotIn( + "app_name", get_permitted_fields("Installed Application", parenttype="Installed Applications") ) def test_is_default_field(self):