Pārlūkot izejas kodu

[fix] high level perms serverside checking

version-14
Rushabh Mehta pirms 10 gadiem
vecāks
revīzija
c153b810e0
9 mainītis faili ar 159 papildinājumiem un 97 dzēšanām
  1. +3
    -2
      frappe/__init__.py
  2. +39
    -31
      frappe/core/doctype/user/test_records.json
  3. +21
    -0
      frappe/core/doctype/user/test_user.py
  4. +25
    -1
      frappe/model/base_document.py
  5. +35
    -21
      frappe/model/create_new.py
  6. +18
    -33
      frappe/model/document.py
  7. +10
    -0
      frappe/model/meta.py
  8. +8
    -8
      frappe/test_runner.py
  9. +0
    -1
      frappe/tests/test_document.py

+ 3
- 2
frappe/__init__.py Parādīt failu

@@ -108,6 +108,7 @@ def init(site, sites_path=None):
local.user = None
local.role_permissions = {}
local.valid_columns = {}
local.new_doc_templates = {}

local.jenv = None
local.jloader =None
@@ -429,14 +430,14 @@ def reset_metadata_version():
cache().set_value("metadata_version", v)
return v

def new_doc(doctype, parent_doc=None, parentfield=None):
def new_doc(doctype, parent_doc=None, parentfield=None, as_dict=False):
"""Returns a new document of the given DocType with defaults set.

:param doctype: DocType of the new document.
:param parent_doc: [optional] add to parent document.
:param parentfield: [optional] add against this `parentfield`."""
from frappe.model.create_new import get_new_doc
return get_new_doc(doctype, parent_doc, parentfield)
return get_new_doc(doctype, parent_doc, parentfield, as_dict=as_dict)

def set_value(doctype, docname, fieldname, value):
"""Set document value. Calls `frappe.client.set_value`"""


+ 39
- 31
frappe/core/doctype/user/test_records.json Parādīt failu

@@ -1,52 +1,60 @@
[
{
"doctype": "User",
"email": "test@example.com",
"enabled": 1,
"first_name": "_Test",
"new_password": "testpassword",
"doctype": "User",
"email": "test@example.com",
"enabled": 1,
"first_name": "_Test",
"new_password": "testpassword",
"user_roles": [
{
"doctype": "UserRole",
"parentfield": "user_roles",
"doctype": "UserRole",
"parentfield": "user_roles",
"role": "_Test Role"
},
},
{
"doctype": "UserRole",
"parentfield": "user_roles",
"doctype": "UserRole",
"parentfield": "user_roles",
"role": "System Manager"
}
]
},
},
{
"doctype": "User",
"email": "test1@example.com",
"first_name": "_Test1",
"doctype": "User",
"email": "test1@example.com",
"first_name": "_Test1",
"new_password": "testpassword"
},
},
{
"doctype": "User",
"email": "test2@example.com",
"first_name": "_Test2",
"new_password": "testpassword"
},
"doctype": "User",
"email": "test2@example.com",
"first_name": "_Test2",
"new_password": "testpassword",
"enabled": 1
},
{
"doctype": "User",
"email": "testperm@example.com",
"first_name": "_Test Perm",
"new_password": "testpassword",
"enabled": 1
},
{
"doctype": "User",
"email": "testdelete@example.com",
"enabled": 1,
"first_name": "_Test",
"new_password": "testpassword",
"doctype": "User",
"email": "testdelete@example.com",
"enabled": 1,
"first_name": "_Test",
"new_password": "testpassword",
"user_roles": [
{
"doctype": "UserRole",
"parentfield": "user_roles",
"doctype": "UserRole",
"parentfield": "user_roles",
"role": "_Test Role 2"
},
},
{
"doctype": "UserRole",
"parentfield": "user_roles",
"doctype": "UserRole",
"parentfield": "user_roles",
"role": "System Manager"
}
]
}
]
]

+ 21
- 0
frappe/core/doctype/user/test_user.py Parādīt failu

@@ -15,6 +15,9 @@ class TestUser(unittest.TestCase):
frappe.db.sql("""delete from tabUserRole where role='_Test Role 2'""")
delete_doc("Role","_Test Role 2")

if frappe.db.exists("User", "_test@example.com"):
delete_doc("User", "_test@example.com")

user = frappe.copy_doc(test_records[1])
user.email = "_test@example.com"
user.insert()
@@ -50,3 +53,21 @@ class TestUser(unittest.TestCase):
frappe.db.set_value("Website Settings", "Website Settings", "_test", "_test_val")
self.assertEquals(frappe.db.get_value("Website Settings", None, "_test"), "_test_val")
self.assertEquals(frappe.db.get_value("Website Settings", "Website Settings", "_test"), "_test_val")

def test_high_permlevel_validations(self):
user = frappe.get_meta("User")
self.assertTrue("user_roles" in [d.fieldname for d in user.get_high_permlevel_fields()])

