ソースを参照

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 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"""


+ 10
- 9
webnotes/db.py ファイルの表示

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


+ 2
- 68
webnotes/model/doc.py ファイルの表示

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




+ 19
- 21
webnotes/model/wrapper.py ファイルの表示

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


読み込み中…
キャンセル
保存