details: http://www.bx.psu.edu/hg/galaxy/rev/22addc979108 changeset: 2801:22addc979108 user: Greg Von Kuster <greg@bx.psu.edu> date: Wed Sep 30 05:16:17 2009 -0400 description: Refactored the library_dataset_dataset_association methods in the library_admin and library controllers, renamed the library_dataset controller to be library_common and moved several common methods to it, and some other code cleanup. 43 file(s) affected in this change: lib/galaxy/web/controllers/library.py lib/galaxy/web/controllers/library_admin.py lib/galaxy/web/controllers/library_common.py lib/galaxy/web/controllers/library_dataset.py templates/admin/center.mako templates/admin/library/browse_libraries.mako templates/admin/library/browse_library.mako templates/admin/library/common.mako templates/admin/library/folder_info.mako templates/admin/library/folder_permissions.mako templates/admin/library/ldda_edit_info.mako templates/admin/library/ldda_info.mako templates/admin/library/ldda_permissions.mako templates/admin/library/library_dataset_info.mako templates/admin/library/library_dataset_permissions.mako templates/admin/library/library_info.mako templates/admin/library/library_permissions.mako templates/admin/library/new_folder.mako templates/admin/library/select_info_template.mako templates/admin/library/upload.mako templates/admin/requests/show_request.mako templates/base_panels.mako templates/library/browse_libraries.mako templates/library/browse_library.mako templates/library/common.mako templates/library/folder_info.mako templates/library/folder_permissions.mako templates/library/ldda_edit_info.mako templates/library/ldda_info.mako templates/library/ldda_permissions.mako templates/library/library_dataset_common.mako templates/library/library_dataset_info.mako templates/library/library_dataset_permissions.mako templates/library/library_info.mako templates/library/library_permissions.mako templates/library/new_folder.mako templates/library/select_info_template.mako templates/library/upload.mako templates/mobile/manage_library.mako templates/requests/show_request.mako test/base/twilltestcase.py test/functional/test_forms_and_requests.py test/functional/test_security_and_libraries.py diffs (truncated from 4989 to 3000 lines): diff -r 6a066b05c94f -r 22addc979108 lib/galaxy/web/controllers/library.py --- a/lib/galaxy/web/controllers/library.py Tue Sep 29 21:51:51 2009 -0400 +++ b/lib/galaxy/web/controllers/library.py Wed Sep 30 05:16:17 2009 -0400 @@ -3,7 +3,6 @@ from galaxy.datatypes import sniff from galaxy import util from galaxy.util.odict import odict -from galaxy.web.controllers.forms import get_all_forms from galaxy.util.streamball import StreamBall import logging, tempfile, zipfile, tarfile, os, sys @@ -94,8 +93,8 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - id = params.get( 'id', None ) - if not id: + library_id = params.get( 'obj_id', None ) + if not library_id: # To handle bots msg = "You must specify a library id." return trans.response.send_redirect( web.url_for( controller='library', @@ -103,10 +102,10 @@ default_action=params.get( 'default_action', None ), msg=util.sanitize_text( msg ), messagetype='error' ) ) - library = library=trans.app.model.Library.get( id ) + library = library=trans.app.model.Library.get( library_id ) if not library: # To handle bots - msg = "Invalid library id ( %s )." + msg = "Invalid library id ( %s )." % str( library_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_libraries', default_action=params.get( 'default_action', None ), @@ -126,10 +125,11 @@ msg=msg, messagetype=messagetype ) @web.expose - def library( self, trans, id=None, **kwd ): + def library( self, trans, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) + library_id = params.get( 'obj_id', None ) # TODO: eventually we'll want the ability for users to create libraries if params.get( 'delete', False ): action = 'delete' @@ -137,15 +137,15 @@ action = 'permissions' else: action = 'information' - if not id: + if not library_id: msg = "You must specify a library." return trans.response.send_redirect( web.url_for( controller='library', action='browse_libraries', msg=util.sanitize_text( msg ), messagetype='error' ) ) - library = trans.app.model.Library.get( int( id ) ) + library = trans.app.model.Library.get( int( library_id ) ) if not library: - msg = "Invalid library id ( %s ) specified." % str( id ) + msg = "Invalid library id ( %s ) specified." % str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_libraries', msg=util.sanitize_text( msg ), @@ -175,7 +175,7 @@ msg = "Library '%s' has been renamed to '%s'" % ( old_name, new_name ) return trans.response.send_redirect( web.url_for( controller='library', action='library', - id=id, + obj_id=library.id, edit_info=True, msg=util.sanitize_text( msg ), messagetype='done' ) ) @@ -198,7 +198,7 @@ msg = "Permissions updated for library '%s'" % library.name return trans.response.send_redirect( web.url_for( controller='library', action='library', - id=id, + obj_id=library.id, permissions=True, msg=util.sanitize_text( msg ), messagetype='done' ) ) @@ -207,157 +207,127 @@ msg=msg, messagetype=messagetype ) @web.expose - def datasets( self, trans, library_id, ldda_ids='', **kwd ): - # This method is used by the select list labeled "Perform action on selected datasets" - # on the analysis library browser. - if not ldda_ids: - msg = "You must select at least one dataset" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - ldda_ids = util.listify( ldda_ids ) + def folder( self, trans, obj_id, library_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - if not params.do_action: - msg = "You must select an action to perform on selected datasets" + if params.get( 'new', False ): + action = 'new' + elif params.get( 'delete', False ): + action = 'delete' + elif params.get( 'permissions', False ): + action = 'permissions' + else: + # 'information' will be the default + action = 'information' + folder = trans.app.model.LibraryFolder.get( int( obj_id ) ) + if not folder: + msg = "Invalid folder specified, id: %s" % str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if params.do_action == 'add': - history = trans.get_history() - for ldda_id in ldda_ids: - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id ) - hda = ldda.to_history_dataset_association( target_history=history, add_to_history = True ) - history.flush() - msg = "%i dataset(s) have been imported into your history" % len( ldda_ids ) - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - elif params.do_action == 'manage_permissions': - # We need the folder containing the LibraryDatasetDatasetAssociation(s) - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_ids[0] ) - trans.response.send_redirect( web.url_for( controller='library', - action='library_dataset_dataset_association', - library_id=library_id, - folder_id=ldda.library_dataset.folder.id, - id=','.join( ldda_ids ), - permissions=True, - msg=util.sanitize_text( msg ), - messagetype=messagetype ) ) - else: - try: - if params.do_action == 'zip': - # Can't use mkstemp - the file must not exist first - tmpd = tempfile.mkdtemp() - tmpf = os.path.join( tmpd, 'library_download.' + params.do_action ) - if ziptype == '64': - archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True ) - else: - archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED ) - archive.add = lambda x, y: archive.write( x, y.encode('CP437') ) - elif params.do_action == 'tgz': - archive = util.streamball.StreamBall( 'w|gz' ) - elif params.do_action == 'tbz': - archive = util.streamball.StreamBall( 'w|bz2' ) - except (OSError, zipfile.BadZipFile): - log.exception( "Unable to create archive for download" ) - msg = "Unable to create archive for download, please report this error" + user, roles = trans.get_user_and_roles() + if action == 'new': + if params.new == 'submitted': + new_folder = trans.app.model.LibraryFolder( name=util.restore_text( params.name ), + description=util.restore_text( params.description ) ) + # We are associating the last used genome build with folders, so we will always + # initialize a new folder with the first dbkey in util.dbnames which is currently + # ? unspecified (?) + new_folder.genome_build = util.dbnames.default_value + folder.add_folder( new_folder ) + new_folder.flush() + # New folders default to having the same permissions as their parent folder + trans.app.security_agent.copy_library_permissions( folder, new_folder ) + msg = "New folder named '%s' has been added to the library" % new_folder.name return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), - messagetype='error' ) ) - seen = [] - user, roles = trans.get_user_and_roles() - for id in ldda_ids: - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if not ldda or not trans.app.security_agent.can_access_dataset( roles, ldda.dataset ): - continue - path = "" - parent_folder = ldda.library_dataset.folder - while parent_folder is not None: - # Exclude the now-hidden "root folder" - if parent_folder.parent is None: - path = os.path.join( parent_folder.library_root[0].name, path ) - break - path = os.path.join( parent_folder.name, path ) - parent_folder = parent_folder.parent - path += ldda.name - while path in seen: - path += '_' - seen.append( path ) - try: - archive.add( ldda.dataset.file_name, path ) - except IOError: - log.exception( "Unable to write to temporary library download archive" ) - msg = "Unable to create archive for download, please report this error" + messagetype='done' ) ) + return trans.fill_template( '/library/new_folder.mako', + library_id=library_id, + folder=folder, + msg=msg, + messagetype=messagetype ) + elif action == 'information': + # See if we have any associated templates + widgets = folder.get_template_widgets( trans ) + if params.get( 'rename_folder_button', False ): + if trans.app.security_agent.can_modify_library_item( user, roles, folder ): + old_name = folder.name + new_name = util.restore_text( params.name ) + new_description = util.restore_text( params.description ) + if not new_name: + msg = 'Enter a valid name' + return trans.fill_template( "/library/folder_info.mako", + folder=folder, + library_id=library_id, + widgets=widgets, + msg=msg, + messagetype='error' ) + else: + folder.name = new_name + folder.description = new_description + folder.flush() + msg = "Folder '%s' has been renamed to '%s'" % ( old_name, new_name ) + return trans.response.send_redirect( web.url_for( controller='library', + action='folder', + obj_id=folder.id, + library_id=library_id, + rename=True, + msg=util.sanitize_text( msg ), + messagetype='done' ) ) + else: + msg = "You are not authorized to edit this folder" + return trans.fill_template( "/library/folder_info.mako", + folder=folder, + library_id=library_id, + widgets=widgets, + msg=msg, + messagetype='error' ) + return trans.fill_template( '/library/folder_info.mako', + folder=folder, + library_id=library_id, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif action == 'permissions': + if params.get( 'update_roles_button', False ): + # The user clicked the Save button on the 'Associate With Roles' form + if trans.app.security_agent.can_manage_library_item( user, roles, folder ): + permissions = {} + for k, v in trans.app.model.Library.permitted_actions.items(): + in_roles = [ trans.app.model.Role.get( int( x ) ) for x in util.listify( params.get( k + '_in', [] ) ) ] + permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles + trans.app.security_agent.set_all_library_permissions( folder, permissions ) + folder.refresh() + msg = 'Permissions updated for folder %s' % folder.name return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, + action='folder', + obj_id=folder.id, + library_id=library_id, + permissions=True, + msg=util.sanitize_text( msg ), + messagetype='done' ) ) + else: + msg = "You are not authorized to manage permissions on this folder" + return trans.response.send_redirect( web.url_for( controller='library', + action='folder', + obj_id=folder.id, + library_id=library_id, + permissions=True, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if params.do_action == 'zip': - archive.close() - tmpfh = open( tmpf ) - # clean up now - try: - os.unlink( tmpf ) - os.rmdir( tmpd ) - except OSError: - log.exception( "Unable to remove temporary library download archive and directory" ) - msg = "Unable to create archive for download, please report this error" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - trans.response.set_content_type( "application/x-zip-compressed" ) - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action - return tmpfh - else: - trans.response.set_content_type( "application/x-tar" ) - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action - archive.wsgi_status = trans.response.wsgi_status() - archive.wsgi_headeritems = trans.response.wsgi_headeritems() - return archive.stream + return trans.fill_template( '/library/folder_permissions.mako', + folder=folder, + library_id=library_id, + msg=msg, + messagetype=messagetype ) @web.expose - def download_dataset_from_folder(self, trans, id, library_id=None, **kwd): - """Catches the dataset id and displays file contents as directed""" - # id must refer to a LibraryDatasetDatasetAssociation object - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if not ldda.dataset: - msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file downlaod' % str( id ) - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=msg, - messagetype='error' ) ) - mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() ) - trans.response.set_content_type( mime ) - fStat = os.stat( ldda.file_name ) - trans.response.headers[ 'Content-Length' ] = int( fStat.st_size ) - valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' - fname = ldda.name - fname = ''.join( c in valid_chars and c or '_' for c in fname )[ 0:150 ] - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( id ), fname ) - try: - return open( ldda.file_name ) - except: - msg = 'This dataset contains no content' - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=msg, - messagetype='error' ) ) - @web.expose - def library_dataset( self, trans, id, library_id, **kwd ): + def library_dataset( self, trans, obj_id, library_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -365,12 +335,12 @@ action = 'permissions' else: action = 'information' - library_dataset = trans.app.model.LibraryDataset.get( id ) + library_dataset = trans.app.model.LibraryDataset.get( obj_id ) if not library_dataset: - msg = "Invalid library dataset specified, id: %s" %str( id ) + msg = "Invalid library dataset specified, id: %s" %str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) user, roles = trans.get_user_and_roles() @@ -424,7 +394,248 @@ msg=msg, messagetype=messagetype ) @web.expose - def library_dataset_dataset_association( self, trans, library_id, folder_id, id=None, **kwd ): + def ldda_edit_info( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda: + msg = "Invalid LibraryDatasetDatasetAssociation specified, obj_id: %s" % str( obj_id ) + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + dbkey = params.get( 'dbkey', '?' ) + if isinstance( dbkey, list ): + dbkey = dbkey[0] + user, roles = trans.get_user_and_roles() + file_formats = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ] + file_formats.sort() + # See if we have any associated templates + widgets = ldda.get_template_widgets( trans ) + if params.get( 'change', False ): + # The user clicked the Save button on the 'Change data type' form + if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): + if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change: + trans.app.datatypes_registry.change_datatype( ldda, params.datatype ) + trans.app.model.flush() + msg = "Data type changed for library dataset '%s'" % ldda.name + messagetype = 'done' + else: + msg = "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % ( ldda.extension, params.datatype ) + messagetype = 'error' + else: + msg = "You are not authorized to change the data type of dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif params.get( 'save', False ): + # The user clicked the Save button on the 'Edit Attributes' form + if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): + old_name = ldda.name + new_name = util.restore_text( params.get( 'name', '' ) ) + new_info = util.restore_text( params.get( 'info', '' ) ) + new_message = util.restore_text( params.get( 'message', '' ) ) + if not new_name: + msg = 'Enter a valid name' + messagetype = 'error' + else: + ldda.name = new_name + ldda.info = new_info + ldda.message = new_message + # The following for loop will save all metadata_spec items + for name, spec in ldda.datatype.metadata_spec.items(): + if spec.get("readonly"): + continue + optional = params.get( "is_" + name, None ) + if optional and optional == 'true': + # optional element... == 'true' actually means it is NOT checked (and therefore ommitted) + setattr( ldda.metadata, name, None ) + else: + setattr( ldda.metadata, name, spec.unwrap( params.get ( name, None ) ) ) + ldda.metadata.dbkey = dbkey + ldda.datatype.after_edit( ldda ) + trans.app.model.flush() + msg = 'Attributes updated for library dataset %s' % ldda.name + messagetype = 'done' + else: + msg = "you are not authorized to edit the attributes of dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif params.get( 'detect', False ): + # The user clicked the Auto-detect button on the 'Edit Attributes' form + if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): + for name, spec in ldda.datatype.metadata_spec.items(): + # We need to be careful about the attributes we are resetting + if name not in [ 'name', 'info', 'dbkey' ]: + if spec.get( 'default' ): + setattr( ldda.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) + ldda.datatype.set_meta( ldda ) + ldda.datatype.after_edit( ldda ) + trans.app.model.flush() + msg = 'Attributes updated for library dataset %s' % ldda.name + messagetype = 'done' + else: + msg = "you are not authorized to edit the attributes of dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif params.get( 'delete', False ): + if trans.app.security_agent.can_modify_library_item( user, roles, folder ): + ldda.deleted = True + ldda.flush() + msg = 'Dataset %s has been removed from this data library' % ldda.name + messagetype = 'done' + else: + msg = "you are not authorized to delete dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): + ldda.datatype.before_edit( ldda ) + if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey: + # Copy dbkey into metadata, for backwards compatability + # This looks like it does nothing, but getting the dbkey + # returns the metadata dbkey unless it is None, in which + # case it resorts to the old dbkey. Setting the dbkey + # sets it properly in the metadata + ldda.metadata.dbkey = ldda.dbkey + return trans.fill_template( "/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + @web.expose + def ldda_display_info( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda: + msg = "Invalid LibraryDatasetDatasetAssociation specified, id: %s" % str( obj_id ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + # See if we have any associated templates + widgets = ldda.get_template_widgets( trans ) + return trans.fill_template( '/library/ldda_info.mako', + ldda=ldda, + library_id=library_id, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + @web.expose + def ldda_manage_permissions( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + obj_ids = util.listify( obj_id ) + # Display permission form, permissions will be updated for all lddas simultaneously. + lddas = [] + for obj_id in [ int( obj_id ) for obj_id in obj_ids ]: + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if ldda is None: + msg = 'You specified an invalid LibraryDatasetDatasetAssociation id: %s' %str( obj_id ) + trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + lddas.append( ldda ) + if params.get( 'update_roles_button', False ): + if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \ + trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ): + permissions = {} + for k, v in trans.app.model.Dataset.permitted_actions.items(): + in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] + permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles + for ldda in lddas: + # Set the DATASET permissions on the Dataset + trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) + ldda.dataset.refresh() + permissions = {} + for k, v in trans.app.model.Library.permitted_actions.items(): + in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] + permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles + for ldda in lddas: + # Set the LIBRARY permissions on the LibraryDataset + # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions + trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) + ldda.library_dataset.refresh() + # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation + trans.app.security_agent.set_all_library_permissions( ldda, permissions ) + ldda.refresh() + msg = 'Permissions and roles have been updated on %d datasets' % len( lddas ) + messagetype = 'done' + else: + msg = "You are not authorized to change the permissions of dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_permissions.mako", + ldda=lddas, + library_id=library_id, + msg=msg, + messagetype=messagetype ) + if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \ + trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ): + # Ensure that the permissions across all library items are identical, otherwise we can't update them together. + check_list = [] + for ldda in lddas: + permissions = [] + # Check the library level permissions - the permissions on the LibraryDatasetDatasetAssociation + # will always be the same as the permissions on the associated LibraryDataset, so we only need to + # check one Library object + for library_permission in trans.app.security_agent.get_library_dataset_permissions( ldda.library_dataset ): + if library_permission.action not in permissions: + permissions.append( library_permission.action ) + for dataset_permission in trans.app.security_agent.get_dataset_permissions( ldda.dataset ): + if dataset_permission.action not in permissions: + permissions.append( dataset_permission.action ) + permissions.sort() + if not check_list: + check_list = permissions + if permissions != check_list: + msg = 'The datasets you selected do not have identical permissions, so they can not be updated together' + trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + else: + msg = "You are not authorized to change the permissions of dataset '%s'" % ldda.name + messagetype = 'error' + return trans.fill_template( "/library/ldda_permissions.mako", + ldda=lddas, + library_id=library_id, + msg=msg, + messagetype=messagetype ) + @web.expose + def upload_library_dataset( self, trans, library_id, folder_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -444,279 +655,6 @@ else: replace_dataset = None user, roles = trans.get_user_and_roles() - # Let's not overwrite the imported datatypes module with the variable datatypes? - # The built-in 'id' is overwritten in lots of places as well - ldatatypes = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ] - ldatatypes.sort() - if id: - if params.get( 'permissions', False ): - action = 'permissions' - elif params.get( 'edit_info', False ): - action = 'edit_info' - else: - action = 'info' - if id.count( ',' ): - ids = id.split( ',' ) - id = None - else: - ids = None - else: - ids = None - if id: - # ldda_id specified, display attributes form - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if not ldda: - msg = "Invalid LibraryDatasetDatasetAssociation specified, id: %s" % str( id ) - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - # See if we have any associated templates - widgets = ldda.get_template_widgets( trans ) - if action == 'permissions': - if params.get( 'update_roles_button', False ): - # The user clicked the Save button on the 'Associate With Roles' form - if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \ - trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ): - permissions = {} - for k, v in trans.app.model.Dataset.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - # Set the DATASET permissions on the Dataset - trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) - ldda.dataset.refresh() - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - # Set the LIBRARY permissions on the LibraryDataset - # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions - trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) - ldda.library_dataset.refresh() - # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation - trans.app.security_agent.set_all_library_permissions( ldda, permissions ) - ldda.refresh() - msg = "Permissions updated for dataset '%s'" % ldda.name - messagetype = 'done' - else: - msg = "You are not authorized to change the permissions of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( '/library/ldda_permissions.mako', - ldda=ldda, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - elif action == 'info': - return trans.fill_template( '/library/ldda_info.mako', - ldda=ldda, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif action == 'edit_info': - if params.get( 'change', False ): - # The user clicked the Save button on the 'Change data type' form - if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): - if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change: - trans.app.datatypes_registry.change_datatype( ldda, params.datatype ) - trans.app.model.flush() - msg = "Data type changed for library dataset '%s'" % ldda.name - messagetype = 'done' - else: - msg = "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % ( ldda.extension, params.datatype ) - messagetype = 'error' - else: - msg = "You are not authorized to change the data type of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif params.get( 'save', False ): - # The user clicked the Save button on the 'Edit Attributes' form - if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): - old_name = ldda.name - new_name = util.restore_text( params.get( 'name', '' ) ) - new_info = util.restore_text( params.get( 'info', '' ) ) - new_message = util.restore_text( params.get( 'message', '' ) ) - if not new_name: - msg = 'Enter a valid name' - messagetype = 'error' - else: - ldda.name = new_name - ldda.info = new_info - ldda.message = new_message - # The following for loop will save all metadata_spec items - for name, spec in ldda.datatype.metadata_spec.items(): - if spec.get("readonly"): - continue - optional = params.get( "is_" + name, None ) - if optional and optional == 'true': - # optional element... == 'true' actually means it is NOT checked (and therefore ommitted) - setattr( ldda.metadata, name, None ) - else: - setattr( ldda.metadata, name, spec.unwrap( params.get ( name, None ) ) ) - ldda.metadata.dbkey = dbkey - ldda.datatype.after_edit( ldda ) - trans.app.model.flush() - msg = 'Attributes updated for library dataset %s' % ldda.name - messagetype = 'done' - else: - msg = "you are not authorized to edit the attributes of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif params.get( 'detect', False ): - # The user clicked the Auto-detect button on the 'Edit Attributes' form - if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): - for name, spec in ldda.datatype.metadata_spec.items(): - # We need to be careful about the attributes we are resetting - if name not in [ 'name', 'info', 'dbkey' ]: - if spec.get( 'default' ): - setattr( ldda.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) - ldda.datatype.set_meta( ldda ) - ldda.datatype.after_edit( ldda ) - trans.app.model.flush() - msg = 'Attributes updated for library dataset %s' % ldda.name - messagetype = 'done' - else: - msg = "you are not authorized to edit the attributes of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif params.get( 'delete', False ): - if trans.app.security_agent.can_modify_library_item( user, roles, folder ): - ldda.deleted = True - ldda.flush() - msg = 'Dataset %s has been removed from this library' % ldda.name - messagetype = 'done' - else: - msg = "you are not authorized to delete dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - if trans.app.security_agent.can_modify_library_item( user, roles, ldda ): - ldda.datatype.before_edit( ldda ) - if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey: - # Copy dbkey into metadata, for backwards compatability - # This looks like it does nothing, but getting the dbkey - # returns the metadata dbkey unless it is None, in which - # case it resorts to the old dbkey. Setting the dbkey - # sets it properly in the metadata - ldda.metadata.dbkey = ldda.dbkey - return trans.fill_template( "/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif ids: - # Multiple ids specified, display permission form, permissions will be updated for all simultaneously. - lddas = [] - for id in [ int( id ) for id in ids ]: - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if ldda is None: - msg = 'You specified an invalid LibraryDatasetDatasetAssociation id: %s' %str( id ) - trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - lddas.append( ldda ) - if len( lddas ) < 2: - msg = 'You must specify at least two datasets on which to modify permissions, ids you sent: %s' % str( ids ) - trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - if action == 'permissions': - if params.get( 'update_roles_button', False ): - if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \ - trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ): - permissions = {} - for k, v in trans.app.model.Dataset.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - for ldda in lddas: - # Set the DATASET permissions on the Dataset - trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) - ldda.dataset.refresh() - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - for ldda in lddas: - # Set the LIBRARY permissions on the LibraryDataset - # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions - trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) - ldda.library_dataset.refresh() - # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation - trans.app.security_agent.set_all_library_permissions( ldda, permissions ) - ldda.refresh() - msg = 'Permissions and roles have been updated on %d datasets' % len( lddas ) - messagetype = 'done' - else: - msg = "You are not authorized to change the permissions of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_permissions.mako", - ldda=lddas, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - if trans.app.security_agent.can_manage_library_item( user, roles, ldda ) and \ - trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ): - # Ensure that the permissions across all library items are identical, otherwise we can't update them together. - check_list = [] - for ldda in lddas: - permissions = [] - # Check the library level permissions - the permissions on the LibraryDatasetDatasetAssociation - # will always be the same as the permissions on the associated LibraryDataset, so we only need to - # check one Library object - for library_permission in trans.app.security_agent.get_library_dataset_permissions( ldda.library_dataset ): - if library_permission.action not in permissions: - permissions.append( library_permission.action ) - for dataset_permission in trans.app.security_agent.get_dataset_permissions( ldda.dataset ): - if dataset_permission.action not in permissions: - permissions.append( dataset_permission.action ) - permissions.sort() - if not check_list: - check_list = permissions - if permissions != check_list: - msg = 'The datasets you selected do not have identical permissions, so they can not be updated together' - trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - else: - msg = "You are not authorized to change the permissions of dataset '%s'" % ldda.name - messagetype = 'error' - return trans.fill_template( "/library/ldda_permissions.mako", - ldda=lddas, - library_id=library_id, - msg=msg, - messagetype=messagetype ) if trans.app.security_agent.can_add_library_item( user, roles, folder ) or \ ( replace_dataset and trans.app.security_agent.can_modify_library_item( user, roles, replace_dataset ) ): if params.get( 'runtool_btn', False ) or params.get( 'ajax_upload', False ): @@ -729,7 +667,7 @@ template_id = 'None' widgets = [] upload_option = params.get( 'upload_option', 'upload_file' ) - created_outputs = trans.webapp.controllers[ 'library_dataset' ].upload_dataset( trans, + created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, controller='library', library_id=library_id, folder_id=folder_id, @@ -761,7 +699,7 @@ default_action = 'add' trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, default_action=default_action, created_ldda_ids=",".join( ldda_id_list ), msg=util.sanitize_text( msg ), @@ -771,45 +709,44 @@ msg = "Upload failed" trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, created_ldda_ids=",".join( ldda_id_list ), msg=util.sanitize_text( msg ), messagetype='error' ) ) - if not id or replace_dataset: - # See if we have any inherited templates, but do not inherit contents. - widgets = folder.get_template_widgets( trans, get_contents=False ) - upload_option = params.get( 'upload_option', 'upload_file' ) - # No dataset(s) specified, so display the upload form. Send list of data formats to the form - # so the "extension" select list can be populated dynamically - file_formats = trans.app.datatypes_registry.upload_file_formats - # Send list of genome builds to the form so the "dbkey" select list can be populated dynamically - def get_dbkey_options( last_used_build ): - for dbkey, build_name in util.dbnames: - yield build_name, dbkey, ( dbkey==last_used_build ) - dbkeys = get_dbkey_options( last_used_build ) - # Send list of roles to the form so the dataset can be associated with 1 or more of them. - roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.c.name ).all() - # Send the current history to the form to enable importing datasets from history to library - history = trans.get_history() - history.refresh() - # If we're using nginx upload, override the form action - action = web.url_for( controller='library', action='library_dataset_dataset_association' ) - if upload_option == 'upload_file' and trans.app.config.nginx_upload_path: - action = web.url_for( trans.app.config.nginx_upload_path ) + '?nginx_redir=' + action - return trans.fill_template( '/library/upload.mako', - upload_option=upload_option, - action=action, - library_id=library_id, - folder_id=folder_id, - replace_dataset=replace_dataset, - file_formats=file_formats, - dbkeys=dbkeys, - last_used_build=last_used_build, - roles=roles, - history=history, - widgets=widgets, - msg=msg, - messagetype=messagetype ) + # See if we have any inherited templates, but do not inherit contents. + widgets = folder.get_template_widgets( trans, get_contents=False ) + upload_option = params.get( 'upload_option', 'upload_file' ) + # No dataset(s) specified, so display the upload form. Send list of data formats to the form + # so the "extension" select list can be populated dynamically + file_formats = trans.app.datatypes_registry.upload_file_formats + # Send list of genome builds to the form so the "dbkey" select list can be populated dynamically + def get_dbkey_options( last_used_build ): + for dbkey, build_name in util.dbnames: + yield build_name, dbkey, ( dbkey==last_used_build ) + dbkeys = get_dbkey_options( last_used_build ) + # Send list of roles to the form so the dataset can be associated with 1 or more of them. + roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.c.name ).all() + # Send the current history to the form to enable importing datasets from history to library + history = trans.get_history() + history.refresh() + # If we're using nginx upload, override the form action + action = web.url_for( controller='library', action='upload_library_dataset' ) + if upload_option == 'upload_file' and trans.app.config.nginx_upload_path: + action = web.url_for( trans.app.config.nginx_upload_path ) + '?nginx_redir=' + action + return trans.fill_template( '/library/upload.mako', + upload_option=upload_option, + action=action, + library_id=library_id, + folder_id=folder_id, + replace_dataset=replace_dataset, + file_formats=file_formats, + dbkeys=dbkeys, + last_used_build=last_used_build, + roles=roles, + history=history, + widgets=widgets, + msg=msg, + messagetype=messagetype ) @web.expose def add_history_datasets_to_library( self, trans, library_id, folder_id, hda_ids='', **kwd ): params = util.Params( kwd ) @@ -821,7 +758,7 @@ msg = "Invalid folder id: %s" % str( folder_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) replace_id = params.get( 'replace_id', None ) @@ -836,7 +773,7 @@ msg = 'Your current history is empty' return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if params.get( 'add_history_datasets_to_library_button', False ): @@ -861,7 +798,7 @@ msg = "The requested HistoryDatasetAssociation id %s is invalid" % str( hda_id ) return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if created_ldda_ids: @@ -890,7 +827,7 @@ default_action = 'add' return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, created_ldda_ids=created_ldda_ids.lstrip( ',' ), default_action=default_action, msg=util.sanitize_text( msg ), @@ -923,264 +860,152 @@ msg=msg, messagetype=messagetype ) @web.expose - def folder( self, trans, id, library_id, **kwd ): + def download_dataset_from_folder(self, trans, obj_id, library_id=None, **kwd): + """Catches the dataset id and displays file contents as directed""" + # id must refer to a LibraryDatasetDatasetAssociation object + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda.dataset: + msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file downlaod' % str( obj_id ) + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=msg, + messagetype='error' ) ) + mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() ) + trans.response.set_content_type( mime ) + fStat = os.stat( ldda.file_name ) + trans.response.headers[ 'Content-Length' ] = int( fStat.st_size ) + valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + fname = ldda.name + fname = ''.join( c in valid_chars and c or '_' for c in fname )[ 0:150 ] + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( obj_id ), fname ) + try: + return open( ldda.file_name ) + except: + msg = 'This dataset contains no content' + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=msg, + messagetype='error' ) ) + @web.expose + def datasets( self, trans, library_id, ldda_ids='', **kwd ): + # This method is used by the select list labeled "Perform action on selected datasets" + # on the analysis library browser. + if not ldda_ids: + msg = "You must select at least one dataset" + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + ldda_ids = util.listify( ldda_ids ) params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - if params.get( 'new', False ): - action = 'new' - elif params.get( 'delete', False ): - action = 'delete' - elif params.get( 'permissions', False ): - action = 'permissions' - else: - # 'information' will be the default - action = 'information' - folder = trans.app.model.LibraryFolder.get( int( id ) ) - if not folder: - msg = "Invalid folder specified, id: %s" % str( id ) + if not params.do_action: + msg = "You must select an action to perform on selected datasets" return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - user, roles = trans.get_user_and_roles() - if action == 'new': - if params.new == 'submitted': - new_folder = trans.app.model.LibraryFolder( name=util.restore_text( params.name ), - description=util.restore_text( params.description ) ) - # We are associating the last used genome build with folders, so we will always - # initialize a new folder with the first dbkey in util.dbnames which is currently - # ? unspecified (?) - new_folder.genome_build = util.dbnames.default_value - folder.add_folder( new_folder ) - new_folder.flush() - # New folders default to having the same permissions as their parent folder - trans.app.security_agent.copy_library_permissions( folder, new_folder ) - msg = "New folder named '%s' has been added to the library" % new_folder.name + if params.do_action == 'add': + history = trans.get_history() + for ldda_id in ldda_ids: + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id ) + hda = ldda.to_history_dataset_association( target_history=history, add_to_history = True ) + history.flush() + msg = "%i dataset(s) have been imported into your history" % len( ldda_ids ) + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='done' ) ) + elif params.do_action == 'manage_permissions': + # We need the folder containing the LibraryDatasetDatasetAssociation(s) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_ids[0] ) + trans.response.send_redirect( web.url_for( controller='library', + action='upload_library_dataset', + library_id=library_id, + folder_id=ldda.library_dataset.folder.id, + obj_id=','.join( ldda_ids ), + permissions=True, + msg=util.sanitize_text( msg ), + messagetype=messagetype ) ) + else: + try: + if params.do_action == 'zip': + # Can't use mkstemp - the file must not exist first + tmpd = tempfile.mkdtemp() + tmpf = os.path.join( tmpd, 'library_download.' + params.do_action ) + if ziptype == '64': + archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True ) + else: + archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED ) + archive.add = lambda x, y: archive.write( x, y.encode('CP437') ) + elif params.do_action == 'tgz': + archive = util.streamball.StreamBall( 'w|gz' ) + elif params.do_action == 'tbz': + archive = util.streamball.StreamBall( 'w|bz2' ) + except (OSError, zipfile.BadZipFile): + log.exception( "Unable to create archive for download" ) + msg = "Unable to create archive for download, please report this error" return trans.response.send_redirect( web.url_for( controller='library', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), - messagetype='done' ) ) - return trans.fill_template( '/library/new_folder.mako', - library_id=library_id, - folder=folder, - msg=msg, - messagetype=messagetype ) - elif action == 'information': - # See if we have any associated templates - widgets = folder.get_template_widgets( trans ) - if params.get( 'rename_folder_button', False ): - if trans.app.security_agent.can_modify_library_item( user, roles, folder ): - old_name = folder.name - new_name = util.restore_text( params.name ) - new_description = util.restore_text( params.description ) - if not new_name: - msg = 'Enter a valid name' - return trans.fill_template( "/library/folder_info.mako", - folder=folder, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype='error' ) - else: - folder.name = new_name - folder.description = new_description - folder.flush() - msg = "Folder '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='library', - action='folder', - id=id, - library_id=library_id, - rename=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - else: - msg = "You are not authorized to edit this folder" - return trans.fill_template( "/library/folder_info.mako", - folder=folder, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype='error' ) - return trans.fill_template( '/library/folder_info.mako', - folder=folder, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif action == 'permissions': - if params.get( 'update_roles_button', False ): - # The user clicked the Save button on the 'Associate With Roles' form - if trans.app.security_agent.can_manage_library_item( user, roles, folder ): - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( int( x ) ) for x in util.listify( params.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - trans.app.security_agent.set_all_library_permissions( folder, permissions ) - folder.refresh() - msg = 'Permissions updated for folder %s' % folder.name + messagetype='error' ) ) + seen = [] + user, roles = trans.get_user_and_roles() + for ldda_id in ldda_ids: + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id ) + if not ldda or not trans.app.security_agent.can_access_dataset( roles, ldda.dataset ): + continue + path = "" + parent_folder = ldda.library_dataset.folder + while parent_folder is not None: + # Exclude the now-hidden "root folder" + if parent_folder.parent is None: + path = os.path.join( parent_folder.library_root[0].name, path ) + break + path = os.path.join( parent_folder.name, path ) + parent_folder = parent_folder.parent + path += ldda.name + while path in seen: + path += '_' + seen.append( path ) + try: + archive.add( ldda.dataset.file_name, path ) + except IOError: + log.exception( "Unable to write to temporary library download archive" ) + msg = "Unable to create archive for download, please report this error" return trans.response.send_redirect( web.url_for( controller='library', - action='folder', - id=id, - library_id=library_id, - permissions=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - else: - msg = "You are not authorized to manage permissions on this folder" - return trans.response.send_redirect( web.url_for( controller='library', - action='folder', - id=id, - library_id=library_id, - permissions=True, + action='browse_library', + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - return trans.fill_template( '/library/folder_permissions.mako', - folder=folder, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - @web.expose - def info_template( self, trans, library_id, id=None, folder_id=None, ldda_id=None, **kwd ): - params = util.Params( kwd ) - msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - if id: - library_item = trans.app.model.FormDefinition.get( int( id ) ) - library_item_desc = 'information template' - response_action = 'info_template' - response_id = id - elif folder_id: - library_item = trans.app.model.LibraryFolder.get( int( folder_id ) ) - library_item_desc = 'folder' - response_action = 'folder' - response_id = folder_id - elif ldda_id: - library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( int( ldda_id ) ) - library_item_desc = 'library dataset' - response_action = 'library_dataset_dataset_association' - response_id = ldda_id - else: - library_item = trans.app.model.Library.get( int( library_id ) ) - library_item_desc = 'library' - response_action = 'browse_library' - response_id = library_id - forms = get_all_forms( trans, - filter=dict( deleted=False ), - form_type=trans.app.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE ) - if not forms: - msg = "There are no forms on which to base the template, so create a form and " - msg += "try again to add the information template to the %s." % library_item_desc - trans.response.send_redirect( web.url_for( controller='forms', - action='new', - new=True, - msg=msg, - messagetype='done' ) ) - if params.get( 'add', False ): - if params.get( 'add_info_template_button', False ): - form = trans.app.model.FormDefinition.get( int( kwd[ 'form_id' ] ) ) - #fields = list( copy.deepcopy( form.fields ) ) - form_values = trans.app.model.FormValues( form, [] ) - form_values.flush() - if folder_id: - assoc = trans.app.model.LibraryFolderInfoAssociation( library_item, form, form_values ) - elif ldda_id: - assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, form, form_values ) - else: - assoc = trans.app.model.LibraryInfoAssociation( library_item, form, form_values ) - assoc.flush() - msg = 'An information template based on the form "%s" has been added to this %s.' % ( form.name, library_item_desc ) - trans.response.send_redirect( web.url_for( controller='library', - action=response_action, - id=response_id, - msg=msg, - message_type='done' ) ) - return trans.fill_template( '/admin/library/select_info_template.mako', - library_item_name=library_item.name, - library_item_desc=library_item_desc, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - forms=forms, - msg=msg, - messagetype=messagetype ) - @web.expose - def edit_template_info( self, trans, library_id, num_widgets, library_item_id=None, library_item_type=None, **kwd ): - params = util.Params( kwd ) - msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - folder_id = None - if library_item_type == 'library': - library_item = trans.app.model.Library.get( library_item_id ) - elif library_item_type == 'library_dataset': - library_item = trans.app.model.LibraryDataset.get( library_item_id ) - elif library_item_type == 'folder': - library_item = trans.app.model.LibraryFolder.get( library_item_id ) - elif library_item_type == 'library_dataset_dataset_association': - library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( library_item_id ) - # This response_action method requires a folder_id - folder_id = library_item.library_dataset.folder.id - else: - msg = "Invalid library item type ( %s ) specified, id ( %s )" % ( str( library_item_type ), str( library_item_id ) ) - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - # Save updated template field contents - field_values = [] - for index in range( int( num_widgets ) ): - field_values.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) ) - info = library_item.info_association[0].info - form_values = trans.app.model.FormValues.get( info.id ) - form_values.content = field_values - form_values.flush() - msg = 'The information has been updated.' - return trans.response.send_redirect( web.url_for( controller='library', - action=library_item_type, - id=library_item.id, - library_id=library_id, - folder_id=folder_id, - edit_info=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - -# ---- Utility methods ------------------------------------------------------- - -def active_folders( trans, folder ): - # Much faster way of retrieving all active sub-folders within a given folder than the - # performance of the mapper. This query also eagerloads the permissions on each folder. - return trans.sa_session.query( trans.app.model.LibraryFolder ) \ - .filter_by( parent=folder, deleted=False ) \ - .options( eagerload_all( "actions" ) ) \ - .order_by( trans.app.model.LibraryFolder.table.c.name ) \ - .all() -def activatable_folders( trans, folder ): - return trans.sa_session.query( trans.app.model.LibraryFolder ) \ - .filter_by( parent=folder, purged=False ) \ - .options( eagerload_all( "actions" ) ) \ - .order_by( trans.app.model.LibraryFolder.table.c.name ) \ - .all() -def active_folders_and_lddas( trans, folder ): - folders = active_folders( trans, folder ) - # This query is much faster than the folder.active_library_datasets property - lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ - .filter_by( deleted=False ) \ - .join( "library_dataset" ) \ - .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \ - .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \ - .all() - return folders, lddas -def activatable_folders_and_lddas( trans, folder ): - folders = activatable_folders( trans, folder ) - # This query is much faster than the folder.activatable_library_datasets property - lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ - .join( "library_dataset" ) \ - .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \ - .join( "dataset" ) \ - .filter( trans.app.model.Dataset.table.c.deleted==False ) \ - .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \ - .all() - return folders, lddas + if params.do_action == 'zip': + archive.close() + tmpfh = open( tmpf ) + # clean up now + try: + os.unlink( tmpf ) + os.rmdir( tmpd ) + except OSError: + log.exception( "Unable to remove temporary library download archive and directory" ) + msg = "Unable to create archive for download, please report this error" + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + trans.response.set_content_type( "application/x-zip-compressed" ) + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action + return tmpfh + else: + trans.response.set_content_type( "application/x-tar" ) + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action + archive.wsgi_status = trans.response.wsgi_status() + archive.wsgi_headeritems = trans.response.wsgi_headeritems() + return archive.stream diff -r 6a066b05c94f -r 22addc979108 lib/galaxy/web/controllers/library_admin.py --- a/lib/galaxy/web/controllers/library_admin.py Tue Sep 29 21:51:51 2009 -0400 +++ b/lib/galaxy/web/controllers/library_admin.py Wed Sep 30 05:16:17 2009 -0400 @@ -2,7 +2,6 @@ from galaxy import util from galaxy.web.base.controller import * from galaxy.model.orm import * -from galaxy.web.controllers.forms import get_all_forms # Older py compatibility try: set() @@ -32,18 +31,19 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - id = params.get( 'id', None ) - deleted = util.string_as_bool( params.get( 'deleted', False ) ) - show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) - if not id: + library_id = params.get( 'obj_id', None ) + if not library_id: + # To handle bots msg = "You must specify a library id." return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_libraries', msg=util.sanitize_text( msg ), messagetype='error' ) ) - library = library=trans.app.model.Library.get( id ) + deleted = util.string_as_bool( params.get( 'deleted', False ) ) + show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) + library = library=trans.app.model.Library.get( library_id ) if not library: - msg = "Invalid library id ( %s )." + msg = "Invalid library id ( %s )." % str( library_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_libraries', msg=util.sanitize_text( msg ), @@ -55,17 +55,17 @@ return trans.fill_template( '/admin/library/browse_library.mako', library=library, deleted=deleted, + show_deleted=show_deleted, created_ldda_ids=created_ldda_ids, - forms=get_all_forms( trans, filter=dict(deleted=False) ), msg=msg, - messagetype=messagetype, - show_deleted=show_deleted ) + messagetype=messagetype ) @web.expose @web.require_admin - def library( self, trans, id=None, **kwd ): + def library( self, trans, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) + library_id = params.get( 'obj_id', None ) if params.get( 'new', False ): action = 'new' elif params.get( 'delete', False ): @@ -74,14 +74,14 @@ action = 'permissions' else: action = 'information' - if not id and not action == 'new': + if not library_id and not action == 'new': msg = "You must specify a library to %s." % action return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_libraries', msg=util.sanitize_text( msg ), messagetype='error' ) ) if not action == 'new': - library = trans.app.model.Library.get( int( id ) ) + library = trans.app.model.Library.get( int( library_id ) ) if action == 'new': if params.new == 'submitted': library = trans.app.model.Library( name = util.restore_text( params.name ), @@ -93,7 +93,7 @@ msg = "The new library named '%s' has been created" % library.name return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library.id, + obj_id=library.id, msg=util.sanitize_text( msg ), messagetype='done' ) ) return trans.fill_template( '/admin/library/new_library.mako', msg=msg, messagetype=messagetype ) @@ -122,7 +122,7 @@ msg = "Library '%s' has been renamed to '%s'" % ( old_name, new_name ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='library', - id=id, + obj_id=library.id, edit_info=True, msg=util.sanitize_text( msg ), messagetype='done' ) ) @@ -171,7 +171,7 @@ msg = "Permissions updated for library '%s'" % library.name return trans.response.send_redirect( web.url_for( controller='library_admin', action='library', - id=id, + obj_id=library.id, permissions=True, msg=util.sanitize_text( msg ), messagetype='done' ) ) @@ -198,7 +198,7 @@ @web.require_admin def purge_library( self, trans, **kwd ): params = util.Params( kwd ) - library = trans.app.model.Library.get( int( params.id ) ) + library = trans.app.model.Library.get( int( params.obj_id ) ) def purge_folder( library_folder ): for lf in library_folder.folders: purge_folder( lf ) @@ -240,7 +240,7 @@ messagetype='done' ) ) @web.expose @web.require_admin - def folder( self, trans, id, library_id, **kwd ): + def folder( self, trans, obj_id, library_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -253,12 +253,12 @@ else: # 'information' will be the default action = 'information' - folder = trans.app.model.LibraryFolder.get( int( id ) ) + folder = trans.app.model.LibraryFolder.get( int( obj_id ) ) if not folder: - msg = "Invalid folder specified, id: %s" % str( id ) + msg = "Invalid folder specified, id: %s" % str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if action == 'new': @@ -276,7 +276,7 @@ msg = "New folder named '%s' has been added to the library" % new_folder.name return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='done' ) ) return trans.fill_template( '/admin/library/new_folder.mako', @@ -306,7 +306,7 @@ msg = "Folder '%s' has been renamed to '%s'" % ( old_name, new_name ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='folder', - id=id, + obj_id=folder.id, library_id=library_id, edit_info=True, msg=util.sanitize_text( msg ), @@ -322,7 +322,7 @@ folder.flush() msg = "Folder '%s' and all of its contents have been marked deleted" % folder.name return trans.response.send_redirect( web.url_for( action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='done' ) ) elif action =='permissions': @@ -337,7 +337,7 @@ msg = "Permissions updated for folder '%s'" % folder.name return trans.response.send_redirect( web.url_for( controller='library_admin', action='folder', - id=id, + obj_id=folder.id, library_id=library_id, permissions=True, msg=util.sanitize_text( msg ), @@ -349,7 +349,7 @@ messagetype=messagetype ) @web.expose @web.require_admin - def library_dataset( self, trans, id, library_id, **kwd ): + def library_dataset( self, trans, obj_id, library_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -357,12 +357,12 @@ action = 'permissions' else: action = 'information' - library_dataset = trans.app.model.LibraryDataset.get( id ) + library_dataset = trans.app.model.LibraryDataset.get( obj_id ) if not library_dataset: - msg = "Invalid library dataset specified, id: %s" %str( id ) + msg = "Invalid library dataset specified, id: %s" %str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if action == 'information': @@ -406,13 +406,261 @@ messagetype=messagetype ) @web.expose @web.require_admin - def library_dataset_dataset_association( self, trans, library_id, folder_id, id=None, **kwd ): + def ldda_edit_info( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda: + msg = "Invalid LibraryDatasetDatasetAssociation specified, obj_id: %s" % str( obj_id ) + return trans.response.send_redirect( web.url_for( controller='library_admin', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + dbkey = params.get( 'dbkey', '?' ) + if isinstance( dbkey, list ): + dbkey = dbkey[0] + file_formats = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ] + file_formats.sort() + # See if we have any associated templates + widgets = ldda.get_template_widgets( trans ) + if params.get( 'change', False ): + # The user clicked the Save button on the 'Change data type' form + if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change: + trans.app.datatypes_registry.change_datatype( ldda, params.datatype ) + trans.app.model.flush() + msg = "Data type changed for library dataset '%s'" % ldda.name + return trans.fill_template( "/admin/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + else: + return trans.show_error_message( "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % \ + ( ldda.extension, params.datatype ) ) + elif params.get( 'save', False ): + # The user clicked the Save button on the 'Edit Attributes' form + old_name = ldda.name + new_name = util.restore_text( params.get( 'name', '' ) ) + new_info = util.restore_text( params.get( 'info', '' ) ) + new_message = util.restore_text( params.get( 'message', '' ) ) + if not new_name: + msg = 'Enter a valid name' + messagetype = 'error' + else: + ldda.name = new_name + ldda.info = new_info + ldda.message = new_message + # The following for loop will save all metadata_spec items + for name, spec in ldda.datatype.metadata_spec.items(): + if spec.get("readonly"): + continue + optional = params.get( "is_" + name, None ) + if optional and optional == 'true': + # optional element... == 'true' actually means it is NOT checked (and therefore ommitted) + setattr( ldda.metadata, name, None ) + else: + setattr( ldda.metadata, name, spec.unwrap( params.get ( name, None ) ) ) + ldda.metadata.dbkey = dbkey + ldda.datatype.after_edit( ldda ) + trans.app.model.flush() + msg = 'Attributes updated for library dataset %s' % ldda.name + messagetype = 'done' + return trans.fill_template( "/admin/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif params.get( 'detect', False ): + # The user clicked the Auto-detect button on the 'Edit Attributes' form + for name, spec in ldda.datatype.metadata_spec.items(): + # We need to be careful about the attributes we are resetting + if name not in [ 'name', 'info', 'dbkey' ]: + if spec.get( 'default' ): + setattr( ldda.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) + ldda.datatype.set_meta( ldda ) + ldda.datatype.after_edit( ldda ) + trans.app.model.flush() + msg = 'Attributes updated for library dataset %s' % ldda.name + return trans.fill_template( "/admin/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + elif params.get( 'delete', False ): + ldda.deleted = True + ldda.flush() + msg = 'Dataset %s has been removed from this data library' % ldda.name + return trans.fill_template( "/admin/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + ldda.datatype.before_edit( ldda ) + if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey: + # Copy dbkey into metadata, for backwards compatability + # This looks like it does nothing, but getting the dbkey + # returns the metadata dbkey unless it is None, in which + # case it resorts to the old dbkey. Setting the dbkey + # sets it properly in the metadata + ldda.metadata.dbkey = ldda.dbkey + return trans.fill_template( "/admin/library/ldda_edit_info.mako", + ldda=ldda, + library_id=library_id, + file_formats=file_formats, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + @web.expose + @web.require_admin + def ldda_display_info( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda: + msg = "Invalid LibraryDatasetDatasetAssociation specified, obj_id: %s" % str( obj_id ) + return trans.response.send_redirect( web.url_for( controller='library_admin', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + # See if we have any associated templates + widgets = ldda.get_template_widgets( trans ) + return trans.fill_template( '/admin/library/ldda_info.mako', + ldda=ldda, + library_id=library_id, + show_deleted=show_deleted, + widgets=widgets, + msg=msg, + messagetype=messagetype ) + @web.expose + @web.require_admin + def ldda_manage_permissions( self, trans, library_id, folder_id, obj_id, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + obj_ids = util.listify( obj_id ) + # Display permission form, permissions will be updated for all lddas simultaneously. + lddas = [] + for obj_id in [ int( obj_id ) for obj_id in obj_ids ]: + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if ldda is None: + msg = 'You specified an invalid LibraryDatasetDatasetAssociation obj_id: %s' %str( obj_id ) + trans.response.send_redirect( web.url_for( controller='library_admin', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + lddas.append( ldda ) + if params.get( 'update_roles_button', False ): + permissions = {} + accessible = False + for k, v in trans.app.model.Dataset.permitted_actions.items(): + in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] + # At least 1 user must have every role associated with this dataset, or the dataset is inaccessible + if v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: + if len( in_roles ) > 1: + # Get the set of all users that are being associated with the dataset + in_roles_set = set() + for role in in_roles: + in_roles_set.add( role ) + users_set = set() + for role in in_roles: + for ura in role.users: + users_set.add( ura.user ) + # Make sure that at least 1 user has every role being associated with the dataset + for user in users_set: + user_roles_set = set() + for ura in user.roles: + user_roles_set.add( ura.role ) + if in_roles_set.issubset( user_roles_set ): + accessible = True + break + else: + accessible = True + if not accessible and v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: + # Don't set the permissions for DATASET_ACCESS if inaccessbile, but set all other permissions + # TODO: keep access permissions as they originally were, rather than automatically making public + permissions[ trans.app.security_agent.get_action( v.action ) ] = [] + else: + permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles + for ldda in lddas: + # Set the DATASET permissions on the Dataset + trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) + ldda.dataset.refresh() + permissions = {} + for k, v in trans.app.model.Library.permitted_actions.items(): + in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] + permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles + for ldda in lddas: + # Set the LIBRARY permissions on the LibraryDataset + # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions + trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) + ldda.library_dataset.refresh() + # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation + trans.app.security_agent.set_all_library_permissions( ldda, permissions ) + ldda.refresh() + if not accessible: + msg = "At least 1 user must have every role associated with accessing these %d datasets. " % len( lddas ) + msg += "The roles you attempted to associate for access would make these datasets inaccessible by everyone, " + msg += "so access permissions were not set. All other permissions were updated for the datasets." + messagetype = 'error' + else: + msg = "Permissions have been updated on %d datasets" % len( lddas ) + return trans.fill_template( "/admin/library/ldda_permissions.mako", + lddas=lddas, + library_id=library_id, + msg=msg, + messagetype=messagetype ) + if len( obj_ids ) > 1: + # Ensure that the permissions across all library items are identical, otherwise we can't update them together. + check_list = [] + for ldda in lddas: + permissions = [] + # Check the library level permissions - the permissions on the LibraryDatasetDatasetAssociation + # will always be the same as the permissions on the associated LibraryDataset, so we only need to + # check one Library object + for library_permission in trans.app.security_agent.get_library_dataset_permissions( ldda.library_dataset ): + if library_permission.action not in permissions: + permissions.append( library_permission.action ) + for dataset_permission in trans.app.security_agent.get_dataset_permissions( ldda.dataset ): + if dataset_permission.action not in permissions: + permissions.append( dataset_permission.action ) + permissions.sort() + if not check_list: + check_list = permissions + if permissions != check_list: + msg = 'The datasets you selected do not have identical permissions, so they can not be updated together' + trans.response.send_redirect( web.url_for( controller='library_admin', + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + return trans.fill_template( "/admin/library/ldda_permissions.mako", + lddas=lddas, + library_id=library_id, + msg=msg, + messagetype=messagetype ) + @web.expose + @web.require_admin + def upload_library_dataset( self, trans, library_id, folder_id, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) deleted = util.string_as_bool( params.get( 'deleted', False ) ) show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) - dbkey = params.get( 'dbkey', None ) + dbkey = params.get( 'dbkey', '?' ) if isinstance( dbkey, list ): last_used_build = dbkey[0] else: @@ -427,10 +675,6 @@ last_used_build = replace_dataset.library_dataset_dataset_association.dbkey else: replace_dataset = None - # Let's not overwrite the imported datatypes module with the variable datatypes? - # The built-in 'id' is overwritten in lots of places as well - ldatatypes = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ] - ldatatypes.sort() if params.get( 'runtool_btn', False ) or params.get( 'ajax_upload', False ): # See if we have any inherited templates, but do not inherit contents. info_association, inherited = folder.get_info_association( inherited=True ) @@ -441,7 +685,7 @@ template_id = 'None' widgets = [] upload_option = params.get( 'upload_option', 'upload_file' ) - created_outputs = trans.webapp.controllers[ 'library_dataset' ].upload_dataset( trans, + created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, controller='library_admin', library_id=library_id, folder_id=folder_id, @@ -466,345 +710,44 @@ messagetype='error' trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, created_ldda_ids=",".join( [ str( v.id ) for v in created_outputs.values() ] ), msg=util.sanitize_text( msg ), messagetype=messagetype ) ) - elif not id or replace_dataset: - # See if we have any inherited templates, but do not inherit contents. - widgets = folder.get_template_widgets( trans, get_contents=False ) - upload_option = params.get( 'upload_option', 'upload_file' ) - # No dataset(s) specified, so display the upload form. Send list of data formats to the form - # so the "extension" select list can be populated dynamically - file_formats = trans.app.datatypes_registry.upload_file_formats - # Send list of genome builds to the form so the "dbkey" select list can be populated dynamically - def get_dbkey_options( last_used_build ): - for dbkey, build_name in util.dbnames: - yield build_name, dbkey, ( dbkey==last_used_build ) - dbkeys = get_dbkey_options( last_used_build ) - # Send list of roles to the form so the dataset can be associated with 1 or more of them. - roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.c.name ).all() - # Send the current history to the form to enable importing datasets from history to library - history = trans.get_history() - history.refresh() - # If we're using nginx upload, override the form action - action = web.url_for( controller='library_admin', action='library_dataset_dataset_association' ) - if upload_option == 'upload_file' and trans.app.config.nginx_upload_path: - action = web.url_for( trans.app.config.nginx_upload_path ) + '?nginx_redir=' + action - return trans.fill_template( '/admin/library/upload.mako', - upload_option=upload_option, - action=action, - library_id=library_id, - folder_id=folder_id, - replace_dataset=replace_dataset, - file_formats=file_formats, - dbkeys=dbkeys, - last_used_build=last_used_build, - roles=roles, - history=history, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - else: - if params.get( 'permissions', False ): - action = 'permissions' - elif params.get( 'edit_info', False ): - action = 'edit_info' - else: - action = 'info' - if id.count( ',' ): - ids = id.split( ',' ) - id = None - else: - ids = None - if id: - # ldda_id specified, display attributes form - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if not ldda: - msg = "Invalid LibraryDatasetDatasetAssociation specified, id: %s" % str( id ) - return trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - # See if we have any associated templates - widgets = ldda.get_template_widgets( trans ) - if action == 'permissions': - if params.get( 'update_roles_button', False ): - permissions = {} - accessible = False - for k, v in trans.app.model.Dataset.permitted_actions.items(): - # TODO: need to handle case where a user has the DATASET_MANAGE_PERMISSIONS permission, but not - # the DATASET_ACCESS permission, making the former useless. Need to display a warning message. - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] - # At least 1 user must have every role associated with this dataset, or the dataset is inaccessible - if v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: - if len( in_roles ) > 1: - # Get the set of all users that are being associated with the dataset - in_roles_set = set() - for role in in_roles: - in_roles_set.add( role ) - users_set = set() - for role in in_roles: - for ura in role.users: - users_set.add( ura.user ) - # Make sure that at least 1 user has every role being associated with the dataset - for user in users_set: - user_roles_set = set() - for ura in user.roles: - user_roles_set.add( ura.role ) - if in_roles_set.issubset( user_roles_set ): - accessible = True - break - else: - accessible = True - if not accessible and v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: - # Don't set the permissions for DATASET_ACCESS if inaccessbile, but set all other permissions - # TODO: keep access permissions as they originally were, rather than automatically making public - permissions[ trans.app.security_agent.get_action( v.action ) ] = [] - else: - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - # Set the DATASET permissions on the Dataset - trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) - ldda.dataset.refresh() - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - # Set the LIBRARY permissions on the LibraryDataset - # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions - trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) - ldda.library_dataset.refresh() - # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation - trans.app.security_agent.set_all_library_permissions( ldda, permissions ) - ldda.refresh() - if not accessible: - msg = "At least 1 user must have every role associated with accessing dataset '%s'. " % ldda.name - msg += "The roles you attempted to associate for access would make this dataset inaccessible by everyone, " - msg += "so access permissions were not set. All other permissions were updated for the dataset." - messagetype = 'error' - else: - msg = "Permissions updated for dataset '%s'" % ldda.name - return trans.fill_template( '/admin/library/ldda_permissions.mako', - ldda=ldda, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - elif action == 'info': - return trans.fill_template( '/admin/library/ldda_info.mako', - ldda=ldda, - library_id=library_id, - deleted=deleted, - show_deleted=show_deleted, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif action == 'edit_info': - if params.get( 'change', False ): - # The user clicked the Save button on the 'Change data type' form - if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change: - trans.app.datatypes_registry.change_datatype( ldda, params.datatype ) - trans.app.model.flush() - msg = "Data type changed for library dataset '%s'" % ldda.name - return trans.fill_template( "/admin/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - else: - return trans.show_error_message( "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % ( ldda.extension, params.datatype ) ) - elif params.get( 'save', False ): - # The user clicked the Save button on the 'Edit Attributes' form - old_name = ldda.name - new_name = util.restore_text( params.get( 'name', '' ) ) - new_info = util.restore_text( params.get( 'info', '' ) ) - new_message = util.restore_text( params.get( 'message', '' ) ) - if not new_name: - msg = 'Enter a valid name' - messagetype = 'error' - else: - ldda.name = new_name - ldda.info = new_info - ldda.message = new_message - # The following for loop will save all metadata_spec items - for name, spec in ldda.datatype.metadata_spec.items(): - if spec.get("readonly"): - continue - optional = params.get( "is_" + name, None ) - if optional and optional == 'true': - # optional element... == 'true' actually means it is NOT checked (and therefore ommitted) - setattr( ldda.metadata, name, None ) - else: - setattr( ldda.metadata, name, spec.unwrap( params.get ( name, None ) ) ) - ldda.metadata.dbkey = dbkey - ldda.datatype.after_edit( ldda ) - trans.app.model.flush() - msg = 'Attributes updated for library dataset %s' % ldda.name - messagetype = 'done' - return trans.fill_template( "/admin/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif params.get( 'detect', False ): - # The user clicked the Auto-detect button on the 'Edit Attributes' form - for name, spec in ldda.datatype.metadata_spec.items(): - # We need to be careful about the attributes we are resetting - if name not in [ 'name', 'info', 'dbkey' ]: - if spec.get( 'default' ): - setattr( ldda.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) - ldda.datatype.set_meta( ldda ) - ldda.datatype.after_edit( ldda ) - trans.app.model.flush() - msg = 'Attributes updated for library dataset %s' % ldda.name - return trans.fill_template( "/admin/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif params.get( 'delete', False ): - ldda.deleted = True - ldda.flush() - msg = 'Dataset %s has been removed from this library' % ldda.name - return trans.fill_template( "/admin/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - ldda.datatype.before_edit( ldda ) - if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey: - # Copy dbkey into metadata, for backwards compatability - # This looks like it does nothing, but getting the dbkey - # returns the metadata dbkey unless it is None, in which - # case it resorts to the old dbkey. Setting the dbkey - # sets it properly in the metadata - ldda.metadata.dbkey = ldda.dbkey - return trans.fill_template( "/admin/library/ldda_edit_info.mako", - ldda=ldda, - library_id=library_id, - datatypes=ldatatypes, - widgets=widgets, - msg=msg, - messagetype=messagetype ) - elif ids: - # Multiple ids specfied, display permission form, permissions will be updated for all simultaneously. - lddas = [] - for id in [ int( id ) for id in ids ]: - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if ldda is None: - msg = 'You specified an invalid LibraryDatasetDatasetAssociation id: %s' %str( id ) - trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - lddas.append( ldda ) - if len( lddas ) < 2: - msg = 'You must specify at least two datasets on which to modify permissions, ids you sent: %s' % str( ids ) - trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - if action == 'permissions': - if params.get( 'update_roles_button', False ): - permissions = {} - accessible = False - for k, v in trans.app.model.Dataset.permitted_actions.items(): - # TODO: need to handle case where a user has the DATASET_MANAGE_PERMISSIONS permission, but not - # the DATASET_ACCESS permission, making the former useless. Need to display a warning message. - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( params.get( k + '_in', [] ) ) ] - # At least 1 user must have every role associated with this dataset, or the dataset is inaccessible - if v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: - if len( in_roles ) > 1: - # Get the set of all users that are being associated with the dataset - in_roles_set = set() - for role in in_roles: - in_roles_set.add( role ) - users_set = set() - for role in in_roles: - for ura in role.users: - users_set.add( ura.user ) - # Make sure that at least 1 user has every role being associated with the dataset - for user in users_set: - user_roles_set = set() - for ura in user.roles: - user_roles_set.add( ura.role ) - if in_roles_set.issubset( user_roles_set ): - accessible = True - break - else: - accessible = True - if not accessible and v == trans.app.security_agent.permitted_actions.DATASET_ACCESS: - # Don't set the permissions for DATASET_ACCESS if inaccessbile, but set all other permissions - # TODO: keep access permissions as they originally were, rather than automatically making public - permissions[ trans.app.security_agent.get_action( v.action ) ] = [] - else: - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - for ldda in lddas: - # Set the DATASET permissions on the Dataset - trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) - ldda.dataset.refresh() - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.app.model.Role.get( x ) for x in util.listify( kwd.get( k + '_in', [] ) ) ] - permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles - for ldda in lddas: - # Set the LIBRARY permissions on the LibraryDataset - # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions - trans.app.security_agent.set_all_library_permissions( ldda.library_dataset, permissions ) - ldda.library_dataset.refresh() - # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation - trans.app.security_agent.set_all_library_permissions( ldda, permissions ) - ldda.refresh() - if not accessible: - msg = "At least 1 user must have every role associated with accessing these %d datasets. " % len( lddas ) - msg += "The roles you attempted to associate for access would make these datasets inaccessible by everyone, " - msg += "so access permissions were not set. All other permissions were updated for the datasets." - messagetype = 'error' - else: - msg = "Permissions have been updated on %d datasets" % len( lddas ) - return trans.fill_template( "/admin/library/ldda_permissions.mako", - ldda=lddas, - library_id=library_id, - msg=msg, - messagetype=messagetype ) - # Ensure that the permissions across all library items are identical, otherwise we can't update them together. - check_list = [] - for ldda in lddas: - permissions = [] - # Check the library level permissions - the permissions on the LibraryDatasetDatasetAssociation - # will always be the same as the permissions on the associated LibraryDataset, so we only need to - # check one Library object - for library_permission in trans.app.security_agent.get_library_dataset_permissions( ldda.library_dataset ): - if library_permission.action not in permissions: - permissions.append( library_permission.action ) - for dataset_permission in trans.app.security_agent.get_dataset_permissions( ldda.dataset ): - if dataset_permission.action not in permissions: - permissions.append( dataset_permission.action ) - permissions.sort() - if not check_list: - check_list = permissions - if permissions != check_list: - msg = 'The datasets you selected do not have identical permissions, so they can not be updated together' - trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - return trans.fill_template( "/admin/library/ldda_permissions.mako", - ldda=lddas, - library_id=library_id, - msg=msg, - messagetype=messagetype ) + # See if we have any inherited templates, but do not inherit contents. + widgets = folder.get_template_widgets( trans, get_contents=False ) + upload_option = params.get( 'upload_option', 'upload_file' ) + # No dataset(s) specified, so display the upload form. Send list of data formats to the form + # so the "extension" select list can be populated dynamically + file_formats = trans.app.datatypes_registry.upload_file_formats + # Send list of genome builds to the form so the "dbkey" select list can be populated dynamically + def get_dbkey_options( last_used_build ): + for dbkey, build_name in util.dbnames: + yield build_name, dbkey, ( dbkey==last_used_build ) + dbkeys = get_dbkey_options( last_used_build ) + # Send list of roles to the form so the dataset can be associated with 1 or more of them. + roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.c.name ).all() + # Send the current history to the form to enable importing datasets from history to library + history = trans.get_history() + history.refresh() + # If we're using nginx upload, override the form action + action = web.url_for( controller='library_admin', action='upload_library_dataset' ) + if upload_option == 'upload_file' and trans.app.config.nginx_upload_path: + action = web.url_for( trans.app.config.nginx_upload_path ) + '?nginx_redir=' + action + return trans.fill_template( '/admin/library/upload.mako', + upload_option=upload_option, + action=action, + library_id=library_id, + folder_id=folder_id, + replace_dataset=replace_dataset, + file_formats=file_formats, + dbkeys=dbkeys, + last_used_build=last_used_build, + roles=roles, + history=history, + widgets=widgets, + msg=msg, + messagetype=messagetype ) @web.expose @web.require_admin def add_history_datasets_to_library( self, trans, library_id, folder_id, hda_ids='', **kwd ): @@ -817,7 +760,7 @@ msg = "Invalid folder id: %s" % str( folder_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) replace_id = params.get( 'replace_id', None ) @@ -832,7 +775,7 @@ msg = 'Your current history is empty' return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if params.get( 'add_history_datasets_to_library_button', False ): @@ -857,7 +800,7 @@ msg = "The requested HistoryDatasetAssociation id %s is invalid" % str( hda_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) if created_ldda_ids: @@ -875,7 +818,7 @@ msg += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, created_ldda_ids=created_ldda_ids, msg=util.sanitize_text( msg ), messagetype='done' ) ) @@ -908,146 +851,15 @@ messagetype=messagetype ) @web.expose @web.require_admin - def info_template( self, trans, library_id, id=None, folder_id=None, ldda_id=None, **kwd ): - params = util.Params( kwd ) - msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - if id: - library_item = trans.app.model.FormDefinition.get( int( id ) ) - library_item_desc = 'information template' - response_action = 'info_template' - response_id = id - elif folder_id: - library_item = trans.app.model.LibraryFolder.get( int( folder_id ) ) - library_item_desc = 'folder' - response_action = 'folder' - response_id = folder_id - elif ldda_id: - library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( int( ldda_id ) ) - library_item_desc = 'library dataset' - response_action = 'library_dataset_dataset_association' - response_id = ldda_id - else: - library_item = trans.app.model.Library.get( int( library_id ) ) - library_item_desc = 'library' - response_action = 'browse_library' - response_id = library_id - forms = get_all_forms( trans, - filter=dict( deleted=False ), - form_type=trans.app.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE ) - if not forms: - msg = "There are no forms on which to base the template, so create a form and " - msg += "try again to add the information template to the %s." % library_item_desc - trans.response.send_redirect( web.url_for( controller='forms', - action='new', - new=True, - msg=msg, - messagetype='done' ) ) - if params.get( 'add', False ): - if params.get( 'add_info_template_button', False ): - form = trans.app.model.FormDefinition.get( int( kwd[ 'form_id' ] ) ) - #fields = list( copy.deepcopy( form.fields ) ) - form_values = trans.app.model.FormValues( form, [] ) - form_values.flush() - if folder_id: - assoc = trans.app.model.LibraryFolderInfoAssociation( library_item, form, form_values ) - elif ldda_id: - assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, form, form_values ) - else: - assoc = trans.app.model.LibraryInfoAssociation( library_item, form, form_values ) - assoc.flush() - msg = 'An information template based on the form "%s" has been added to this %s.' % ( form.name, library_item_desc ) - trans.response.send_redirect( web.url_for( controller='library_admin', - action=response_action, - id=response_id, - msg=msg, - message_type='done' ) ) - return trans.fill_template( '/admin/library/select_info_template.mako', - library_item_name=library_item.name, - library_item_desc=library_item_desc, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - forms=forms, - msg=msg, - messagetype=messagetype ) - @web.expose - @web.require_admin - def edit_template_info( self, trans, library_id, num_widgets, library_item_id=None, library_item_type=None, **kwd ): - params = util.Params( kwd ) - msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - folder_id = None - if library_item_type == 'library': - library_item = trans.app.model.Library.get( library_item_id ) - elif library_item_type == 'library_dataset': - library_item = trans.app.model.LibraryDataset.get( library_item_id ) - elif library_item_type == 'folder': - library_item = trans.app.model.LibraryFolder.get( library_item_id ) - elif library_item_type == 'library_dataset_dataset_association': - library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( library_item_id ) - # This response_action method requires a folder_id - folder_id = library_item.library_dataset.folder.id - else: - msg = "Invalid library item type ( %s ) specified, id ( %s )" % ( str( library_item_type ), str( library_item_id ) ) + def download_dataset_from_folder(self, trans, obj_id, library_id=None, **kwd): + """Catches the dataset id and displays file contents as directed""" + # id must refer to a LibraryDatasetDatasetAssociation object + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( obj_id ) + if not ldda.dataset: + msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file downlaod' % str( obj_id ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - # Save updated template field contents - field_contents = [] - for index in range( int( num_widgets ) ): - field_contents.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) ) - if field_contents: - # Since information templates are inherited, the template fields can be displayed on the information - # page for a folder or library dataset when it has no info_association object. If the user has added - # field contents on an inherited template via a parent's info_association, we'll need to create a new - # form_values and info_association for the current object. The value for the returned inherited variable - # is not applicable at this level. - info_association, inherited = library_item.get_info_association( restrict=True ) - if info_association: - template = info_association.template - info = info_association.info - form_values = trans.app.model.FormValues.get( info.id ) - # Update existing content only if it has changed - if form_values.content != field_contents: - form_values.content = field_contents - form_values.flush() - else: - # Inherit the next available info_association so we can get the template - info_association, inherited = library_item.get_info_association() - template = info_association.template - # Create a new FormValues object - form_values = trans.app.model.FormValues( template, field_contents ) - form_values.flush() - # Create a new info_association between the current library item and form_values - if library_item_type == 'folder': - info_association = trans.app.model.LibraryFolderInfoAssociation( library_item, template, form_values ) - info_association.flush() - elif library_item_type == 'library_dataset_dataset_association': - info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, template, form_values ) - info_association.flush() - msg = 'The information has been updated.' - return trans.response.send_redirect( web.url_for( controller='library_admin', - action=library_item_type, - id=library_item.id, - library_id=library_id, - folder_id=folder_id, - edit_info=True, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - @web.expose - @web.require_admin - def download_dataset_from_folder(self, trans, id, library_id=None, **kwd): - """Catches the dataset id and displays file contents as directed""" - # id must refer to a LibraryDatasetDatasetAssociation object - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - if not ldda.dataset: - msg = 'Invalid LibraryDatasetDatasetAssociation id %s received for file downlaod' % str( id ) - return trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) mime = trans.app.datatypes_registry.get_mimetype_by_extension( ldda.extension.lower() ) @@ -1057,14 +869,14 @@ valid_chars = '.,^_-()[]0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' fname = ldda.name fname = ''.join( c in valid_chars and c or '_' for c in fname )[ 0:150 ] - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( id ), fname ) + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryDataset-%s-[%s]" % ( str( obj_id ), fname ) try: return open( ldda.file_name ) except: msg = 'This dataset contains no content' return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) @web.expose @@ -1076,48 +888,40 @@ msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) if params.get( 'action_on_datasets_button', False ): - if not params.ldda_ids: + ldda_ids = util.listify( params.get( 'ldda_ids', None ) ) + if not ldda_ids: msg = "At least one dataset must be selected for %s" % params.action trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - ldda_ids = util.listify( params.ldda_ids ) - if params.action == 'edit': + if params.action == 'manage_permissions': # We need the folder containing the LibraryDatasetDatasetAssociation(s) - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_ids[0] ) + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( int( ldda_ids[0] ) ) trans.response.send_redirect( web.url_for( controller='library_admin', - action='library_dataset_dataset_association', + action='ldda_manage_permissions', library_id=library_id, folder_id=ldda.library_dataset.folder.id, - id=",".join( ldda_ids ), - permissions=True, + obj_id=",".join( ldda_ids ), msg=util.sanitize_text( msg ), messagetype=messagetype ) ) elif params.action == 'delete': - for id in ldda_ids: - ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) + for ldda_id in ldda_ids: + ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id ) ldda.deleted = True ldda.flush() - msg = "The selected datasets have been removed from this library" + msg = "The selected datasets have been removed from this data library" trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, show_deleted=False, msg=util.sanitize_text( msg ), messagetype='done' ) ) - else: - msg = "Action %s is not yet implemented" % str( params.action ) - trans.response.send_redirect( web.url_for( controller='library_admin', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) else: trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_library', - id=library_id, + obj_id=library_id, msg=util.sanitize_text( msg ), messagetype=messagetype ) ) @web.expose @@ -1149,7 +953,10 @@ if library_item_type == 'library': return self.browse_libraries( trans, msg=msg, messagetype=messagetype ) else: - return self.browse_library( trans, id=library_id , msg=msg, messagetype=messagetype ) + return self.browse_library( trans, + obj_id=library_id, + msg=msg, + messagetype=messagetype ) @web.expose @web.require_admin def undelete_library_item( self, trans, library_id, library_item_id, library_item_type ): @@ -1177,4 +984,7 @@ if library_item_type == 'library': return self.browse_libraries( trans, msg=msg, messagetype=messagetype ) else: - return self.browse_library( trans, id=library_id , msg=msg, messagetype=messagetype ) + return self.browse_library( trans, + obj_id=library_id, + msg=msg, + messagetype=messagetype ) diff -r 6a066b05c94f -r 22addc979108 lib/galaxy/web/controllers/library_common.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/web/controllers/library_common.py Wed Sep 30 05:16:17 2009 -0400 @@ -0,0 +1,300 @@ +import os, os.path, shutil, urllib, StringIO, re, gzip, tempfile, shutil, zipfile +from galaxy.web.base.controller import * +from galaxy import util, jobs +from galaxy.datatypes import sniff +from galaxy.security import RBACAgent +from galaxy.util.json import to_json_string +from galaxy.tools.actions import upload_common +from galaxy.web.controllers.forms import get_all_forms +from galaxy.model.orm import * + +log = logging.getLogger( __name__ ) + +class LibraryCommon( BaseController ): + @web.json + def library_item_updates( self, trans, ids=None, states=None ): + # Avoid caching + trans.response.headers['Pragma'] = 'no-cache' + trans.response.headers['Expires'] = '0' + # Create new HTML for any that have changed + rval = {} + if ids is not None and states is not None: + ids = map( int, ids.split( "," ) ) + states = states.split( "," ) + for id, state in zip( ids, states ): + data = self.app.model.LibraryDatasetDatasetAssociation.get( id ) + if data.state != state: + job_ldda = data + while job_ldda.copied_from_library_dataset_dataset_association: + job_ldda = job_ldda.copied_from_library_dataset_dataset_association + force_history_refresh = False + rval[id] = { + "state": data.state, + "html": unicode( trans.fill_template( "library/library_item_info.mako", ldda=data ), 'utf-8' ) + #"force_history_refresh": force_history_refresh + } + return rval + def upload_dataset( self, trans, controller, library_id, folder_id, replace_dataset=None, **kwd ): + # Set up the traditional tool state/params + tool_id = 'upload1' + tool = trans.app.toolbox.tools_by_id[ tool_id ] + state = tool.new_state( trans ) + errors = tool.update_state( trans, tool.inputs_by_page[0], state.inputs, kwd, changed_dependencies={} ) + tool_params = state.inputs + dataset_upload_inputs = [] + for input_name, input in tool.inputs.iteritems(): + if input.type == "upload_dataset": + dataset_upload_inputs.append( input ) + # Library-specific params + params = util.Params( kwd ) # is this filetoolparam safe? + library_bunch = upload_common.handle_library_params( trans, params, folder_id, replace_dataset ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + server_dir = util.restore_text( params.get( 'server_dir', '' ) ) + if replace_dataset not in [ None, 'None' ]: + replace_id = replace_dataset.id + else: + replace_id = None + upload_option = params.get( 'upload_option', 'upload_file' ) + err_redirect = False + if upload_option == 'upload_directory': + if server_dir in [ None, 'None', '' ]: + err_redirect = True + if controller == 'library_admin': + import_dir = trans.app.config.library_import_dir + import_dir_desc = 'library_import_dir' + full_dir = os.path.join( import_dir, server_dir ) + else: + import_dir = trans.app.config.user_library_import_dir + import_dir_desc = 'user_library_import_dir' + if server_dir == trans.user.email: + full_dir = os.path.join( import_dir, server_dir ) + else: + full_dir = os.path.join( import_dir, trans.user.email, server_dir ) + if import_dir: + msg = 'Select a directory' + else: + msg = '"%s" is not defined in the Galaxy configuration file' % import_dir_desc + # Proceed with (mostly) regular upload processing + precreated_datasets = upload_common.get_precreated_datasets( trans, tool_params, trans.app.model.LibraryDatasetDatasetAssociation, controller=controller ) + if upload_option == 'upload_file': + tool_params = upload_common.persist_uploads( tool_params ) + uploaded_datasets = upload_common.get_uploaded_datasets( trans, tool_params, precreated_datasets, dataset_upload_inputs, library_bunch=library_bunch ) + elif upload_option == 'upload_directory': + uploaded_datasets = self.get_server_dir_uploaded_datasets( trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ) + upload_common.cleanup_unused_precreated_datasets( precreated_datasets ) + if upload_option == 'upload_file' and not uploaded_datasets: + msg = 'Select a file, enter a URL or enter text' + err_redirect = True + if err_redirect: + trans.response.send_redirect( web.url_for( controller=controller, + action='upload_library_dataset', + library_id=library_id, + folder_id=folder_id, + replace_id=replace_id, + upload_option=upload_option, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + json_file_path = upload_common.create_paramfile( uploaded_datasets ) + data_list = [ ud.data for ud in uploaded_datasets ] + return upload_common.create_job( trans, tool_params, tool, json_file_path, data_list, folder=library_bunch.folder ) + def get_server_dir_uploaded_datasets( self, trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ): + files = [] + try: + for entry in os.listdir( full_dir ): + # Only import regular files + if os.path.isfile( os.path.join( full_dir, entry ) ): + files.append( entry ) + except Exception, e: + msg = "Unable to get file list for configured %s, error: %s" % ( import_dir_desc, str( e ) ) + err_redirect = True + return None + if not files: + msg = "The directory '%s' contains no valid files" % full_dir + err_redirect = True + return None + uploaded_datasets = [] + for file in files: + library_bunch.replace_dataset = None + uploaded_dataset = util.bunch.Bunch() + uploaded_dataset.path = os.path.join( full_dir, file ) + if not os.path.isfile( uploaded_dataset.path ): + continue + uploaded_dataset.type = 'server_dir' + uploaded_dataset.name = file + uploaded_dataset.ext = None + uploaded_dataset.file_type = params.file_type + uploaded_dataset.dbkey = params.dbkey + uploaded_dataset.space_to_tab = params.space_to_tab + uploaded_dataset.data = upload_common.new_upload( trans, uploaded_dataset, library_bunch ) + uploaded_datasets.append( uploaded_dataset ) + return uploaded_datasets + @web.expose + def info_template( self, trans, cntrller, library_id, response_action='library', obj_id=None, folder_id=None, ldda_id=None, **kwd ): + # Only adding a new templAte to a library or folder is currently allowed. Editing an existing template is + # a future enhancement. The response_action param is the name of the method to which this method will redirect + # if a new template is being added to a library or folder. + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + if obj_id: + library_item = trans.app.model.FormDefinition.get( int( obj_id ) ) + library_item_desc = 'information template' + response_id = obj_id + elif folder_id: + library_item = trans.app.model.LibraryFolder.get( int( folder_id ) ) + library_item_desc = 'folder' + response_id = folder_id + elif ldda_id: + library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( int( ldda_id ) ) + library_item_desc = 'library dataset' + response_id = ldda_id + else: + library_item = trans.app.model.Library.get( int( library_id ) ) + library_item_desc = 'library' + response_id = library_id + forms = get_all_forms( trans, + filter=dict( deleted=False ), + form_type=trans.app.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE ) + if not forms: + msg = "There are no forms on which to base the template, so create a form and " + msg += "try again to add the information template to the %s." % library_item_desc + trans.response.send_redirect( web.url_for( controller='forms', + action='new', + new=True, + msg=msg, + messagetype='done' ) ) + if params.get( 'add_info_template_button', False ): + form = trans.app.model.FormDefinition.get( int( kwd[ 'form_id' ] ) ) + #fields = list( copy.deepcopy( form.fields ) ) + form_values = trans.app.model.FormValues( form, [] ) + form_values.flush() + if folder_id: + assoc = trans.app.model.LibraryFolderInfoAssociation( library_item, form, form_values ) + elif ldda_id: + assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, form, form_values ) + else: + assoc = trans.app.model.LibraryInfoAssociation( library_item, form, form_values ) + assoc.flush() + msg = 'An information template based on the form "%s" has been added to this %s.' % ( form.name, library_item_desc ) + trans.response.send_redirect( web.url_for( controller=cntrller, + action=response_action, + obj_id=response_id, + msg=msg, + message_type='done' ) ) + # TODO: handle this better + if cntrller == 'library_admin': + tmplt = '/admin/library/select_info_template.mako' + else: + tmplt = '/ibrary/select_info_template.mako' + return trans.fill_template( tmplt, + library_item_name=library_item.name, + library_item_desc=library_item_desc, + library_id=library_id, + folder_id=folder_id, + ldda_id=ldda_id, + forms=forms, + msg=msg, + messagetype=messagetype ) + @web.expose + def edit_template_info( self, trans, cntrller, library_id, response_action, num_widgets, library_item_id=None, library_item_type=None, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + folder_id = None + if library_item_type == 'library': + library_item = trans.app.model.Library.get( library_item_id ) + elif library_item_type == 'library_dataset': + library_item = trans.app.model.LibraryDataset.get( library_item_id ) + elif library_item_type == 'folder': + library_item = trans.app.model.LibraryFolder.get( library_item_id ) + elif library_item_type == 'library_dataset_dataset_association': + library_item = trans.app.model.LibraryDatasetDatasetAssociation.get( library_item_id ) + # This response_action method requires a folder_id + folder_id = library_item.library_dataset.folder.id + else: + msg = "Invalid library item type ( %s ) specified, id ( %s )" % ( str( library_item_type ), str( library_item_id ) ) + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + # Save updated template field contents + field_contents = [] + for index in range( int( num_widgets ) ): + field_contents.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) ) + if field_contents: + # Since information templates are inherited, the template fields can be displayed on the information + # page for a folder or library dataset when it has no info_association object. If the user has added + # field contents on an inherited template via a parent's info_association, we'll need to create a new + # form_values and info_association for the current object. The value for the returned inherited variable + # is not applicable at this level. + info_association, inherited = library_item.get_info_association( restrict=True ) + if info_association: + template = info_association.template + info = info_association.info + form_values = trans.app.model.FormValues.get( info.id ) + # Update existing content only if it has changed + if form_values.content != field_contents: + form_values.content = field_contents + form_values.flush() + else: + # Inherit the next available info_association so we can get the template + info_association, inherited = library_item.get_info_association() + template = info_association.template + # Create a new FormValues object + form_values = trans.app.model.FormValues( template, field_contents ) + form_values.flush() + # Create a new info_association between the current library item and form_values + if library_item_type == 'folder': + info_association = trans.app.model.LibraryFolderInfoAssociation( library_item, template, form_values ) + info_association.flush() + elif library_item_type == 'library_dataset_dataset_association': + info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( library_item, template, form_values ) + info_association.flush() + msg = 'The information has been updated.' + return trans.response.send_redirect( web.url_for( controller=cntrller, + action=response_action, + library_id=library_id, + folder_id=folder_id, + obj_id=library_item.id, + msg=util.sanitize_text( msg ), + messagetype='done' ) ) + +# ---- Utility methods ------------------------------------------------------- + +def active_folders( trans, folder ): + # Much faster way of retrieving all active sub-folders within a given folder than the + # performance of the mapper. This query also eagerloads the permissions on each folder. + return trans.sa_session.query( trans.app.model.LibraryFolder ) \ + .filter_by( parent=folder, deleted=False ) \ + .options( eagerload_all( "actions" ) ) \ + .order_by( trans.app.model.LibraryFolder.table.c.name ) \ + .all() +def activatable_folders( trans, folder ): + return trans.sa_session.query( trans.app.model.LibraryFolder ) \ + .filter_by( parent=folder, purged=False ) \ + .options( eagerload_all( "actions" ) ) \ + .order_by( trans.app.model.LibraryFolder.table.c.name ) \ + .all() +def active_folders_and_lddas( trans, folder ): + folders = active_folders( trans, folder ) + # This query is much faster than the folder.active_library_datasets property + lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ + .filter_by( deleted=False ) \ + .join( "library_dataset" ) \ + .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \ + .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \ + .all() + return folders, lddas +def activatable_folders_and_lddas( trans, folder ): + folders = activatable_folders( trans, folder ) + # This query is much faster than the folder.activatable_library_datasets property + lddas = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ) \ + .join( "library_dataset" ) \ + .filter( trans.app.model.LibraryDataset.table.c.folder_id==folder.id ) \ + .join( "dataset" ) \ + .filter( trans.app.model.Dataset.table.c.deleted==False ) \ + .order_by( trans.app.model.LibraryDatasetDatasetAssociation.table.c.name ) \ + .all() + return folders, lddas diff -r 6a066b05c94f -r 22addc979108 lib/galaxy/web/controllers/library_dataset.py --- a/lib/galaxy/web/controllers/library_dataset.py Tue Sep 29 21:51:51 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -import os, os.path, shutil, urllib, StringIO, re, gzip, tempfile, shutil, zipfile -from galaxy.web.base.controller import * -from galaxy import util, jobs -from galaxy.datatypes import sniff -from galaxy.security import RBACAgent -from galaxy.util.json import to_json_string -from galaxy.tools.actions import upload_common - -log = logging.getLogger( __name__ ) - -class UploadLibraryDataset( BaseController ): - @web.json - def library_item_updates( self, trans, ids=None, states=None ): - # Avoid caching - trans.response.headers['Pragma'] = 'no-cache' - trans.response.headers['Expires'] = '0' - # Create new HTML for any that have changed - rval = {} - if ids is not None and states is not None: - ids = map( int, ids.split( "," ) ) - states = states.split( "," ) - for id, state in zip( ids, states ): - data = self.app.model.LibraryDatasetDatasetAssociation.get( id ) - if data.state != state: - job_ldda = data - while job_ldda.copied_from_library_dataset_dataset_association: - job_ldda = job_ldda.copied_from_library_dataset_dataset_association - force_history_refresh = False - rval[id] = { - "state": data.state, - "html": unicode( trans.fill_template( "library/library_item_info.mako", ldda=data ), 'utf-8' ) - #"force_history_refresh": force_history_refresh - } - return rval - def upload_dataset( self, trans, controller, library_id, folder_id, replace_dataset=None, **kwd ): - # Set up the traditional tool state/params - tool_id = 'upload1' - tool = trans.app.toolbox.tools_by_id[ tool_id ] - state = tool.new_state( trans ) - errors = tool.update_state( trans, tool.inputs_by_page[0], state.inputs, kwd, changed_dependencies={} ) - tool_params = state.inputs - dataset_upload_inputs = [] - for input_name, input in tool.inputs.iteritems(): - if input.type == "upload_dataset": - dataset_upload_inputs.append( input ) - # Library-specific params - params = util.Params( kwd ) # is this filetoolparam safe? - library_bunch = upload_common.handle_library_params( trans, params, folder_id, replace_dataset ) - msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) - server_dir = util.restore_text( params.get( 'server_dir', '' ) ) - if replace_dataset not in [ None, 'None' ]: - replace_id = replace_dataset.id - else: - replace_id = None - upload_option = params.get( 'upload_option', 'upload_file' ) - err_redirect = False - if upload_option == 'upload_directory': - if server_dir in [ None, 'None', '' ]: - err_redirect = True - if controller == 'library_admin': - import_dir = trans.app.config.library_import_dir - import_dir_desc = 'library_import_dir' - full_dir = os.path.join( import_dir, server_dir ) - else: - import_dir = trans.app.config.user_library_import_dir - import_dir_desc = 'user_library_import_dir' - if server_dir == trans.user.email: - full_dir = os.path.join( import_dir, server_dir ) - else: - full_dir = os.path.join( import_dir, trans.user.email, server_dir ) - if import_dir: - msg = 'Select a directory' - else: - msg = '"%s" is not defined in the Galaxy configuration file' % import_dir_desc - # Proceed with (mostly) regular upload processing - precreated_datasets = upload_common.get_precreated_datasets( trans, tool_params, trans.app.model.LibraryDatasetDatasetAssociation, controller=controller ) - if upload_option == 'upload_file': - tool_params = upload_common.persist_uploads( tool_params ) - uploaded_datasets = upload_common.get_uploaded_datasets( trans, tool_params, precreated_datasets, dataset_upload_inputs, library_bunch=library_bunch ) - elif upload_option == 'upload_directory': - uploaded_datasets = self.get_server_dir_uploaded_datasets( trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ) - upload_common.cleanup_unused_precreated_datasets( precreated_datasets ) - if upload_option == 'upload_file' and not uploaded_datasets: - msg = 'Select a file, enter a URL or enter text' - err_redirect = True - if err_redirect: - trans.response.send_redirect( web.url_for( controller=controller, - action='library_dataset_dataset_association', - library_id=library_id, - folder_id=folder_id, - replace_id=replace_id, - upload_option=upload_option, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - json_file_path = upload_common.create_paramfile( uploaded_datasets ) - data_list = [ ud.data for ud in uploaded_datasets ] - return upload_common.create_job( trans, tool_params, tool, json_file_path, data_list, folder=library_bunch.folder ) - def get_server_dir_uploaded_datasets( self, trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ): - files = [] - try: - for entry in os.listdir( full_dir ): - # Only import regular files - if os.path.isfile( os.path.join( full_dir, entry ) ): - files.append( entry ) - except Exception, e: - msg = "Unable to get file list for configured %s, error: %s" % ( import_dir_desc, str( e ) ) - err_redirect = True