From 8b5fb45c6ea45545e9fb7303fa7b37338ea7cde4 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 14 Jan 2013 17:02:12 +0530 Subject: [PATCH] consolidated permission checking and added patch --- webnotes/__init__.py | 32 ++++++++++++++++-- webnotes/db.py | 19 ++++++----- webnotes/model/doc.py | 70 ++------------------------------------- webnotes/model/wrapper.py | 40 +++++++++++----------- 4 files changed, 60 insertions(+), 101 deletions(-) diff --git a/webnotes/__init__.py b/webnotes/__init__.py index 91b0bfc553..e75ec18921 100644 --- a/webnotes/__init__.py +++ b/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""" diff --git a/webnotes/db.py b/webnotes/db.py index 07e95fa921..3c1c4406d6 100644 --- a/webnotes/db.py +++ b/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: diff --git a/webnotes/model/doc.py b/webnotes/model/doc.py index 1d74bdbbd3..65cac86535 100755 --- a/webnotes/model/doc.py +++ b/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) diff --git a/webnotes/model/wrapper.py b/webnotes/model/wrapper.py index afaf40e953..81d79a633a 100644 --- a/webnotes/model/wrapper.py +++ b/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):