frappe.set_user("testperm@example.com")

me = frappe.get_doc("User", "testperm@example.com")
me.add_roles("System Manager")

self.assertTrue("System Manager" not in [d.role for d in me.get("user_roles")])

frappe.set_user("Administrator")

me = frappe.get_doc("User", "testperm@example.com")
me.add_roles("System Manager")

self.assertTrue("System Manager" in [d.role for d in me.get("user_roles")])

+ 25
- 1
frappe/model/base_document.py Parādīt failu

@@ -2,12 +2,13 @@
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe, json, sys
import frappe, sys
from frappe import _
from frappe.utils import cint, flt, now, cstr, strip_html
from frappe.model import default_fields
from frappe.model.naming import set_new_name
from frappe.modules import load_doctype_module
from frappe.model import display_fieldtypes

_classes = {}

@@ -471,6 +472,29 @@ class BaseDocument(object):
else:
return True

def reset_values_if_no_permlevel_access(self, has_access_to, high_permlevel_fields):
"""If the user does not have permissions at permlevel > 0, then reset the values to original / default"""
to_reset = []

for df in high_permlevel_fields:
if df.permlevel not in has_access_to and df.fieldtype not in display_fieldtypes:
to_reset.append(df)

if to_reset:
if self.is_new():
# if new, set default value
ref_doc = frappe.new_doc(self.doctype)
else:
# get values from old doc
if self.parent:
self.parent_doc.get_latest()
ref_doc = [d for d in self.parent_doc.get(self.parentfield) if d.name == self.name][0]
else:
ref_doc = self.get_latest()

for df in to_reset:
self.set(df.fieldname, ref_doc.get(df.fieldname))

def _filter(data, filters, limit=None):
"""pass filters as:
{"key": "val", "key": ["!=", "val"],


+ 35
- 21
frappe/model/create_new.py Parādīt failu

@@ -7,37 +7,51 @@ Create a new document with defaults set
"""

import frappe
from frappe.utils import nowdate, nowtime, cint, flt, now_datetime
from frappe.utils import nowdate, nowtime, now_datetime
import frappe.defaults
from frappe.model.db_schema import type_map
import copy

def get_new_doc(doctype, parent_doc = None, parentfield = None):
doc = frappe.get_doc({
"doctype": doctype,
"__islocal": 1,
"owner": frappe.session.user,
"docstatus": 0
})
def get_new_doc(doctype, parent_doc = None, parentfield = None, as_dict=False):
if not doctype in frappe.local.new_doc_templates:
# cache a copy of new doc as it is called
# frequently for inserts
doc = frappe.get_doc({
"doctype": doctype,
"__islocal": 1,
"owner": frappe.session.user,
"docstatus": 0
})

user_permissions = frappe.defaults.get_user_permissions()
user_permissions = frappe.defaults.get_user_permissions()

if parent_doc:
doc.parent = parent_doc.name
doc.parenttype = parent_doc.doctype
defaults = frappe.defaults.get_defaults()

if parentfield:
doc.parentfield = parentfield
for df in doc.meta.get("fields"):
if df.fieldtype in type_map:
default_value = get_default_value(df, defaults, user_permissions, parent_doc)
doc.set(df.fieldname, default_value)

doc._fix_numeric_types()
doc = doc.get_valid_dict()
doc["doctype"] = doctype
doc["__islocal"] = 1

defaults = frappe.defaults.get_defaults()
frappe.local.new_doc_templates[doctype] = doc

for df in doc.meta.get("fields"):
if df.fieldtype in type_map:
default_value = get_default_value(df, defaults, user_permissions, parent_doc)
doc.set(df.fieldname, default_value)
doc = copy.deepcopy(frappe.local.new_doc_templates[doctype])

doc._fix_numeric_types()
if parent_doc:
doc["parent"] = parent_doc.name
doc["parenttype"] = parent_doc.doctype

if parentfield:
doc["parentfield"] = parentfield

return doc
if as_dict:
return doc
else:
return frappe.get_doc(doc)

