# Python 2.3 ... 2.6 compatibility: from roundup.anypy.sets_ import set # Roles that can always remove or restore files and messages EDIT_ROLES = set('Developer Admin Coordinator'.split()) def removed(db, cl, nodeid, newvalues, name): ''' Sets [msg|file].issueid on unlink, unsets on link Used for restoring removed files or messages in the web UI. Also audits spurious removals and restorations by users. ''' if name == 'messages': klass = db.msg elif name == 'files': klass = db.file new = set(newvalues[name] or []) old = set(cl.get(nodeid, name) or []) len_new, len_old = len(new), len(old) if len_new != len_old: user = db.getuid() roles = db.user.get(user, 'roles').split(',') add_remove_ok = bool([role for role in roles if role in EDIT_ROLES]) if len_new < len_old: gone = (old - new).pop() if name == 'files': # Allow users to remove their own files file_creator = klass.get(gone, 'creator') == user add_remove_ok = add_remove_ok or file_creator if add_remove_ok: # Record issue id in removed file/msg klass.set(gone, issueid=nodeid) else: raise ValueError( "You don't have permission to remove %s %s." % (name[:-1], gone)) else: added = (new - old).pop() # Allow adding new files and messages that were # not previously unlinked add_remove_ok = add_remove_ok or not klass.get(added, 'issueid') if add_remove_ok: if klass.get(added, 'issueid') == nodeid: klass.set(added, issueid='') else: raise ValueError( "You don't have permission to remove %s %s." % (name[:-1], added)) def removed_file(db, cl, nodeid, newvalues): if 'files' not in newvalues or nodeid is None: return removed(db, cl, nodeid, newvalues, 'files') def removed_msg(db, cl, nodeid, newvalues): if 'messages' not in newvalues or nodeid is None: return removed(db, cl, nodeid, newvalues, 'messages') def init(db): db.issue.audit('set', removed_msg) db.issue.audit('set', removed_file)