瀏覽代碼

consolidated permission checking and added patch

version-14
Rushabh Mehta 12 年之前
父節點
當前提交
8b5fb45c6e
共有 4 個文件被更改,包括 60 次插入101 次删除
  1. +29
    -3
      webnotes/__init__.py
  2. +10
    -9
      webnotes/db.py
  3. +2
    -68
      webnotes/model/doc.py
  4. +19
    -21
      webnotes/model/wrapper.py

+ 29
- 3
webnotes/__init__.py 查看文件

@@ -263,18 +263,44 @@ def get_roles(user=None, with_standard=True):
return roles

def has_permission(doctype, ptype="read"):
def has_permission(doctype, ptype="read", doc=None):
"""check if user has permission"""
if session.user=="Administrator":
return True
if conn.get_value("DocType", doctype, "istable"):
return True
return conn.sql("""select name from tabDocPerm p
perms = conn.sql("""select `name`, `match` from tabDocPerm p
where p.parent = %s
and ifnull(p.`%s`,0) = 1
and ifnull(p.permlevel,0) = 0
and (p.role="All" or p.role in (select `role` from tabUserRole where `parent`=%s))
""" % ("%s", ptype, "%s"), (doctype, session.user))
""" % ("%s", ptype, "%s"), (doctype, session.user), as_dict=1)
if doc:
match_failed = {}
for p in perms:
if p.match:
if ":" in p.match:
keys = p.match.split(":")
else:
keys = [p.match, p.match]

if doc.fields.get(keys[0],"[No Value]") \
in conn.get_defaults_as_list(keys[1], session.user):
return True
else:
match_failed[keys[0]] = doc.fields.get(keys[0],"[No Value]")
else:
# found a permission without a match
return True

# no valid permission found
if match_failed:
key = match_failed.keys()[0]
msgprint(_("Not allowed for: ") + key + "=" + match_failed[key])
return False
else:
return perms and True or False

def generate_hash():
"""Generates random hash for session id"""


+ 10
- 9
webnotes/db.py 查看文件

@@ -169,20 +169,17 @@ class Database:

# date
if type(v)==datetime.date:
v = str(v)
v = unicode(v)
if formatted:
v = formatdate(v)
# time
elif type(v)==datetime.timedelta:
h = int(v.seconds/60/60)
v = str(h) + ':' + str(v.seconds/60 - h*60)
if v[1]==':':
v='0'+v
v = unicode(v)
# datetime
elif type(v)==datetime.datetime:
v = str(v)
v = unicode(v)
# long
elif type(v)==long:
@@ -326,10 +323,14 @@ class Database:
def get_default(self, key, parent="Control Panel"):
"""get default value"""
ret = self.sql("""select defvalue from \
tabDefaultValue where defkey=%s and parent=%s""", (key, parent))
return ret and ret[0][0] or None
ret = self.get_defaults_as_list(key, parent)
return ret and ret[0] or None
def get_defaults_as_list(self, key, parent="Control Panel"):
ret = [r[0] for r in self.sql("""select defvalue from \
tabDefaultValue where defkey=%s and parent=%s""", (key, parent))]
return ret
def get_defaults(self, key=None, parent="Control Panel"):
"""get all defaults"""
if key:


+ 2
- 68
webnotes/model/doc.py 查看文件

