Parcourir la source

validate permissions before delete

version-14
Rushabh Mehta il y a 12 ans
Parent
révision
9765844c73
4 fichiers modifiés avec 115 ajouts et 175 suppressions
  1. +15
    -15
      public/css/bootstrap.css
  2. +2
    -117
      webnotes/model/__init__.py
  3. +97
    -43
      webnotes/model/utils.py
  4. +1
    -0
      webnotes/widgets/reportview.py

+ 15
- 15
public/css/bootstrap.css Voir le fichier

@@ -4116,15 +4116,15 @@ input[type="submit"].btn.btn-mini {
} }


.navbar-inverse .navbar-inner { .navbar-inverse .navbar-inner {
background-color: #1b1b1b;
background-image: -moz-linear-gradient(top, #222222, #111111);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
background-image: -webkit-linear-gradient(top, #222222, #111111);
background-image: -o-linear-gradient(top, #222222, #111111);
background-image: linear-gradient(to bottom, #222222, #111111);
background-color: #444444;
background-image: -moz-linear-gradient(top, #666666, #111111);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#666666), to(#111111));
background-image: -webkit-linear-gradient(top, #666666, #111111);
background-image: -o-linear-gradient(top, #666666, #111111);
background-image: linear-gradient(to bottom, #666666, #111111);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #252525; border-color: #252525;
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff666666', endColorstr='#ff111111', GradientType=0);
} }


.navbar-inverse .brand, .navbar-inverse .brand,
@@ -4168,7 +4168,7 @@ input[type="submit"].btn.btn-mini {
} }


.navbar-inverse .divider-vertical { .navbar-inverse .divider-vertical {
border-right-color: #222222;
border-right-color: #666666;
border-left-color: #111111; border-left-color: #111111;
} }


@@ -4237,17 +4237,17 @@ input[type="submit"].btn.btn-mini {
.navbar-inverse .btn-navbar { .navbar-inverse .btn-navbar {
color: #ffffff; color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: #0e0e0e;
background-color: #373737;
*background-color: #040404; *background-color: #040404;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
background-image: -webkit-linear-gradient(top, #151515, #040404);
background-image: -o-linear-gradient(top, #151515, #040404);
background-image: linear-gradient(to bottom, #151515, #040404);
background-image: -moz-linear-gradient(top, #151515, #040404);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#595959), to(#040404));
background-image: -webkit-linear-gradient(top, #595959, #040404);
background-image: -o-linear-gradient(top, #595959, #040404);
background-image: linear-gradient(to bottom, #595959, #040404);
background-image: -moz-linear-gradient(top, #595959, #040404);
background-repeat: repeat-x; background-repeat: repeat-x;
border-color: #040404 #040404 #000000; border-color: #040404 #040404 #000000;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ff595959', endColorstr='#ff040404', GradientType=0);
filter: progid:dximagetransform.microsoft.gradient(enabled=false); filter: progid:dximagetransform.microsoft.gradient(enabled=false);
} }




+ 2
- 117
webnotes/model/__init__.py Voir le fichier

@@ -27,8 +27,6 @@ import webnotes
no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'FlexTable', 'Button', 'Image', 'Graph'] no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'FlexTable', 'Button', 'Image', 'Graph']
default_fields = ['doctype','name','owner','creation','modified','modified_by','parent','parentfield','parenttype','idx','docstatus'] default_fields = ['doctype','name','owner','creation','modified','modified_by','parent','parentfield','parenttype','idx','docstatus']


#=================================================================================

def insert(doclist): def insert(doclist):
if not isinstance(doclist, list): if not isinstance(doclist, list):
doclist = [doclist] doclist = [doclist]
@@ -44,103 +42,11 @@ def insert(doclist):
return wrapper return wrapper


def check_if_doc_is_linked(dt, dn):
"""
Raises excption if the given doc(dt, dn) is linked in another record.
"""
sql = webnotes.conn.sql

ll = get_link_fields(dt)
for l in ll:
link_dt, link_field = l
issingle = sql("select issingle from tabDocType where name = '%s'" % link_dt)

# no such doctype (?)
if not issingle: continue
if issingle[0][0]:
item = sql("select doctype from `tabSingles` where field='%s' and value = '%s' and doctype = '%s' " % (link_field, dn, l[0]))
if item:
webnotes.msgprint("Cannot delete %s <b>%s</b> because it is linked in <b>%s</b>" % (dt, dn, item[0][0]), raise_exception=1)
else:
item = None
try:
# (ifnull(parent, '')='' or `%s`!=`parent`)
# this condition ensures that it allows deletion when child table field references parent
item = sql("select name, parent, parenttype from `tab%s` where `%s`='%s' and docstatus!=2 and (ifnull(parent, '')='' or `%s`!=`parent`) \
limit 1" % (link_dt, link_field, dn, link_field), debug=1)

except Exception, e:
if e.args[0]==1146: pass
else: raise e
if item:
webnotes.msgprint("Cannot delete %s <b>%s</b> because it is linked in %s <b>%s</b>" % (dt, dn, item[0][2] or link_dt, item[0][1] or item[0][0]), raise_exception=1)

@webnotes.whitelist() @webnotes.whitelist()
def delete_doc(doctype=None, name=None, doclist = None, force=0): def delete_doc(doctype=None, name=None, doclist = None, force=0):
"""
Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record
"""
import webnotes.model.meta
sql = webnotes.conn.sql

# get from form
if not doctype:
doctype = webnotes.form_dict.get('dt')
name = webnotes.form_dict.get('dn')
if not doctype:
webnotes.msgprint('Nothing to delete!', raise_exception =1)

# already deleted..?
if not webnotes.conn.exists(doctype, name):
return

tablefields = webnotes.model.meta.get_table_fields(doctype)
# check if submitted
d = webnotes.conn.sql("select docstatus from `tab%s` where name=%s" % (doctype, '%s'), name)
if d and int(d[0][0]) == 1:
webnotes.msgprint("Submitted Record '%s' '%s' cannot be deleted" % (doctype, name))
raise Exception
import webnotes.model.utils
webnotes.model.utils.delete_doc(doctype, name, doclist, force)
# call on_trash if required
from webnotes.model.code import get_obj
if doclist:
obj = get_obj(doclist=doclist)
else:
obj = get_obj(doctype, name)

if hasattr(obj,'on_trash'):
obj.on_trash()
if doctype=='DocType':
webnotes.conn.sql("delete from `tabCustom Field` where dt = %s", name)
webnotes.conn.sql("delete from `tabCustom Script` where dt = %s", name)
webnotes.conn.sql("delete from `tabProperty Setter` where doc_type = %s", name)
webnotes.conn.sql("delete from `tabSearch Criteria` where doc_type = %s", name)

# check if links exist
if not force:
check_if_doc_is_linked(doctype, name)
# remove tags
from webnotes.widgets.tags import clear_tags
clear_tags(doctype, name)
try:
webnotes.conn.sql("delete from `tab%s` where name='%s' limit 1" % (doctype, name))
for t in tablefields:
webnotes.conn.sql("delete from `tab%s` where parent = %s" % (t[0], '%s'), name)
except Exception, e:
if e.args[0]==1451:
webnotes.msgprint("Cannot delete %s '%s' as it is referenced in another record. You must delete the referred record first" % (doctype, name))
raise e
return 'okay'

def get_search_criteria(dt): def get_search_criteria(dt):
import webnotes.model.doc import webnotes.model.doc
# load search criteria for reports (all) # load search criteria for reports (all)
@@ -153,24 +59,9 @@ def get_search_criteria(dt):
pass # no search criteria pass # no search criteria
return dl return dl



# Rename Doc
#=================================================================================
def rename(doctype, old, new, is_doctype=0, debug=1): def rename(doctype, old, new, is_doctype=0, debug=1):
import webnotes.model.rename_doc import webnotes.model.rename_doc
webnotes.model.rename_doc.rename_doc(doctype, old, new, is_doctype, debug) webnotes.model.rename_doc.rename_doc(doctype, old, new, is_doctype, debug)
def get_link_fields(dt):
"""
Returns linked fields for dt as a tuple of (linked_doctype, linked_field)
"""
import webnotes.model.rename_doc
link_fields = webnotes.model.rename_doc.get_link_fields(dt)
link_fields = [[lf['parent'], lf['fieldname']] for lf in link_fields]
return link_fields
# Make Table Copy
#=================================================================================


def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfields=[]): def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfields=[]):
import webnotes.model.doc import webnotes.model.doc
@@ -189,14 +80,10 @@ def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfie
l.append(newrow) l.append(newrow)
return l return l


# DB Exists
#=================================================================================

def db_exists(dt, dn): def db_exists(dt, dn):
import webnotes import webnotes
return webnotes.conn.exists(dt, dn) return webnotes.conn.exists(dt, dn)



def delete_fields(args_dict, delete=0): def delete_fields(args_dict, delete=0):
""" """
Delete a field. Delete a field.
@@ -233,5 +120,3 @@ def delete_fields(args_dict, delete=0):
", ".join(["DROP COLUMN `%s`" % f for f in fields if f in existing_fields]) ", ".join(["DROP COLUMN `%s`" % f for f in fields if f in existing_fields])
webnotes.conn.commit() webnotes.conn.commit()
webnotes.conn.sql(query) webnotes.conn.sql(query)

+ 97
- 43
webnotes/model/utils.py Voir le fichier

@@ -87,31 +87,14 @@ def compress(doclist):




def getlist(doclist, field): def getlist(doclist, field):
"""
Filter a list of records for a specific field from the full doclist

Example::

# find all phone call details
dl = getlist(self.doclist, 'contact_updates')
pl = []
for d in dl:
if d.type=='Phone':
pl.append(d)
"""
from webnotes.utils import cint from webnotes.utils import cint
l = [] l = []
for d in doclist: for d in doclist:
if d.parentfield == field: if d.parentfield == field:
l.append(d) l.append(d)

l.sort(lambda a, b: cint(a.idx) - cint(b.idx)) l.sort(lambda a, b: cint(a.idx) - cint(b.idx))

return l return l


# Copy doclist
# ------------

def copy_doclist(doclist, no_copy = []): def copy_doclist(doclist, no_copy = []):
""" """
Save & return a copy of the given doclist Save & return a copy of the given doclist
@@ -161,50 +144,121 @@ def getvaluelist(doclist, fieldname):
l.append(d.fields[fieldname]) l.append(d.fields[fieldname])
return l return l


def _make_html(doc, link_list):
def delete_doc(doctype=None, name=None, doclist = None, force=0):
"""
Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record
"""
import webnotes.model.meta
sql = webnotes.conn.sql

# get from form
if not doctype:
doctype = webnotes.form_dict.get('dt')
name = webnotes.form_dict.get('dn')
if not doctype:
webnotes.msgprint('Nothing to delete!', raise_exception =1)


from webnotes.utils import cstr
out = '<table class="simpletable">'
for k in doc.fields.keys():
if k!='server_code_compiled':
v = cstr(doc.fields[k])
# already deleted..?
if not webnotes.conn.exists(doctype, name):
return


# link field
if v and (k in link_list.keys()):
dt = link_list[k]
if isinstance(dt, basestring) and dt.startswith('link:'):
dt = dt[5:]
v = '<a href="index.cgi?page=Form/%s/%s">%s</a>' % (dt, v, v)
# permission
if not webnotes.has_permission(doctype, "cancel"):
webnotes.msgprint("User not allowed to delete.", raise_exception=1)


out += '\t<tr><td>%s</td><td>%s</td></tr>\n' % (cstr(k), v)
tablefields = webnotes.model.meta.get_table_fields(doctype)
# check if submitted
d = webnotes.conn.sql("select docstatus from `tab%s` where name=%s" % (doctype, '%s'), name)
if d and int(d[0][0]) == 1:
webnotes.msgprint("Submitted Record '%s' '%s' cannot be deleted" % (doctype, name))
raise Exception
# call on_trash if required
from webnotes.model.code import get_obj
if doclist:
obj = get_obj(doclist=doclist)
else:
obj = get_obj(doctype, name)


out += '</table>'
return out
if hasattr(obj,'on_trash'):
obj.on_trash()
if doctype=='DocType':
webnotes.conn.sql("delete from `tabCustom Field` where dt = %s", name)
webnotes.conn.sql("delete from `tabCustom Script` where dt = %s", name)
webnotes.conn.sql("delete from `tabProperty Setter` where doc_type = %s", name)
webnotes.conn.sql("delete from `tabSearch Criteria` where doc_type = %s", name)

# check if links exist
if not force:
check_if_doc_is_linked(doctype, name)
# remove tags
from webnotes.widgets.tags import clear_tags
clear_tags(doctype, name)
try:
webnotes.conn.sql("delete from `tab%s` where name='%s' limit 1" % (doctype, name))
for t in tablefields:
webnotes.conn.sql("delete from `tab%s` where parent = %s" % (t[0], '%s'), name)
except Exception, e:
if e.args[0]==1451:
webnotes.msgprint("Cannot delete %s '%s' as it is referenced in another record. You must delete the referred record first" % (doctype, name))
raise e
return 'okay'


def to_html(doclist):
def check_if_doc_is_linked(dt, dn):
""" """
Return a simple HTML format of the doclist
Raises excption if the given doc(dt, dn) is linked in another record.
""" """
out = ''
link_lists = {}
sql = webnotes.conn.sql


for d in doclist:
if not link_lists.get(d.doctype):
link_lists[d.doctype] = d.make_link_list()
from webnotes.model.rename_doc import get_link_fields
link_fields = get_link_fields(dt)
link_fields = [[lf['parent'], lf['fieldname']] for lf in link_fields]

for l in link_fields:
link_dt, link_field = l
issingle = sql("select issingle from tabDocType where name = '%s'" % link_dt)


out += _make_html(d, link_lists[d.doctype])
# no such doctype (?)
if not issingle: continue
if issingle[0][0]:
item = sql("select doctype from `tabSingles` where field='%s' and value = '%s' and doctype = '%s' " % (link_field, dn, l[0]))
if item:
webnotes.msgprint("Cannot delete %s <b>%s</b> because it is linked in <b>%s</b>" % (dt, dn, item[0][0]), raise_exception=1)
else:
item = None
try:
# (ifnull(parent, '')='' or `%s`!=`parent`)
# this condition ensures that it allows deletion when child table field references parent
item = sql("select name, parent, parenttype from `tab%s` where `%s`='%s' and docstatus!=2 and (ifnull(parent, '')='' or `%s`!=`parent`) \
limit 1" % (link_dt, link_field, dn, link_field), debug=1)

except Exception, e:
if e.args[0]==1146: pass
else: raise e
if item:
webnotes.msgprint("Cannot delete %s <b>%s</b> because it is linked in %s <b>%s</b>" % (dt, dn, item[0][2] or link_dt, item[0][1] or item[0][0]), raise_exception=1)


return out


def round_doc(doc, precision_map): def round_doc(doc, precision_map):
from webnotes.utils import flt from webnotes.utils import flt
for fieldname, precision in precision_map.items(): for fieldname, precision in precision_map.items():
doc.fields[fieldname] = flt(doc.fields.get(fieldname), precision) doc.fields[fieldname] = flt(doc.fields.get(fieldname), precision)
def set_default(doc, key): def set_default(doc, key):
if not doc.is_default: if not doc.is_default:
webnotes.conn.set(doc, "is_default", 1) webnotes.conn.set(doc, "is_default", 1)
webnotes.conn.sql("""update `tab%s` set `is_default`=0 webnotes.conn.sql("""update `tab%s` set `is_default`=0
where `%s`=%s and name!=%s""" % (doc.doctype, key, "%s", "%s"), where `%s`=%s and name!=%s""" % (doc.doctype, key, "%s", "%s"),
(doc.fields.get(key), doc.name))
(doc.fields.get(key), doc.name))

+ 1
- 0
webnotes/widgets/reportview.py Voir le fichier

@@ -317,6 +317,7 @@ def delete_items():
dt_obj.on_trash() dt_obj.on_trash()
delete_doc(doctype, d) delete_doc(doctype, d)
except Exception, e: except Exception, e:
webnotes.errprint(webnotes.getTraceback())
pass pass
@webnotes.whitelist() @webnotes.whitelist()


Chargement…
Annuler
Enregistrer