def get_default_value(df, defaults, user_permissions, parent_doc):
user_permissions_exist = (df.fieldtype=="Link"


+ 18
- 33
frappe/model/document.py Parādīt failu

@@ -8,7 +8,6 @@ from frappe.utils import flt, cint, cstr, now, get_datetime_str
from frappe.model.base_document import BaseDocument, get_controller
from frappe.model.naming import set_new_name
from werkzeug.exceptions import NotFound, Forbidden
from frappe.model import display_fieldtypes
import hashlib, json

# once_only validation
@@ -84,7 +83,7 @@ class Document(BaseDocument):
# incorrect arguments. let's not proceed.
raise frappe.DataError("Document({0}, {1})".format(arg1, arg2))

self.dont_update_if_missing = []
self._default_new_docs = {}
self.flags = frappe._dict()

def load_from_db(self):
@@ -122,6 +121,11 @@ class Document(BaseDocument):
else:
self.set(df.fieldname, [])

def get_latest(self):
if not getattr(self, "latest", None):
self.latest = frappe.get_doc(self.doctype, self.name)
return self.latest

def check_permission(self, permtype, permlabel=None):
"""Raise `frappe.PermissionError` if not permitted"""
if not self.has_permission(permtype):
@@ -301,37 +305,18 @@ class Document(BaseDocument):
if self.flags.ignore_permissions or frappe.flags.in_install:
return

self.get_high_permlevel_fields()
if not self.high_permlevel_fields:
return

has_access_to = self.get_permlevel_access()
to_reset = []
for df in self.high_permlevel_fields:
if df.permlevel not in has_access_to and df.fieldtype not in display_fieldtypes:
to_reset.append(df)
high_permlevel_fields = self.meta.get_high_permlevel_fields()

if to_reset:
if self.is_new():
# if new, set default value
for df in to_reset:
self.set(df.fieldname, df.default or None)
if high_permlevel_fields:
self.reset_values_if_no_permlevel_access(has_access_to, high_permlevel_fields)

else:
# get values from old doc
old = frappe.get_doc(self.doctype, self.name)
for df in to_reset:
self.set(df.fieldname, old.get(df.fieldname))

def get_high_permlevel_fields(self):
"""Build list of fields with high perm level and all the higher perm levels defined."""
self.high_permlevel_fields = []
self.high_permlevels = []
for df in self.meta.fields:
if df.permlevel > 0:
self.high_permlevel_fields.append(df)
if not df.permlevel in self.high_permlevels:
self.high_permlevels.append(df.permlevel)
# check for child tables
for df in self.meta.get_table_fields():
high_permlevel_fields = frappe.get_meta(df.options).meta.get_high_permlevel_fields()
if high_permlevel_fields:
for d in self.get(df.fieldname):
d.reset_values_if_no_permlevel_access(has_access_to, high_permlevel_fields)

def get_permlevel_access(self):
user_roles = frappe.get_roles()
@@ -347,12 +332,12 @@ class Document(BaseDocument):
if frappe.flags.in_import:
return

new_doc = frappe.new_doc(self.doctype)
new_doc = frappe.new_doc(self.doctype, as_dict=True)
self.update_if_missing(new_doc)

# children
for df in self.meta.get_table_fields():
new_doc = frappe.new_doc(df.options)
new_doc = frappe.new_doc(df.options, as_dict=True)
value = self.get(df.fieldname)
if isinstance(value, list):
for d in value:
@@ -578,7 +563,7 @@ class Document(BaseDocument):
self.run_method("on_update_after_submit")

frappe.cache().set_value("last_modified:" + self.doctype, self.modified)
self.latest = None

def check_no_back_links_exist(self):
"""Check if document links to any active document before Cancel."""


+ 10
- 0
frappe/model/meta.py Parādīt failu

@@ -213,6 +213,16 @@ class Meta(Document):

return fields

def get_high_permlevel_fields(self):
"""Build list of fields with high perm level and all the higher perm levels defined."""
if not hasattr(self, "high_permlevel_fields"):
self.high_permlevel_fields = []
for df in self.fields:
if df.permlevel > 0:
self.high_permlevel_fields.append(df)

return self.high_permlevel_fields

doctype_table_fields = [
frappe._dict({"fieldname": "fields", "options": "DocField"}),
frappe._dict({"fieldname": "permissions", "options": "DocPerm"})


+ 8
- 8
frappe/test_runner.py Parādīt failu

@@ -193,14 +193,14 @@ def make_test_records_for_doctype(doctype, verbose=0, force=False):
def make_test_objects(doctype, test_records, verbose=None):
records = []

if not frappe.get_meta(doctype).issingle:
existing = frappe.get_all(doctype, filters={"name":("like", "_T-" + doctype + "-%")})
if existing:
return [d.name for d in existing]
existing = frappe.get_all(doctype, filters={"name":("like", "_Test " + doctype + "%")})
if existing:
return [d.name for d in existing]
# if not frappe.get_meta(doctype).issingle:
# existing = frappe.get_all(doctype, filters={"name":("like", "_T-" + doctype + "-%")})
# if existing:
# return [d.name for d in existing]
#
# existing = frappe.get_all(doctype, filters={"name":("like", "_Test " + doctype + "%")})
# if existing:
# return [d.name for d in existing]

for doc in test_records:
if not doc.get("doctype"):


+ 0
- 1
frappe/tests/test_document.py Parādīt failu

@@ -146,4 +146,3 @@ class TestDocument(unittest.TestCase):
d.validate_update_after_submit()
d.meta.get_field("starts_on").allow_on_submit = 0



Notiek ielāde…
Atcelt
Saglabāt