@@ -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): | |||