consolidated permission checking and added patch
This commit is contained in:
parent
2527dd142c
commit
8b5fb45c6e
4 changed files with 60 additions and 101 deletions
|
|
@ -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"""
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Reference in a new issue