From 6d573a987046cb65e4821cf9ee4abcbd137ec97e Mon Sep 17 00:00:00 2001 From: Greg Von Kuster Date: Thu, 1 Oct 2009 15:07:22 -0400 Subject: [PATCH] Only allow 'uload files' option when replacing a dataset with a new version, more code merging, a few bugs fixes and additional functional tests for libraries. --- lib/galaxy/web/controllers/library.py | 157 ++++++++---------- lib/galaxy/web/controllers/library_admin.py | 48 ++---- lib/galaxy/web/controllers/library_common.py | 29 ++++ templates/admin/library/browse_library.mako | 2 +- templates/admin/library/ldda_info.mako | 2 +- templates/admin/library/upload.mako | 25 +-- templates/library/browse_library.mako | 2 +- templates/library/ldda_info.mako | 2 +- templates/library/upload.mako | 19 ++- test/base/twilltestcase.py | 16 +- .../functional/test_security_and_libraries.py | 46 ++++- 11 files changed, 183 insertions(+), 165 deletions(-) diff --git a/lib/galaxy/web/controllers/library.py b/lib/galaxy/web/controllers/library.py index 60b30d95f2d..e00eda0090d 100644 --- a/lib/galaxy/web/controllers/library.py +++ b/lib/galaxy/web/controllers/library.py @@ -568,64 +568,31 @@ class Library( BaseController ): 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 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 ): - # Ensure that the permissions across all library items are identical, otherwise we can't update them together. - check_list = [] + 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: - 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' ) ) + # 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' @@ -634,6 +601,39 @@ class Library( BaseController ): 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 ) @@ -652,8 +652,11 @@ class Library( BaseController ): replace_dataset = trans.app.model.LibraryDataset.get( params.get( 'replace_id', None ) ) if not last_used_build: last_used_build = replace_dataset.library_dataset_dataset_association.dbkey + # Don't allow multiple datasets to be uploaded when replacing a dataset with a new version + upload_option = 'upload_file' else: replace_dataset = None + upload_option = params.get( 'upload_option', 'upload_file' ) user, roles = trans.get_user_and_roles() 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 ) ): @@ -666,15 +669,14 @@ class Library( BaseController ): else: template_id = 'None' widgets = [] - upload_option = params.get( 'upload_option', 'upload_file' ) created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, - controller='library', - library_id=library_id, - folder_id=folder_id, - template_id=template_id, - widgets=widgets, - replace_dataset=replace_dataset, - **kwd ) + controller='library', + library_id=library_id, + folder_id=folder_id, + template_id=template_id, + widgets=widgets, + replace_dataset=replace_dataset, + **kwd ) if created_outputs: ldda_id_list = [ str( v.id ) for v in created_outputs.values() ] total_added = len( created_outputs.values() ) @@ -860,35 +862,6 @@ class Library( BaseController ): msg=msg, messagetype=messagetype ) @web.expose - 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. diff --git a/lib/galaxy/web/controllers/library_admin.py b/lib/galaxy/web/controllers/library_admin.py index 86f651172a3..83599d8f1b7 100644 --- a/lib/galaxy/web/controllers/library_admin.py +++ b/lib/galaxy/web/controllers/library_admin.py @@ -673,8 +673,11 @@ class LibraryAdmin( BaseController ): replace_dataset = trans.app.model.LibraryDataset.get( int( replace_id ) ) if not last_used_build: last_used_build = replace_dataset.library_dataset_dataset_association.dbkey + # Don't allow multiple datasets to be uploaded when replacing a dataset with a new version + upload_option = 'upload_file' else: replace_dataset = None + upload_option = params.get( 'upload_option', 'upload_file' ) 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 ) @@ -684,15 +687,14 @@ class LibraryAdmin( BaseController ): else: template_id = 'None' widgets = [] - upload_option = params.get( 'upload_option', 'upload_file' ) created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, - controller='library_admin', - library_id=library_id, - folder_id=folder_id, - template_id=template_id, - widgets=widgets, - replace_dataset=replace_dataset, - **kwd ) + controller='library_admin', + library_id=library_id, + folder_id=folder_id, + template_id=template_id, + widgets=widgets, + replace_dataset=replace_dataset, + **kwd ) if created_outputs: total_added = len( created_outputs.values() ) if replace_dataset: @@ -851,36 +853,6 @@ class LibraryAdmin( BaseController ): messagetype=messagetype ) @web.expose @web.require_admin - 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', - obj_id=library_id, - msg=util.sanitize_text( 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_admin', - action='browse_library', - obj_id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - @web.expose - @web.require_admin def datasets( self, trans, library_id, **kwd ): # This method is used by the select list labeled "Perform action on selected datasets" # on the admin library browser. diff --git a/lib/galaxy/web/controllers/library_common.py b/lib/galaxy/web/controllers/library_common.py index edcab8e0ab3..bb64efdffcd 100644 --- a/lib/galaxy/web/controllers/library_common.py +++ b/lib/galaxy/web/controllers/library_common.py @@ -181,6 +181,35 @@ class LibraryCommon( BaseController ): return None, err_redirect, msg return uploaded_datasets, None, None @web.expose + def download_dataset_from_folder( self, trans, cntrller, 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=cntrller, + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( 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=cntrller, + action='browse_library', + obj_id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + @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 diff --git a/templates/admin/library/browse_library.mako b/templates/admin/library/browse_library.mako index 4d7ce6a1377..7e051bb0ee4 100644 --- a/templates/admin/library/browse_library.mako +++ b/templates/admin/library/browse_library.mako @@ -137,7 +137,7 @@ Edit this dataset's permissions Upload a new version of this dataset %if ldda.has_data: - Download this dataset + Download this dataset %endif Delete this dataset diff --git a/templates/admin/library/ldda_info.mako b/templates/admin/library/ldda_info.mako index d1a9402404d..a1ea050c15c 100644 --- a/templates/admin/library/ldda_info.mako +++ b/templates/admin/library/ldda_info.mako @@ -47,7 +47,7 @@ Upload a new version of this dataset %endif %if ldda.has_data: - Download this dataset + Download this dataset %endif %if not library.deleted and not ldda.library_dataset.folder.deleted and not ldda.library_dataset.deleted: Delete this dataset diff --git a/templates/admin/library/upload.mako b/templates/admin/library/upload.mako index 463ac399de7..cea87914686 100644 --- a/templates/admin/library/upload.mako +++ b/templates/admin/library/upload.mako @@ -12,17 +12,20 @@ %> Create new data library datasets - -
- Upload files - %if trans.app.config.library_import_dir and os.path.exists( trans.app.config.library_import_dir ): - Upload directory of files - %endif - %if trans.app.config.allow_library_path_paste: - Upload files from filesystem paths - %endif - Import datasets from your current history -
+%if replace_dataset in [ None, 'None' ]: + ## Don't allow multiple datasets to be uploaded when replacing a dataset with a new version + +
+ Upload files + %if trans.app.config.library_import_dir and os.path.exists( trans.app.config.library_import_dir ): + Upload directory of files + %endif + %if trans.app.config.allow_library_path_paste: + Upload files from filesystem paths + %endif + Import datasets from your current history +
+%endif