@@ -263,18 +263,44 @@ def get_roles(user=None, with_standard=True): | |||||
return roles | return roles | ||||
def has_permission(doctype, ptype="read"): | |||||
def has_permission(doctype, ptype="read", doc=None): | |||||
"""check if user has permission""" | """check if user has permission""" | ||||
if session.user=="Administrator": | if session.user=="Administrator": | ||||
return True | return True | ||||
if conn.get_value("DocType", doctype, "istable"): | if conn.get_value("DocType", doctype, "istable"): | ||||
return True | return True | ||||
return conn.sql("""select name from tabDocPerm p | |||||
perms = conn.sql("""select `name`, `match` from tabDocPerm p | |||||
where p.parent = %s | where p.parent = %s | ||||
and ifnull(p.`%s`,0) = 1 | and ifnull(p.`%s`,0) = 1 | ||||
and ifnull(p.permlevel,0) = 0 | and ifnull(p.permlevel,0) = 0 | ||||
and (p.role="All" or p.role in (select `role` from tabUserRole where `parent`=%s)) | 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(): | def generate_hash(): | ||||
"""Generates random hash for session id""" | """Generates random hash for session id""" | ||||
@@ -169,20 +169,17 @@ class Database: | |||||
# date | # date | ||||
if type(v)==datetime.date: | if type(v)==datetime.date: | ||||
v = str(v) | |||||
v = unicode(v) | |||||
if formatted: | if formatted: | ||||
v = formatdate(v) | v = formatdate(v) | ||||
# time | # time | ||||
elif type(v)==datetime.timedelta: | 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 | # datetime | ||||
elif type(v)==datetime.datetime: | elif type(v)==datetime.datetime: | ||||
v = str(v) | |||||
v = unicode(v) | |||||
# long | # long | ||||
elif type(v)==long: | elif type(v)==long: | ||||
@@ -326,10 +323,14 @@ class Database: | |||||
def get_default(self, key, parent="Control Panel"): | def get_default(self, key, parent="Control Panel"): | ||||
"""get default value""" | """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"): | def get_defaults(self, key=None, parent="Control Panel"): | ||||
"""get all defaults""" | """get all defaults""" | ||||
if key: | if key: | ||||
@@ -417,10 +417,7 @@ class Document: | |||||
webnotes.conn.get_table_columns(self.doctype) | webnotes.conn.get_table_columns(self.doctype) | ||||
return valid_fields_map.get(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, | def save(self, new=0, check_links=1, ignore_fields=0, make_autoname=1, | ||||
keep_timestamps=False): | keep_timestamps=False): | ||||
""" | """ | ||||
@@ -484,69 +481,6 @@ class Document: | |||||
self.idx = (webnotes.conn.sql("""select max(idx) from `tab%s` | self.idx = (webnotes.conn.sql("""select max(idx) from `tab%s` | ||||
where parent=%s and parentfield=%s""" % (self.doctype, '%s', '%s'), | where parent=%s and parentfield=%s""" % (self.doctype, '%s', '%s'), | ||||
(self.parent, self.parentfield))[0][0] or 0) + 1 | (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): | def _clear_temp_fields(self): | ||||
# clear temp stuff | # 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': | if dt=='Page' and webnotes.session['user'] == 'Guest': | ||||
check_page_perm(doc) | check_page_perm(doc) | ||||
else: | else: | ||||
if not doc.check_perm(): | |||||
if not webnotes.has_permission(dt, "read", doc): | |||||
webnotes.response['403'] = 1 | webnotes.response['403'] = 1 | ||||
raise webnotes.ValidationError, '[WNF] No read permission for %s %s' % (dt, dn) | 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 | import webnotes | ||||
from webnotes import _ | |||||
from webnotes.utils import cint | from webnotes.utils import cint | ||||
from webnotes.model.doc import Document | 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. | 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) | 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): | def check_links(self): | ||||
""" | """ | ||||
Checks integrity of links (throws exception if links are invalid) | Checks integrity of links (throws exception if links are invalid) | ||||
@@ -171,8 +164,6 @@ class ModelWrapper: | |||||
def prepare_for_save(self, check_links): | def prepare_for_save(self, check_links): | ||||
self.check_if_latest() | self.check_if_latest() | ||||
if not self.ignore_permissions: | |||||
self.check_permission() | |||||
if check_links: | if check_links: | ||||
self.check_links() | self.check_links() | ||||
self.update_timestamps_and_docstatus() | self.update_timestamps_and_docstatus() | ||||
@@ -248,31 +239,31 @@ class ModelWrapper: | |||||
return self.save() | return self.save() | ||||
def save(self, check_links=1): | 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.prepare_for_save(check_links) | ||||
self.run_method('validate') | self.run_method('validate') | ||||
self.save_main() | self.save_main() | ||||
self.save_children() | self.save_children() | ||||
self.run_method('on_update') | self.run_method('on_update') | ||||
else: | else: | ||||
webnotes.msgprint("No Permission to Write", raise_exception=True) | |||||
self.no_permission_to(_("Write")) | |||||
return self | return self | ||||
def submit(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: | if self.doc.docstatus != 0: | ||||
webnotes.msgprint("Only draft can be submitted", raise_exception=1) | webnotes.msgprint("Only draft can be submitted", raise_exception=1) | ||||
self.to_docstatus = 1 | self.to_docstatus = 1 | ||||
self.save() | self.save() | ||||
self.run_method('on_submit') | self.run_method('on_submit') | ||||
else: | else: | ||||
webnotes.msgprint("No Permission to Submit", raise_exception=True) | |||||
self.no_permission_to(_("Submit")) | |||||
return self | return self | ||||
def cancel(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: | if self.doc.docstatus != 1: | ||||
webnotes.msgprint("Only submitted can be cancelled", raise_exception=1) | webnotes.msgprint("Only submitted can be cancelled", raise_exception=1) | ||||
self.to_docstatus = 2 | self.to_docstatus = 2 | ||||
@@ -281,21 +272,28 @@ class ModelWrapper: | |||||
self.save_children() | self.save_children() | ||||
self.run_method('on_cancel') | self.run_method('on_cancel') | ||||
else: | else: | ||||
webnotes.msgprint("No Permission to Cancel", raise_exception=True) | |||||
self.no_permission_to(_("Cancel")) | |||||
return self | return self | ||||
def update_after_submit(self): | def update_after_submit(self): | ||||
if self.doc.docstatus != 1: | if self.doc.docstatus != 1: | ||||
webnotes.msgprint("Only to called after submit", raise_exception=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 | 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 | # clone | ||||
def clone(source_wrapper): | def clone(source_wrapper): | ||||