Merge pull request #12480 from marination/perms-in-unrelated-doc

fix: frappe.new_doc won't set default in presence of User Permissions
This commit is contained in:
mergify[bot] 2021-03-20 05:19:28 +00:00 committed by GitHub
commit 60896845fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 7 deletions

View file

@ -2,8 +2,9 @@
# Copyright (c) 2017, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals
from frappe.core.doctype.user_permission.user_permission import add_user_permissions
from frappe.core.doctype.user_permission.user_permission import add_user_permissions, remove_applicable
from frappe.permissions import has_user_permission
from frappe.core.doctype.doctype.test_doctype import new_doctype
import frappe
import unittest
@ -17,6 +18,7 @@ class TestUserPermission(unittest.TestCase):
'nested_doc_user@example.com')""")
frappe.delete_doc_if_exists("DocType", "Person")
frappe.db.sql_ddl("DROP TABLE IF EXISTS `tabPerson`")
frappe.db.sql_ddl("DROP TABLE IF EXISTS `tabDoc A`")
def test_default_user_permission_validation(self):
user = create_user('test_default_permission@example.com')
@ -153,6 +155,84 @@ class TestUserPermission(unittest.TestCase):
self.assertTrue(has_user_permission(frappe.get_doc("Person", parent_record.name), user.name))
self.assertFalse(has_user_permission(frappe.get_doc("Person", child_record.name), user.name))
def test_user_perm_on_new_doc_with_field_default(self):
"""Test User Perm impact on frappe.new_doc. with *field* default value"""
frappe.set_user('Administrator')
user = create_user("new_doc_test@example.com", "Blogger")
# make a doctype "Doc A" with 'doctype' link field and default value ToDo
if not frappe.db.exists("DocType", "Doc A"):
doc = new_doctype("Doc A",
fields=[
{
"label": "DocType",
"fieldname": "doc",
"fieldtype": "Link",
"options": "DocType",
"default": "ToDo"
}
], unique=0)
doc.insert()
# make User Perm on DocType 'ToDo' in Assignment Rule (unrelated doctype)
add_user_permissions(get_params(user, "DocType", "ToDo", applicable=["Assignment Rule"]))
frappe.set_user("new_doc_test@example.com")
new_doc = frappe.new_doc("Doc A")
# User perm is created on ToDo but for doctype Assignment Rule only
# it should not have impact on Doc A
self.assertEquals(new_doc.doc, "ToDo")
frappe.set_user('Administrator')
remove_applicable(["Assignment Rule"], "new_doc_test@example.com", "DocType", "ToDo")
def test_user_perm_on_new_doc_with_user_default(self):
"""Test User Perm impact on frappe.new_doc. with *user* default value"""
from frappe.core.doctype.session_default_settings.session_default_settings import (clear_session_defaults,
set_session_default_values)
frappe.set_user('Administrator')
user = create_user("user_default_test@example.com", "Blogger")
# make a doctype "Doc A" with 'doctype' link field
if not frappe.db.exists("DocType", "Doc A"):
doc = new_doctype("Doc A",
fields=[
{
"label": "DocType",
"fieldname": "doc",
"fieldtype": "Link",
"options": "DocType",
}
], unique=0)
doc.insert()
# create a 'DocType' session default field
if not frappe.db.exists("Session Default", {"ref_doctype": "DocType"}):
settings = frappe.get_single('Session Default Settings')
settings.append("session_defaults", {
"ref_doctype": "DocType"
})
settings.save()
# make User Perm on DocType 'ToDo' in Assignment Rule (unrelated doctype)
add_user_permissions(get_params(user, "DocType", "ToDo", applicable=["Assignment Rule"]))
# User default Doctype value is ToDo via Session Defaults
frappe.set_user("user_default_test@example.com")
set_session_default_values({"doctype": "ToDo"})
new_doc = frappe.new_doc("Doc A")
# User perm is created on ToDo but for doctype Assignment Rule only
# it should not have impact on Doc A
self.assertEquals(new_doc.doc, "ToDo")
frappe.set_user('Administrator')
clear_session_defaults()
remove_applicable(["Assignment Rule"], "user_default_test@example.com", "DocType", "ToDo")
def create_user(email, *roles):
''' create user with role system manager '''
if frappe.db.exists('User', email):

View file

@ -60,7 +60,8 @@ def set_user_and_static_default_values(doc):
# user permissions for link options
doctype_user_permissions = user_permissions.get(df.options, [])
# Allowed records for the reference doctype (link field) along with default doc
allowed_records, default_doc = filter_allowed_docs_for_doctype(doctype_user_permissions, df.parent, with_default_doc=True)
allowed_records, default_doc = filter_allowed_docs_for_doctype(doctype_user_permissions,
df.parent, with_default_doc=True)
user_default_value = get_user_default_value(df, defaults, doctype_user_permissions, allowed_records, default_doc)
if user_default_value is not None:
@ -83,11 +84,12 @@ def get_user_default_value(df, defaults, doctype_user_permissions, allowed_recor
# 2 - Look in user defaults
user_default = defaults.get(df.fieldname)
is_allowed_user_default = user_default and (not user_permissions_exist(df, doctype_user_permissions)
or user_default in allowed_records)
allowed_by_user_permission = validate_value_via_user_permissions(df, doctype_user_permissions,
allowed_records, user_default=user_default)
# is this user default also allowed as per user permissions?
if is_allowed_user_default:
if user_default and allowed_by_user_permission:
return user_default
def get_static_default_value(df, doctype_user_permissions, allowed_records):
@ -101,8 +103,8 @@ def get_static_default_value(df, doctype_user_permissions, allowed_records):
elif not cstr(df.default).startswith(":"):
# a simple default value
is_allowed_default_value = (not user_permissions_exist(df, doctype_user_permissions)
or (df.default in allowed_records))
is_allowed_default_value = validate_value_via_user_permissions(df, doctype_user_permissions,
allowed_records)
if df.fieldtype!="Link" or df.options=="User" or is_allowed_default_value:
return df.default
@ -110,6 +112,19 @@ def get_static_default_value(df, doctype_user_permissions, allowed_records):
elif (df.fieldtype == "Select" and df.options and df.options not in ("[Select]", "Loading...")):
return df.options.split("\n")[0]
def validate_value_via_user_permissions(df, doctype_user_permissions, allowed_records, user_default=None):
is_valid = True
# If User Permission exists and allowed records is empty,
# that means there are User Perms, but none applicable to this new doctype.
if user_permissions_exist(df, doctype_user_permissions) and allowed_records:
# If allowed records is not empty,
# check if this field value is allowed via User Permissions applied to this doctype.
value = user_default if user_default else df.default
is_valid = value in allowed_records
return is_valid
def set_dynamic_default_values(doc, parent_doc, parentfield):
# these values should not be cached
user_permissions = get_user_permissions()