@@ -417,10 +417,7 @@ class Document:
webnotes.conn.get_table_columns(self.doctype)
return valid_fields_map.get(self.doctype)
# Save values
# ---------------------------------------------------------------------------
def save(self, new=0, check_links=1, ignore_fields=0, make_autoname=1,
keep_timestamps=False):
"""
@@ -484,69 +481,6 @@ class Document:
self.idx = (webnotes.conn.sql("""select max(idx) from `tab%s`
where parent=%s and parentfield=%s""" % (self.doctype, '%s', '%s'),
(self.parent, self.parentfield))[0][0] or 0) + 1

# check permissions
# ---------------------------------------------------------------------------

def _get_perms(self):
if not self._perms:
self._perms = webnotes.conn.sql("""select role, `match` from tabDocPerm
where parent=%s and ifnull(`read`,0) = 1
and ifnull(permlevel,0)=0""", self.doctype)

def _get_roles(self):
# check if roles match/
if not self._roles:
if webnotes.user:
self._roles = webnotes.user.get_roles()
else:
self._roles = ['Guest']

def _get_user_defaults(self):
if not self._user_defaults:
if webnotes.user:
self._user_defaults = webnotes.user.get_defaults()
else:
self.defaults = {}

def check_perm(self, verbose=0):
import webnotes
# Admin has all permissions
if webnotes.session['user']=='Administrator':
return 1
# find roles with read access for this record at 0
self._get_perms()
self._get_roles()
self._get_user_defaults()
has_perm, match = 0, []
# loop through everything to find if there is a match
for r in self._perms:
if r[0] in self._roles:
has_perm = 1
if r[1] and match != -1:
match.append(r[1]) # add to match check
else:
match = -1 # has permission and no match, so match not required!
if has_perm and match and match != -1:
for m in match:
if ":" in m:
document_key, default_key = m.split(":")
else:
document_key = default_key = m
if self.fields.get(document_key, 'no value') in \
self._user_defaults.get(default_key, 'no default'):
has_perm = 1
break # permission found! break
else:
has_perm = 0
return has_perm
def _clear_temp_fields(self):
# clear temp stuff
@@ -759,7 +693,7 @@ def get(dt, dn='', with_children = 1, from_get_obj = 0, prefix = 'tab'):
if dt=='Page' and webnotes.session['user'] == 'Guest':
check_page_perm(doc)
else:
if not doc.check_perm():
if not webnotes.has_permission(dt, "read", doc):
webnotes.response['403'] = 1
raise webnotes.ValidationError, '[WNF] No read permission for %s %s' % (dt, dn)



+ 19
- 21
webnotes/model/wrapper.py 查看文件

@@ -29,6 +29,7 @@ Group actions like save, etc are performed on doclists
"""

import webnotes
from webnotes import _
from webnotes.utils import cint
from webnotes.model.doc import Document

@@ -131,14 +132,6 @@ class ModelWrapper:
To maintain the integrity of the data, you will not be able to save your changes.
Please refresh this document. [%s/%s]""" % (tmp[0][0], self.doc.modified), raise_exception=1)

def check_permission(self):
"""
Raises exception if permission is not valid
"""
if not self.doc.check_perm(verbose=1):
webnotes.msgprint("Not enough permission to save %s" %
self.doc.doctype, raise_exception=1)

def check_links(self):
"""
Checks integrity of links (throws exception if links are invalid)
@@ -171,8 +164,6 @@ class ModelWrapper:

def prepare_for_save(self, check_links):
self.check_if_latest()
if not self.ignore_permissions:
self.check_permission()
if check_links:
self.check_links()
self.update_timestamps_and_docstatus()
@@ -248,31 +239,31 @@ class ModelWrapper:
return self.save()
def save(self, check_links=1):
if webnotes.has_permission(self.doc.doctype, "write") or self.ignore_permissions:
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "write", self.doc):
self.prepare_for_save(check_links)
self.run_method('validate')
self.save_main()
self.save_children()
self.run_method('on_update')
else:
webnotes.msgprint("No Permission to Write", raise_exception=True)
self.no_permission_to(_("Write"))
return self

def submit(self):
if webnotes.has_permission(self.doc.doctype, "submit") or self.ignore_permissions:
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "submit", self.doc):
if self.doc.docstatus != 0:
webnotes.msgprint("Only draft can be submitted", raise_exception=1)
self.to_docstatus = 1
self.save()
self.run_method('on_submit')
else:
webnotes.msgprint("No Permission to Submit", raise_exception=True)
self.no_permission_to(_("Submit"))
return self

def cancel(self):
if webnotes.has_permission(self.doc.doctype, "submit") or self.ignore_permissions:
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "cancel", self.doc):
if self.doc.docstatus != 1:
webnotes.msgprint("Only submitted can be cancelled", raise_exception=1)
self.to_docstatus = 2
@@ -281,21 +272,28 @@ class ModelWrapper:
self.save_children()
self.run_method('on_cancel')
else:
webnotes.msgprint("No Permission to Cancel", raise_exception=True)
self.no_permission_to(_("Cancel"))
return self

def update_after_submit(self):
if self.doc.docstatus != 1:
webnotes.msgprint("Only to called after submit", raise_exception=1)
self.to_docstatus = 1
self.prepare_for_save(1)
self.save_main()
self.save_children()
self.run_method('on_update_after_submit')
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, "write", self.doc):
self.to_docstatus = 1
self.prepare_for_save(1)
self.save_main()
self.save_children()
self.run_method('on_update_after_submit')
else:
self.no_permission_to(_("Update"))
return self

def no_permission_to(self, ptype):
webnotes.msgprint(("%s (%s): " % (self.doc.name, _(self.doc.doctype))) + \
_("No Permission to ") + ptype, raise_exception=True)

# clone

def clone(source_wrapper):


Loading…
取消
儲存