details: http://www.bx.psu.edu/hg/galaxy/rev/8916a67cc639 changeset: 3257:8916a67cc639 user: Greg Von Kuster greg@bx.psu.edu date: Fri Jan 22 11:24:28 2010 -0500 description: If a library is not public, ensure that the roles displayed on the upload form or any permission form for a contained folder or dataset are derived from the set of users that have access to the library.  Add error checks to the upload tool to display appropriate error messages if ill-legitimate roles were selected ( shouldn't happen since they are filtered out ) or if roles are selected such that the dataset would be in-accessible to everyone.
diffstat:
lib/galaxy/model/__init__.py | 53 ++- lib/galaxy/security/__init__.py | 99 +++- lib/galaxy/tools/actions/__init__.py | 8 +- lib/galaxy/tools/actions/upload_common.py | 10 +- lib/galaxy/tools/parameters/basic.py | 6 +- lib/galaxy/web/controllers/dataset.py | 8 +- lib/galaxy/web/controllers/library.py | 4 +- lib/galaxy/web/controllers/library_common.py | 364 ++++++------- lib/galaxy/web/controllers/requests.py | 6 +- lib/galaxy/web/controllers/root.py | 23 +- lib/galaxy/web/controllers/tool_runner.py | 12 + templates/admin/center.mako | 67 +- templates/base_panels.mako | 23 +- templates/dataset/edit_attributes.mako | 5 +- templates/library/common/browse_library.mako | 27 +- templates/library/common/common.mako | 4 +- templates/library/common/folder_info.mako | 7 +- templates/library/common/folder_permissions.mako | 4 +- templates/library/common/ldda_edit_info.mako | 7 +- templates/library/common/ldda_info.mako | 8 +- templates/library/common/ldda_permissions.mako | 5 - templates/library/common/library_dataset_info.mako | 7 +- templates/library/common/library_dataset_permissions.mako | 12 +- templates/library/common/library_info.mako | 7 +- templates/library/common/library_permissions.mako | 12 +- templates/mobile/history/detail.mako | 4 +- templates/mobile/manage_library.mako | 12 +- templates/root/history_common.mako | 6 +- test/base/twilltestcase.py | 3 +- test/functional/test_security_and_libraries.py | 185 +++++- test/functional/test_toolbox.py | 1 + 31 files changed, 624 insertions(+), 375 deletions(-)
diffs (2062 lines):
diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/model/__init__.py Fri Jan 22 11:24:28 2010 -0500 @@ -5,7 +5,7 @@ the relationship cardinalities are obvious (e.g. prefer Dataset to Data) """
-import os.path, os, errno, sys, codecs +import os.path, os, errno, sys, codecs, operator import galaxy.datatypes from galaxy.util.bunch import Bunch from galaxy import util @@ -435,6 +435,12 @@ os.remove(self.data.file_name) except OSError, e: log.critical('%s delete error %s' % (self.__class__.__name__, e)) + def get_access_roles( self, trans ): + roles = [] + for dp in self.actions: + if dp.action == trans.app.security_agent.permitted_actions.DATASET_ACCESS.action: + roles.append( dp.role ) + return roles
class DatasetInstance( object ): """A base class for all 'dataset instances', HDAs, LDAs, etc""" @@ -747,6 +753,49 @@ return template.get_widgets( trans.user, contents=info.content ) return template.get_widgets( trans.user ) return [] + def get_access_roles( self, trans ): + roles = [] + for lp in self.actions: + if lp.action == trans.app.security_agent.permitted_actions.LIBRARY_ACCESS.action: + roles.append( lp.role ) + return roles + def get_legitimate_roles( self, trans ): + if trans.app.security_agent.library_is_public( self ): + return trans.sa_session.query( trans.app.model.Role ) \ + .filter( trans.app.model.Role.table.c.deleted==False ) \ + .order_by( trans.app.model.Role.table.c.name ) + def sort_by_attr( seq, attr ): + """ + Sort the sequence of objects by object's attribute + Arguments: + seq - the list or any sequence (including immutable one) of objects to sort. + attr - the name of attribute to sort by + """ + # Use the "Schwartzian transform" + # Create the auxiliary list of tuples where every i-th tuple has form + # (seq[i].attr, i, seq[i]) and sort it. The second item of tuple is needed not + # only to provide stable sorting, but mainly to eliminate comparison of objects + # (which can be expensive or prohibited) in case of equal attribute values. + intermed = map( None, map( getattr, seq, ( attr, ) * len( seq ) ), xrange( len( seq ) ), seq ) + intermed.sort() + return map( operator.getitem, intermed, ( -1, ) * len( intermed ) ) + roles = set() + # If a library has roles associated with the LIBRARY_ACCESS permission, we need to start with them. + access_roles = self.get_access_roles( trans ) + for role in access_roles: + roles.add( role ) + # Each role potentially has users. We need to find all roles that each of those users have. + for ura in role.users: + roles.add( ura.role ) + # Each role also potentially has groups which, in turn, have members ( users ). We need to + # find all roles that each group's members have. + for gra in role.groups: + group = gra.group + for uga in group.users: + user = uga.user + for ura in user.roles: + roles.add( ura.role ) + return sort_by_attr( [ role for role in roles ], 'name' ) def get_display_name( self ): # Library name can be either a string or a unicode object. If string, # convert to unicode object assuming 'utf-8' format. @@ -937,6 +986,8 @@ return ldda def clear_associated_files( self, metadata_safe = False, purge = False ): return + def get_access_roles( self, trans ): + return self.dataset.get_access_roles( trans ) def get_info_association( self, restrict=False, inherited=False ): # If restrict is True, we will return this ldda's info_association whether it # exists or not. If restrict is False, we'll return the next available info_association diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/security/__init__.py --- a/lib/galaxy/security/__init__.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/security/__init__.py Fri Jan 22 11:24:28 2010 -0500 @@ -5,6 +5,7 @@ import logging, socket from datetime import datetime, timedelta from galaxy.util.bunch import Bunch +from galaxy.util import listify from galaxy.model.orm import *
log = logging.getLogger(__name__) @@ -17,6 +18,8 @@
class RBACAgent: """Class that handles galaxy security""" + IN_ACCESSIBLE = 'access_error' + ILL_LEGITIMATE = 'legitimate_error' permitted_actions = Bunch( DATASET_MANAGE_PERMISSIONS = Action( "manage permissions", "Role members can manage the roles associated with this dataset", "grant" ), DATASET_ACCESS = Action( "access", "Role members can import this dataset into their history for analysis", "restrict" ), @@ -74,6 +77,10 @@ raise "Unimplemented Method" def make_library_public( self, library ): raise "Unimplemented Method" + def get_library_dataset_permissions( self, library_dataset ): + raise "Unimplemented Method" + def check_library_dataset_access( self, trans, library_id, **kwd ): + raise "Unimplemented Method" def get_component_associations( self, **kwd ): raise "Unimplemented Method" def components_are_associated( self, **kwd ): @@ -283,8 +290,6 @@ permissions looks like: { Action : [ Role, Role ] } """ # Delete all of the current permissions on the dataset - # TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset, - # or the dataset is inaccessible. See admin/library_dataset_dataset_association() for dp in dataset.actions: self.sa_session.delete( dp ) # Add the new permissions on the dataset @@ -299,8 +304,6 @@ Set a specific permission on a dataset, leaving all other current permissions on the dataset alone permissions looks like: { Action : [ Role, Role ] } """ - # TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset, - # or the dataset is inaccessible. See admin/library_dataset_dataset_association() for action, roles in permission.items(): if isinstance( action, Action ): action = action.action @@ -405,18 +408,92 @@ else: permissions[ action ] = [ library_dataset_permission.role ] return permissions + def check_library_dataset_access( self, trans, library_id, **kwd ): + # library_id must be decoded before being sent + msg = '' + permissions = {} + # accessible will be True only if at least 1 user has every role in DATASET_ACCESS_in + accessible = False + # legitimate will be True only if all roles in DATASET_ACCESS_in are in the set + # of roles returned from library.get_legitimate_roles() + legitimate = False + error = None + for k, v in get_permitted_actions( filter='DATASET' ).items(): + in_roles = [ self.sa_session.query( self.model.Role ).get( x ) for x in listify( kwd.get( k + '_in', [] ) ) ] + if v == self.permitted_actions.DATASET_ACCESS and in_roles: + library = self.model.Library.get( library_id ) + if not self.library_is_public( library ): + # Ensure that roles being associated with DATASET_ACCESS are a subset of the legitimate roles + # derived from the roles associated with the LIBRARY_ACCESS permission on the library if it's + # not public. This will keep ill-legitimate roles from being associated with the DATASET_ACCESS + # permission on the dataset (i.e., if Role1 is associated with LIBRARY_ACCESS, then only those users + # that have Role1 should be associated with DATASET_ACCESS. + legitimate_roles = library.get_legitimate_roles( trans ) + ill_legitimate_roles = [] + for role in in_roles: + if role not in legitimate_roles: + ill_legitimate_roles.append( role ) + if ill_legitimate_roles: + error = self.ILL_LEGITIMATE + msg += "The following roles are not associated with users that have the 'access library' permission on this " + msg += "library, so they cannot be associated with the 'access' permission on the datasets: " + for role in ill_legitimate_roles: + msg += "%s, " % role.name + msg = msg.rstrip( ", " ) + new_in_roles = [] + for role in in_roles: + if role in legitimate_roles: + new_in_roles.append( role ) + in_roles = new_in_roles + else: + legitimate = True + if len( in_roles ) == 1: + accessible = True + else: + # At least 1 user must have every role associated with the access + # permission on this dataset, or the dataset is not accessible. + 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 ) + for gra in role.groups: + group = gra.group + for uga in group.users: + users_set.add( uga.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 + if not accessible: + error = self.IN_ACCESSIBLE + # Don't set the permissions for DATASET_ACCESS if inaccessible, but set all other permissions + permissions[ self.get_action( v.action ) ] = [] + msg += "At least 1 user must have every role associated with accessing datasets. The roles you " + msg += "attempted to associate for access would make the datasets in-accessible by everyone, " + msg += "so access permissions were left in their original state (or not set). All other " + msg += "permissions were updated for the datasets." + else: + permissions[ self.get_action( v.action ) ] = in_roles + else: + permissions[ self.get_action( v.action ) ] = in_roles + return permissions, in_roles, error, msg def copy_library_permissions( self, source_library_item, target_library_item, user=None ): # Copy all relevant permissions from source. permissions = {} for role_assoc in source_library_item.actions: - if role_assoc.action == self.permitted_actions.LIBRARY_ACCESS and \ - not( isinstance( source_library_item, galaxy.model.Libary ) and isinstance( target_library_item, galaxy.model.Libary ) ): + if role_assoc.action != self.permitted_actions.LIBRARY_ACCESS.action: # LIBRARY_ACCESS is a special permission that is set only at the library level. - continue - if role_assoc.action in permissions: - permissions[role_assoc.action].append( role_assoc.role ) - else: - permissions[role_assoc.action] = [ role_assoc.role ] + if role_assoc.action in permissions: + permissions[role_assoc.action].append( role_assoc.role ) + else: + permissions[role_assoc.action] = [ role_assoc.role ] self.set_all_library_permissions( target_library_item, permissions ) if user: item_class = None diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/tools/actions/__init__.py --- a/lib/galaxy/tools/actions/__init__.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/tools/actions/__init__.py Fri Jan 22 11:24:28 2010 -0500 @@ -51,8 +51,8 @@ trans.sa_session.add( assoc ) trans.sa_session.flush() data = new_data - roles = trans.get_current_user_roles() - if data and not trans.app.security_agent.can_access_dataset( roles, data.dataset ): + current_user_roles = trans.get_current_user_roles() + if data and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): raise "User does not have permission to use a dataset (%s) provided for input." % data.id return data if isinstance( input, DataToolParameter ): @@ -269,10 +269,10 @@ # parameters to the command as a special case. for name, value in tool.params_to_strings( incoming, trans.app ).iteritems(): job.add_parameter( name, value ) - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() for name, dataset in inp_data.iteritems(): if dataset: - if not trans.app.security_agent.can_access_dataset( roles, dataset.dataset ): + if not trans.app.security_agent.can_access_dataset( current_user_roles, dataset.dataset ): raise "User does not have permission to use a dataset (%s) provided for input." % data.id job.add_input_dataset( name, dataset ) else: diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/tools/actions/upload_common.py --- a/lib/galaxy/tools/actions/upload_common.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/tools/actions/upload_common.py Fri Jan 22 11:24:28 2010 -0500 @@ -59,7 +59,7 @@ role = trans.sa_session.query( trans.app.model.Role ).get( role_id ) library_bunch.roles.append( role ) return library_bunch -def get_precreated_datasets( trans, params, data_obj, controller='root' ): +def get_precreated_datasets( trans, params, data_obj, controller='root' ): """ Get any precreated datasets (when using asynchronous uploads). """ @@ -67,7 +67,7 @@ async_datasets = [] if params.get( 'async_datasets', None ) not in ["None", "", None]: async_datasets = params['async_datasets'].split(',') - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() for id in async_datasets: try: data = trans.sa_session.query( data_obj ).get( int( id ) ) @@ -82,7 +82,7 @@ else: rval.append( data ) elif data_obj is trans.app.model.LibraryDatasetDatasetAssociation: - if controller == 'library' and not trans.app.security_agent.can_add_library_item( roles, data.library_dataset.folder ): + if controller == 'library' and not trans.app.security_agent.can_add_library_item( current_user_roles, data.library_dataset.folder ): log.error( 'Got a precreated dataset (%s) but this user (%s) is not allowed to write to it' % ( data.id, trans.user.id ) ) else: rval.append( data ) @@ -122,8 +122,8 @@ trans.sa_session.flush() return hda def new_library_upload( trans, uploaded_dataset, library_bunch, state=None ): - roles = trans.get_current_user_roles() - if not ( trans.app.security_agent.can_add_library_item( roles, library_bunch.folder ) \ + current_user_roles = trans.get_current_user_roles() + if not ( trans.app.security_agent.can_add_library_item( current_user_roles, library_bunch.folder ) \ or trans.user.email in trans.app.config.get( "admin_users", "" ).split( "," ) ): # This doesn't have to be pretty - the only time this should happen is if someone's being malicious. raise Exception( "User is not authorized to add datasets to this library." ) diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/tools/parameters/basic.py --- a/lib/galaxy/tools/parameters/basic.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/tools/parameters/basic.py Fri Jan 22 11:24:28 2010 -0500 @@ -1177,7 +1177,7 @@ field = form_builder.SelectField( self.name, self.multiple, None, self.refresh_on_change, refresh_on_change_values = self.refresh_on_change_values ) # CRUCIAL: the dataset_collector function needs to be local to DataToolParameter.get_html_field() def dataset_collector( hdas, parent_hid ): - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() for i, hda in enumerate( hdas ): if len( hda.name ) > 30: hda_name = '%s..%s' % ( hda.name[:17], hda.name[-11:] ) @@ -1189,7 +1189,7 @@ hid = str( hda.hid ) if not hda.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED] and \ hda.visible and \ - trans.app.security_agent.can_access_dataset( roles, hda.dataset ): + trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset ): # If we are sending data to an external application, then we need to make sure there are no roles # associated with the dataset that restrict it's access from "public". if self.tool and self.tool.tool_type == 'data_destination' and not trans.app.security_agent.dataset_is_public( hda.dataset ): @@ -1204,7 +1204,7 @@ if target_ext: if converted_dataset: hda = converted_dataset - if not trans.app.security_agent.can_access_dataset( roles, hda.dataset ): + if not trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset ): continue selected = ( value and ( hda in value ) ) field.add_option( "%s: (as %s) %s" % ( hid, target_ext, hda_name ), hda.id, selected ) diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/dataset.py --- a/lib/galaxy/web/controllers/dataset.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/dataset.py Fri Jan 22 11:24:28 2010 -0500 @@ -192,8 +192,8 @@ data = data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id ) if not data: raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) ) - roles = trans.get_current_user_roles() - if trans.app.security_agent.can_access_dataset( roles, data.dataset ): + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): if data.state == trans.model.Dataset.states.UPLOAD: return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." )
@@ -298,10 +298,10 @@ if 'display_url' not in kwd or 'redirect_url' not in kwd: return trans.show_error_message( 'Invalid parameters specified for "display at" link, please contact a Galaxy administrator' ) redirect_url = kwd['redirect_url'] % urllib.quote_plus( kwd['display_url'] ) - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() if trans.app.security_agent.dataset_is_public( data.dataset ): return trans.response.send_redirect( redirect_url ) # anon access already permitted by rbac - if trans.app.security_agent.can_access_dataset( roles, data.dataset ): + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): trans.app.host_security_agent.set_dataset_permissions( data, trans.user, site ) return trans.response.send_redirect( redirect_url ) else: diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/library.py --- a/lib/galaxy/web/controllers/library.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/library.py Fri Jan 22 11:24:28 2010 -0500 @@ -21,13 +21,13 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() all_libraries = trans.sa_session.query( trans.app.model.Library ) \ .filter( trans.app.model.Library.table.c.deleted==False ) \ .order_by( trans.app.model.Library.name ) authorized_libraries = [] for library in all_libraries: - if trans.app.security_agent.library_is_public( library ) or trans.app.security_agent.can_access_library( roles, library ): + if trans.app.security_agent.can_access_library( current_user_roles, library ): authorized_libraries.append( library ) return trans.fill_template( '/library/browse_libraries.mako', libraries=authorized_libraries, diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/library_common.py --- a/lib/galaxy/web/controllers/library_common.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/library_common.py Fri Jan 22 11:24:28 2010 -0500 @@ -101,6 +101,7 @@ show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) created_ldda_ids = params.get( 'created_ldda_ids', '' ) hidden_folder_ids = util.listify( params.get( 'hidden_folder_ids', '' ) ) + current_user_roles = trans.get_current_user_roles() if created_ldda_ids and not msg: msg = "%d datasets are uploading in the background to the library '%s' (each is selected). " % \ ( len( created_ldda_ids.split( ',' ) ), library.name ) @@ -115,6 +116,7 @@ default_action=params.get( 'default_action', None ), show_deleted=show_deleted, comptypes=comptypes, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) @web.expose @@ -126,18 +128,14 @@ library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) # See if we have any associated templates widgets = library.get_template_widgets( trans ) + current_user_roles = trans.get_current_user_roles() if params.get( 'rename_library_button', False ): old_name = library.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/common/library_info.mako', - cntrller=cntrller, - library=library, - widgets=widgets, - msg=msg, - messagetype='error' ) + messagetype='error' else: library.name = new_name library.description = new_description @@ -157,6 +155,7 @@ cntrller=cntrller, library=library, widgets=widgets, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) @web.expose @@ -166,6 +165,7 @@ messagetype = params.get( 'messagetype', 'done' ) library_id = params.get( 'id', None ) library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + current_user_roles = trans.get_current_user_roles() if params.get( 'update_roles_button', False ): # The user clicked the Save button on the 'Associate With Roles' form permissions = {} @@ -183,9 +183,12 @@ id=trans.security.encode_id( library.id ), msg=util.sanitize_text( msg ), messagetype='done' ) ) + roles = library.get_legitimate_roles( trans ) return trans.fill_template( '/library/common/library_permissions.mako', cntrller=cntrller, library=library, + current_user_roles=current_user_roles, + roles=roles, msg=msg, messagetype=messagetype ) @web.expose @@ -233,52 +236,34 @@ msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) ) - if cntrller != 'library_admin': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() # See if we have any associated templates widgets = folder.get_template_widgets( trans ) if params.get( 'rename_folder_button', False ): - if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, folder ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_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/common/folder_info.mako", - cntrller=cntrller, - folder=folder, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype='error' ) + messagetype='error' else: folder.name = new_name folder.description = new_description trans.sa_session.add( folder ) trans.sa_session.flush() msg = "Folder '%s' has been renamed to '%s'" % ( old_name, new_name ) - return trans.response.send_redirect( web.url_for( controller='library_common', - action='folder_info', - cntrller=cntrller, - id=id, - library_id=library_id, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) + messagetype='done' else: msg = "You are not authorized to edit this folder" - return trans.fill_template( "/library/common/folder_info.mako", - cntrller=cntrller, - folder=folder, - library_id=library_id, - widgets=widgets, - msg=msg, - messagetype='error' ) + messagetype='error' return trans.fill_template( '/library/common/folder_info.mako', cntrller=cntrller, folder=folder, library_id=library_id, widgets=widgets, - msg=msg, + current_user_roles=current_user_roles, + msg=util.sanitize_text( msg ), messagetype=messagetype ) @web.expose def folder_permissions( self, trans, cntrller, id, library_id, **kwd ): @@ -294,36 +279,40 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() if params.get( 'update_roles_button', False ): # The user clicked the Save button on the 'Associate With Roles' form - if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( roles, folder ): + if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ): permissions = {} for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.sa_session.query( 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 + if k != 'LIBRARY_ACCESS': + # LIBRARY_ACCESS is a special permission set only at the library level + # and it is not inherited. + in_roles = [ trans.sa_session.query( 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 ) trans.sa_session.refresh( folder ) msg = 'Permissions updated for folder %s' % folder.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='folder_permissions', - id=trans.security.encode_id( folder.id ), - library_id=library_id, - msg=util.sanitize_text( msg ), - messagetype='done' ) ) + messagetype='done' else: msg = "You are not authorized to manage permissions on this folder" - return trans.response.send_redirect( web.url_for( controller='library_common', - action='folder_permissions', - id=trans.security.encode_id( folder.id ), - library_id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) + messagetype = "error" + return trans.response.send_redirect( web.url_for( controller='library_common', + action='folder_permissions', + id=trans.security.encode_id( folder.id ), + library_id=library_id, + msg=util.sanitize_text( msg ), + messagetype=messagetype ) ) + # If the library is public all roles are legitimate, but if the library is restricted, only those + # roles associated with the LIBRARY_ACCESS permission are legitimate. + library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + roles = library.get_legitimate_roles( trans ) return trans.fill_template( '/library/common/folder_permissions.mako', cntrller=cntrller, folder=folder, library_id=library_id, + current_user_roles=current_user_roles, + roles=roles, msg=msg, messagetype=messagetype ) @web.expose @@ -343,15 +332,14 @@ dbkey = params.get( 'dbkey', '?' ) if isinstance( dbkey, list ): dbkey = dbkey[0] - if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_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 cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_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.sa_session.flush() @@ -369,11 +357,12 @@ library_id=library_id, file_formats=file_formats, widgets=widgets, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) elif params.get( 'save', False ): # The user clicked the Save button on the 'Edit Attributes' form - if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ): old_name = ldda.name new_name = util.restore_text( params.get( 'name', '' ) ) new_info = util.restore_text( params.get( 'info', '' ) ) @@ -409,11 +398,12 @@ library_id=library_id, file_formats=file_formats, widgets=widgets, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) elif params.get( 'detect', False ): # The user clicked the Auto-detect button on the 'Edit Attributes' form - if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_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' ]: @@ -433,9 +423,10 @@ library_id=library_id, file_formats=file_formats, widgets=widgets, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) - if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, 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 @@ -449,6 +440,7 @@ library_id=library_id, file_formats=file_formats, widgets=widgets, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) @web.expose @@ -469,6 +461,7 @@ library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) # See if we have any associated templates widgets = ldda.get_template_widgets( trans ) + current_user_roles = trans.get_current_user_roles() return trans.fill_template( '/library/common/ldda_info.mako', cntrller=cntrller, ldda=ldda, @@ -483,7 +476,6 @@ msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) ids = util.listify( id ) - # Display permission form, permissions will be updated for all lddas simultaneously. lddas = [] for id in [ trans.security.decode_id( id ) for id in ids ]: ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( id ) @@ -496,63 +488,44 @@ msg=util.sanitize_text( msg ), messagetype='error' ) ) lddas.append( ldda ) + # If the library is public all roles are legitimate, but if the library is restricted, only those + # roles associated with the LIBRARY_ACCESS permission are legitimate. + library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + roles = library.get_legitimate_roles( trans ) if params.get( 'update_roles_button', False ): - if cntrller=='library_admin' or ( trans.app.security_agent.can_manage_library_item( roles, ldda ) and \ - trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ) ): + current_user_roles = trans.get_current_user_roles() + if cntrller=='library_admin' or ( trans.app.security_agent.can_manage_library_item( current_user_roles, ldda ) and \ + trans.app.security_agent.can_manage_dataset( current_user_roles, ldda.dataset ) ): + permissions, in_roles, error, msg = \ + trans.app.security_agent.check_library_dataset_access( trans, trans.app.security.decode_id( library_id ), **kwd ) + for ldda in lddas: + # Set the DATASET permissions on the Dataset. + if error == trans.app.security_agent.IN_ACCESSIBLE: + # If the check_library_dataset_access() returned a "in_accessible" error, then we keep the original role + # associations for the DATASET_ACCESS permission on each ldda. + a = trans.app.security_agent.get_action( trans.app.security_agent.permitted_actions.DATASET_ACCESS.action ) + permissions[ a ] = ldda.get_access_roles( trans ) + trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) + trans.sa_session.refresh( ldda.dataset ) + # Set the LIBRARY permissions on the LibraryDataset + # NOTE: the LibraryDataset and LibraryDatasetDatasetAssociation will be set with the same permissions permissions = {} - accessible = False - for k, v in trans.app.model.Dataset.permitted_actions.items(): - in_roles = [ trans.sa_session.query( 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: + for k, v in trans.app.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + # LIBRARY_ACCESS is a special permission set only at the library level and it is not inherited. + in_roles = [ trans.sa_session.query( 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 DATASET permissions on the Dataset - trans.app.security_agent.set_all_dataset_permissions( ldda.dataset, permissions ) - trans.sa_session.refresh( ldda.dataset ) - permissions = {} - for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.sa_session.query( 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 ) trans.sa_session.refresh( ldda.library_dataset ) # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation trans.app.security_agent.set_all_library_permissions( ldda, permissions ) trans.sa_session.refresh( ldda ) - 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." + if error: messagetype = 'error' else: - msg = "Permissions have been updated on %d datasets" % len( lddas ) + msg = 'Permissions 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' @@ -560,6 +533,7 @@ cntrller=cntrller, lddas=lddas, library_id=library_id, + roles=roles, msg=msg, messagetype=messagetype ) if len( ids ) > 1: @@ -587,10 +561,12 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) + # Display permission form, permissions will be updated for all lddas simultaneously. return trans.fill_template( "/library/common/ldda_permissions.mako", cntrller=cntrller, lddas=lddas, library_id=library_id, + roles=roles, msg=msg, messagetype=messagetype ) @web.expose @@ -623,72 +599,86 @@ replace_dataset = None upload_option = params.get( 'upload_option', 'upload_file' ) if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() if cntrller == 'library_admin' or \ - ( trans.app.security_agent.can_add_library_item( roles, folder ) or \ - ( replace_dataset and trans.app.security_agent.can_modify_library_item( roles, replace_dataset ) ) ): + ( trans.app.security_agent.can_add_library_item( current_user_roles, folder ) or \ + ( replace_dataset and trans.app.security_agent.can_modify_library_item( current_user_roles, replace_dataset ) ) ): 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 ) - if info_association: - template_id = str( info_association.template.id ) - widgets = folder.get_template_widgets( trans, get_contents=False ) - else: - template_id = 'None' - widgets = [] - created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, - cntrller=cntrller, - 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() ) - ldda_id_list = [ str( v.id ) for v in created_outputs.values() ] - if replace_dataset: - msg = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, replace_dataset_name, folder.name ) + # Check to see if the user selected roles to associate with the DATASET_ACCESS permission + # on the dataset that would make the dataset in-accessible to everyone. + roles = params.get( 'roles', False ) + error = None + if roles: + vars = dict( DATASET_ACCESS_in=roles ) + permissions, in_roles, error, msg = \ + trans.app.security_agent.check_library_dataset_access( trans, trans.app.security.decode_id( library_id ), **vars ) + if error: + if error == trans.app.security_agent.IN_ACCESSIBLE: + msg = "At least 1 user must have every role associated with accessing datasets. The roles you " + msg += "attempted to associate for access would make the datasets in-accessible by everyone." + messagetype = 'error' + if not error: + # See if we have any inherited templates, but do not inherit contents. + info_association, inherited = folder.get_info_association( inherited=True ) + if info_association: + template_id = str( info_association.template.id ) + widgets = folder.get_template_widgets( trans, get_contents=False ) else: - if not folder.parent: - # Libraries have the same name as their root_folder - msg = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, folder.name ) + template_id = 'None' + widgets = [] + created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans, + cntrller=cntrller, + 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() ) + ldda_id_list = [ str( v.id ) for v in created_outputs.values() ] + if replace_dataset: + msg = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, replace_dataset_name, folder.name ) else: - msg = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, folder.name ) - if cntrller == 'library_admin': - msg += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." - messagetype='done' - else: - # Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need - # to check one of them to see if the current user can manage permissions on them. - check_ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( ldda_id_list[0] ) - if trans.app.security_agent.can_manage_library_item( roles, check_ldda ): - if replace_dataset: - default_action = '' + if not folder.parent: + # Libraries have the same name as their root_folder + msg = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, folder.name ) + else: + msg = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, folder.name ) + if cntrller == 'library_admin': + msg += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." + messagetype='done' + else: + # Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need + # to check one of them to see if the current user can manage permissions on them. + check_ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( ldda_id_list[0] ) + if trans.app.security_agent.can_manage_library_item( current_user_roles, check_ldda ): + if replace_dataset: + default_action = '' + else: + msg += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." + default_action = 'manage_permissions' else: - msg += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." - default_action = 'manage_permissions' - else: - default_action = 'add' - trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - default_action=default_action, - created_ldda_ids=",".join( ldda_id_list ), - msg=util.sanitize_text( msg ), - messagetype='done' ) ) - - else: - msg = "Upload failed" - messagetype='error' - trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - created_ldda_ids=",".join( [ str( v.id ) for v in created_outputs.values() ] ), - msg=util.sanitize_text( msg ), - messagetype=messagetype ) ) + default_action = 'add' + trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + cntrller=cntrller, + id=library_id, + default_action=default_action, + created_ldda_ids=",".join( ldda_id_list ), + msg=util.sanitize_text( msg ), + messagetype='done' ) ) + + else: + msg = "Upload failed" + messagetype='error' + trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + cntrller=cntrller, + id=library_id, + created_ldda_ids=",".join( [ str( v.id ) for v in created_outputs.values() ] ), + msg=util.sanitize_text( 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' ) @@ -700,10 +690,11 @@ 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.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) + # Send list of legitimate roles to the form so the dataset can be associated with 1 or more of them. + # If the library is public, all active roles are legitimate. If the library is restricted by the + # LIBRARY_ACCESS permission, only those roles associated with that permission are legitimate. + library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + roles = library.get_legitimate_roles( trans ) # Send the current history to the form to enable importing datasets from history to library history = trans.get_history() trans.sa_session.refresh( history ) @@ -949,8 +940,8 @@ # Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need # to check one of them to see if the current user can manage permissions on them. check_ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id_list[0] ) ) - roles = trans.get_current_user_roles() - if trans.app.security_agent.can_manage_library_item( roles, check_ldda ): + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_manage_library_item( current_user_roles, check_ldda ): if replace_dataset: default_action = '' else: @@ -977,10 +968,9 @@ 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.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) + # Send list of legitimate roles to the form so the dataset can be associated with 1 or more of them. + library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + roles = library.get_legitimate_roles( trans ) return trans.fill_template( "/library/common/upload.mako", upload_option=upload_option, library_id=library_id, @@ -1039,10 +1029,9 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() if params.get( 'edit_attributes_button', False ): - if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, library_dataset ): + if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ): if params.get( 'edit_attributes_button', False ): old_name = library_dataset.name new_name = util.restore_text( params.get( 'name', '' ) ) @@ -1064,6 +1053,7 @@ cntrller=cntrller, library_dataset=library_dataset, library_id=library_id, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) @web.expose @@ -1080,15 +1070,17 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() if params.get( 'update_roles_button', False ): - if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( roles, library_dataset ): + if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset ): # The user clicked the Save button on the 'Associate With Roles' form permissions = {} for k, v in trans.app.model.Library.permitted_actions.items(): - in_roles = [ trans.sa_session.query( 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 + if k != 'LIBRARY_ACCESS': + # LIBRARY_ACCESS is a special permission set only at the library level + # and it is not inherited. + in_roles = [ trans.sa_session.query( 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( library_dataset, permissions ) @@ -1101,16 +1093,20 @@ else: msg = "You are not authorized to managed the permissions of this dataset" messagetype = "error" + library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) + roles = library.get_legitimate_roles( trans ) return trans.fill_template( '/library/common/library_dataset_permissions.mako', cntrller=cntrller, library_dataset=library_dataset, library_id=library_id, + roles=roles, + current_user_roles=current_user_roles, msg=msg, messagetype=messagetype ) @web.expose def act_on_multiple_datasets( self, trans, cntrller, library_id, ldda_ids='', **kwd ): # This method is used by the select list labeled "Perform action on selected datasets" - # on the analysis library browser. + # on the analysis library browser params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) @@ -1204,11 +1200,11 @@ msg=util.sanitize_text( msg ), messagetype='error' ) ) seen = [] - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() for ldda_id in ldda_ids: ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) ) if not ldda \ - or not trans.app.security_agent.can_access_dataset( roles, ldda.dataset ) \ + or not trans.app.security_agent.can_access_dataset( current_user_roles, ldda.dataset ) \ or ldda.dataset.state in [ 'new', 'upload', 'queued', 'running', 'empty', 'discarded' ]: continue path = "" @@ -1318,7 +1314,7 @@ id=response_id, library_id=library_id, msg=msg, - message_type='done' ) ) + messagetype='done' ) ) return trans.fill_template( '/library/common/select_info_template.mako', cntrller=cntrller, library_item_name=library_item.name, diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/requests.py --- a/lib/galaxy/web/controllers/requests.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/requests.py Fri Jan 22 11:24:28 2010 -0500 @@ -604,11 +604,11 @@ all_libraries = trans.sa_session.query( trans.app.model.Library ) \ .filter( trans.app.model.Library.table.c.deleted == False ) \ .order_by( trans.app.model.Library.name ) - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ] libraries = odict() for library in all_libraries: - can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( trans.user, roles, library, actions_to_check ) + can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( trans.user, current_user_roles, library, actions_to_check ) if can_show: libraries[ library ] = hidden_folder_ids # create data library selectbox with refresh on change enabled @@ -662,7 +662,7 @@ folder_list.add_option('Select one', 'none') # get all show-able folders for the selected library showable_folders = trans.app.security_agent.get_showable_folders( trans.user, - roles, + current_user_roles, selected_lib, actions_to_check, selected_hidden_folder_ids ) diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/root.py --- a/lib/galaxy/web/controllers/root.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/root.py Fri Jan 22 11:24:28 2010 -0500 @@ -161,8 +161,8 @@ except: return "Dataset id '%s' is invalid" %str( id ) if data: - roles = trans.get_current_user_roles() - if trans.app.security_agent.can_access_dataset( roles, data.dataset ): + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() ) trans.response.set_content_type(mime) if tofile: @@ -194,8 +194,8 @@ if data: child = data.get_child_by_designation( designation ) if child: - roles = trans.get_current_user_roles() - if trans.app.security_agent.can_access_dataset( roles, child ): + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, child ): return self.display( trans, id=child.id, tofile=tofile, toext=toext ) else: return "You are not privileged to access this dataset." @@ -211,8 +211,8 @@ if 'authz_method' in kwd: authz_method = kwd['authz_method'] if data: - roles = trans.get_current_user_roles() - if authz_method == 'rbac' and trans.app.security_agent.can_access_dataset( roles, data ): + current_user_roles = trans.get_current_user_roles() + if authz_method == 'rbac' and trans.app.security_agent.can_access_dataset( current_user_roles, data ): trans.response.set_content_type( data.get_mime() ) trans.log_event( "Formatted dataset id %s for display at %s" % ( str( id ), display_app ) ) return data.as_display_type( display_app, **kwd ) @@ -266,8 +266,8 @@ return trans.show_error_message( "Problem retrieving dataset." ) if id is not None and data.history.user is not None and data.history.user != trans.user: return trans.show_error_message( "This instance of a dataset (%s) in a history does not belong to you." % ( data.id ) ) - roles = trans.get_current_user_roles() - if trans.app.security_agent.can_access_dataset( roles, data.dataset ): + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): if data.state == trans.model.Dataset.states.UPLOAD: return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to edit its metadata." ) params = util.Params( kwd, sanitize=False ) @@ -333,7 +333,7 @@ elif params.update_roles_button: if not trans.user: return trans.show_error_message( "You must be logged in if you want to change permissions." ) - if trans.app.security_agent.can_manage_dataset( roles, data.dataset ): + if trans.app.security_agent.can_manage_dataset( current_user_roles, data.dataset ): permissions = {} for k, v in trans.app.model.Dataset.permitted_actions.items(): in_roles = params.get( k + '_in', [] ) @@ -358,7 +358,10 @@ 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() trans.log_event( "Opened edit view on dataset %s" % str(id) ) - return trans.fill_template( "/dataset/edit_attributes.mako", data=data, datatypes=ldatatypes ) + return trans.fill_template( "/dataset/edit_attributes.mako", + data=data, + datatypes=ldatatypes, + current_user_roles=current_user_roles ) else: return trans.show_error_message( "You do not have permission to edit this dataset's ( id: %s ) information." % str( id ) )
diff -r 4cd66d01aaf0 -r 8916a67cc639 lib/galaxy/web/controllers/tool_runner.py --- a/lib/galaxy/web/controllers/tool_runner.py Fri Jan 22 10:49:38 2010 -0500 +++ b/lib/galaxy/web/controllers/tool_runner.py Fri Jan 22 11:24:28 2010 -0500 @@ -140,6 +140,18 @@ """ Precreate datasets for asynchronous uploading. """ + roles = kwd.get( 'roles', False ) + if roles: + # The user associated the DATASET_ACCESS permission on the uploaded datasets with 1 or more roles. + # We need to ensure that the roles are legitimately derived from the roles associated with the LIBRARY_ACCESS + # permission if the library is not public ( this should always be the case since any ill-legitimate roles + # were filtered out of the roles displayed on the upload form. In addition, we need to ensure that the user + # did not associated roles that would make the dataset in-accessible by everyone. + library_id = trans.app.security.decode_id( kwd.get( 'library_id', '' ) ) + vars = dict( DATASET_ACCESS_in=roles ) + permissions, in_roles, error, msg = trans.app.security_agent.check_library_dataset_access( trans, library_id, **vars ) + if error: + return [ 'error', msg ] permissions = trans.app.security_agent.history_get_default_permissions( trans.history ) def create_dataset( name ): ud = Bunch( name=name, file_type=None, dbkey=None ) diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/admin/center.mako --- a/templates/admin/center.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/admin/center.mako Fri Jan 22 11:24:28 2010 -0500 @@ -6,7 +6,7 @@
<p>The menu on the left provides the following features</p> <ul> - <li><strong>Security</strong> + <li><strong>Security</strong> - see the <strong>Data Security and Data Libraries</strong> section below for details <p/> <ul> <li> @@ -16,14 +16,15 @@ <p/> <li> <strong>Manage groups</strong> - provides a view of all groups along with the members of the group and the roles associated with - each group (both private and non-private roles). Non-private roles include a link to a page that allows you to manage the users - and groups that are associated with the role. The page also includes a view of the data library datasets that are associated with the - role and the permissions applied to each dataset. + each group (both private and non-private roles). The group names include a link to a page that allows you to manage the users and + roles that are associated with the group. </li> <p/> <li> <strong>Manage roles</strong> - provides a view of all non-private roles along with the role type, and the users and groups that - are associated with the role. + are associated with the role. The role names include a link to a page that allows you to manage the users and groups that are associated + with the role. The page also includes a view of the data library datasets that are associated with the role and the permissions applied + to each dataset. </li> </ul> </li> @@ -33,8 +34,21 @@ <ul> <li> <strong>Manage data libraries</strong> - Data libraries enable a Galaxy administrator to upload datasets into a data library. Currently, - only administrators can create data libraries, but permission to perform the following functions on the data library can be granted to - users (a library item is one of: a data library, a library folder, a library dataset). + only administrators can create data libraries. + <p/> + When a data library is first created, it is considered "public" since it will be displayed in the "Data Libraries" view for any user, even + those that are not logged in. The Galaxy administrator can restrict access to a data library by associating roles with the data library's + "access library" permission. This permission will conservatively override the [dataset] "access" permission for the data library's contained + datasets. + <p/> + For example, if a data library's "access library" permission is associated with Role1 and the data library contains "public" datasets, the + data library will still only be displayed to those users that have Role1. However, if the data library's "access library" permission is + associated with both Role1 and Role2 and the data library contains datasets whose [dataset] "access" permission is associated with only Role1, + then users that have Role2 will be able to access the library, but will not see those contained datasets whose [dataset] "access" permission + is associated with only Role1. + <p/> + In addition to the "access library" permission, permission to perform the following functions on the data library (and it's contents) can + be granted to users (a library item is one of: a data library, a library folder, a library dataset). <p/> <ul> <li><strong>add library item</strong> - Role members can add library items to this data library or folder</li> @@ -42,10 +56,10 @@ <li><strong>manage library permissions</strong> - Role members can manage permissions applied to this library item</li> </ul> <p/> - The default behavior is for no permissions to be applied to a data library item, but applied permissions are inherited downward, so it is - important to set desired permissions on a new data library when it is created. When this is done, new folders and datasets added to the - data library will automatically inherit those permissions. In the same way, permissions can be applied to a folder, which will be - automatically inherited by all contained datasets and sub-folders. + The default behavior is for no permissions to be applied to a data library item, but applied permissions are inherited downward (with the exception + of the "access library" permission, which is only available on the data library itself). Because of this, it is important to set desired permissions + on a new data library when it is created. When this is done, new folders and datasets added to the data library will automatically inherit those + permissions. In the same way, permissions can be applied to a folder, which will be automatically inherited by all contained datasets and sub-folders. <p/> The "Data Libraries" menu item allows users to access the datasets in a data library as long as they are not restricted from accessing them. Importing a library dataset into a history will not make a copy of the dataset, but will be a "pointer" to the dataset on disk. This @@ -71,7 +85,20 @@ </li> </ul> </li> + <p/> + <li><strong>Forms</strong> + <p/>To be completed + </li> + <p/> + <li><strong>Sequencing Requests</strong> + <p/>To be completed + </li> + <p/> + <li><strong>Cloud</strong> + <p/>To be completed + </li> </ul> +<p/> <p><strong>Data Security and Data Libraries</strong></p> <p/> <strong>Security</strong> - Data security in Galaxy is a new feature, so familiarize yourself with the details which can be found @@ -120,9 +147,10 @@ <li> <strong>access</strong> - users associated with the role can import this dataset into their history for analysis. <p> - If no roles with the "access" permission are associated with a dataset, the dataset is "public" and may be accessed by - anyone. Public data library datasets will be accessible to all users (as well as anyone not logged in during a Galaxy session) - from the list of data libraries displayed when the "Data Libraries" menu item is selected. + If no roles with the "access" permission are associated with a dataset, the dataset is "public" and may be accessed by anyone + that can access the data library in which it is contained. See the <strong>Manage data libraries</strong> section above for + details. Public datasets contained in public data libraries will be accessible to all users (as well as anyone not logged in + during a Galaxy session) from the list of data libraries displayed when the "Data Libraries" menu item is selected. </p> <p> Associating a dataset with a role that includes the "access" permission restricts the set of users that can access it. @@ -139,11 +167,11 @@ <p> In order for a user to make a dataset private (i.e., only they can access it), they should associate the dataset with their private role (the role identical to their Galaxy user name / email address). Associating additional roles that - include the "access" permission is not possible, since it would render the dataset inaccessible to everyone. To make - a dataset private to themselves and one or more other users, the user can create a new role and associate the dataset - with that role, not their "private role". Galaxy makes this easy by telling the user they are about to share a private - dataset and giving them the option of doing so. If they respond positively, the sharing role is automatically created - for them. + include the "access" permission is not possible, since it would render the dataset inaccessible to everyone. + <p> + To make a dataset private to themselves and one or more other users, the user can create a new role and associate the dataset + with that role, not their "private role". Galaxy makes this easy by telling the user they are about to share a private dataset + and giving them the option of doing so. If they respond positively, the sharing role is automatically created for them. </p> <p> Private data (data associated with roles that include the "access" permission) must be made public in order to be used @@ -156,3 +184,4 @@ </ul> </li> </ul> +<br/> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/base_panels.mako --- a/templates/base_panels.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/base_panels.mako Fri Jan 22 11:24:28 2010 -0500 @@ -95,16 +95,33 @@ } // Make a synchronous request to create the datasets first var async_datasets; + var upload_error = false; $.ajax( { async: false, type: "POST", url: "${h.url_for(controller='/tool_runner', action='upload_async_create')}", data: $(this).formSerialize(), dataType: "json", - success: function( d, s ) { async_datasets = d.join() } + success: function(array_obj, status) { + if (array_obj.length > 0) { + if (array_obj[0] == 'error') { + upload_error = true; + upload_form_error(array_obj[1]); + } else { + async_datasets = array_obj.join(); + } + } else { + // ( gvk 1/22/10 ) FIXME: this block is never entered, so there may be a bug somewhere + // I've done some debugging like checking to see if array_obj is undefined, but have not + // tracked down the behavior that will result in this block being entered. I believe the + // intent was to have this block entered if the upload button is clicked on the upload + // form but no file was selected. + upload_error = true; + upload_form_error( 'No data was entered in the upload form. You may choose to upload a file, paste some data directly in the data box, or enter URL(s) to fetch data.' ); + } + } } ); - if (async_datasets == '') { - upload_form_error( 'No data was entered in the upload form. You may choose to upload a file, paste some data directly in the data box, or enter URL(s) to fetch from.' ); + if (upload_error == true) { return false; } else { $(this).find("input[name=async_datasets]").val( async_datasets ); diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/dataset/edit_attributes.mako --- a/templates/dataset/edit_attributes.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/dataset/edit_attributes.mako Fri Jan 22 11:24:28 2010 -0500 @@ -6,7 +6,6 @@ <%def name="stylesheets()"> ${h.css( "base", "autocomplete_tagging" )} </%def> -<% user_roles = trans.get_current_user_roles() %>
<%def name="javascripts()"> ${parent.javascripts()} @@ -163,9 +162,9 @@ </div> <p />
-%if trans.app.security_agent.can_manage_dataset( user_roles, data.dataset ): +%if trans.app.security_agent.can_manage_dataset( current_user_roles, data.dataset ): <%namespace file="/dataset/security_common.mako" import="render_permission_form" /> - ${render_permission_form( data.dataset, data.get_display_name(), h.url_for( controller='root', action='edit', id=data.id ), user_roles )} + ${render_permission_form( data.dataset, data.get_display_name(), h.url_for( controller='root', action='edit', id=data.id ), current_user_roles )} %elif trans.user: <div class="toolForm"> <div class="toolFormTitle">View Permissions</div> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/browse_library.mako --- a/templates/library/common/browse_library.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/browse_library.mako Fri Jan 22 11:24:28 2010 -0500 @@ -16,12 +16,11 @@
<% if cntrller in [ 'library', 'requests' ]: - roles = trans.get_current_user_roles() - can_add = trans.app.security_agent.can_add_library_item( roles, library ) + can_add = trans.app.security_agent.can_add_library_item( current_user_roles, library ) if can_add: info_association, inherited = library.get_info_association() - can_modify = trans.app.security_agent.can_modify_library_item( roles, library ) - can_manage = trans.app.security_agent.can_manage_library_item( roles, library ) + can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, library ) + can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, library ) elif cntrller in [ 'library_admin', 'requests_admin' ]: info_association, inherited = library.get_info_association()
@@ -162,8 +161,8 @@ if ldda == library_dataset.library_dataset_dataset_association: current_version = True if cntrller in [ 'library', 'requests' ]: - can_modify_library_dataset = trans.app.security_agent.can_modify_library_item( roles, library_dataset ) - can_manage_library_dataset = trans.app.security_agent.can_manage_library_item( roles, library_dataset ) + can_modify_library_dataset = trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ) + can_manage_library_dataset = trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset ) else: current_version = False if current_version and ldda.state not in ( 'ok', 'error', 'empty', 'deleted', 'discarded' ): @@ -191,7 +190,7 @@ <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_display_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ) )}">View this dataset's information</a> %endif %if cntrller in [ 'library_admin', 'requests_admin' ] or can_manage_library_dataset: - <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_permissions', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), permissions=True )}">Edit this dataset's permissions</a> + <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_permissions', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ) )}">Edit this dataset's permissions</a> %endif %if cntrller in [ 'library_admin', 'requests_admin' ] or can_modify_library_dataset: <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), replace_id=trans.security.encode_id( library_dataset.id ) )}">Upload a new version of this dataset</a> @@ -236,22 +235,22 @@ return "" my_row = None if cntrller in [ 'library', 'requests' ]: - can_access, folder_ids = trans.app.security_agent.check_folder_contents( user, roles, folder ) + can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, folder ) if not can_access: can_show, folder_ids = \ - trans.app.security_agent.show_library_item( user, - roles, + trans.app.security_agent.show_library_item( trans.user, + current_user_roles, folder, [ trans.app.security_agent.permitted_actions.LIBRARY_ADD, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ] ) if not can_show: return "" - can_add = trans.app.security_agent.can_add_library_item( roles, folder ) + can_add = trans.app.security_agent.can_add_library_item( current_user_roles, folder ) if can_add: info_association, inherited = folder.get_info_association( restrict=True ) - can_modify = trans.app.security_agent.can_modify_library_item( roles, folder ) - can_manage = trans.app.security_agent.can_manage_library_item( roles, folder ) + can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, folder ) + can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) elif cntrller in [ 'library_admin', 'requests_admin' ]: info_association, inherited = folder.get_info_association( restrict=True ) %> @@ -311,7 +310,7 @@ %for library_dataset in folder.active_library_datasets: <% ldda = library_dataset.library_dataset_dataset_association - can_access = trans.app.security_agent.can_access_dataset( roles, ldda.dataset ) + can_access = trans.app.security_agent.can_access_dataset( current_user_roles, ldda.dataset ) selected = created_ldda_ids and str( ldda.id ) in created_ldda_ids %> %if can_access: diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/common.mako --- a/templates/library/common/common.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/common.mako Fri Jan 22 11:24:28 2010 -0500 @@ -15,14 +15,14 @@ library_item_type = 'library_dataset_dataset_association' library_item_desc = 'library dataset' if cntrller == 'library': - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() %> %if widgets: <p/> <div class="toolForm"> <div class="toolFormTitle">Other information about ${library_item_desc} ${library_item.name}</div> <div class="toolFormBody"> - %if editable and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, library_item ) ): + %if editable and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, library_item ) ): <form name="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, library_id=library_id, response_action=response_action, num_widgets=len( widgets ) )}" method="post"> <input type="hidden" name="library_item_id" value="${trans.security.encode_id( library_item.id )}"/> <input type="hidden" name="library_item_type" value="${library_item_type}"/> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/folder_info.mako --- a/templates/library/common/folder_info.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/folder_info.mako Fri Jan 22 11:24:28 2010 -0500 @@ -2,11 +2,6 @@ <%namespace file="/message.mako" import="render_msg" /> <%namespace file="/library/common/common.mako" import="render_template_info" />
-<% - if cntrller != 'library_admin': - roles = trans.get_current_user_roles() -%> - <br/><br/> <ul class="manage-table-actions"> <li> @@ -21,7 +16,7 @@ <div class="toolForm"> <div class="toolFormTitle">Edit folder name and description</div> <div class="toolFormBody"> - %if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, folder ): + %if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, folder ): <form name="folder" action="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=library_id )}" method="post" > <div class="form-row"> <label>Name:</label> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/folder_permissions.mako --- a/templates/library/common/folder_permissions.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/folder_permissions.mako Fri Jan 22 11:24:28 2010 -0500 @@ -13,9 +13,7 @@ ${render_msg( msg, messagetype )} %endif
-<% roles = trans.get_current_user_roles() %> - -%if cntrller=='library_admin' or trans.app.security_agent.can_manage_library_item( roles, folder ): +%if cntrller in [ 'library_admin', 'requests_admin' ] or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ): ## LIBRARY_ACCESS is a special permission that is set only at the library level. ${render_permission_form( folder, folder.name, h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=library_id ), roles, do_not_render=[ 'LIBRARY_ACCESS' ] )} %endif diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/ldda_edit_info.mako --- a/templates/library/common/ldda_edit_info.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/ldda_edit_info.mako Fri Jan 22 11:24:28 2010 -0500 @@ -20,11 +20,6 @@ ${h.css( "autocomplete_tagging" )} </%def>
-<% - if cntrller == 'library': - roles = trans.get_current_user_roles() -%> - %if ldda == ldda.library_dataset.library_dataset_dataset_association: <b><i>This is the latest version of this library dataset</i></b> %else: @@ -54,7 +49,7 @@ </select> </%def>
-%if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda.library_dataset ): +%if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset ): <div class="toolForm"> <div class="toolFormTitle">Edit attributes of ${ldda.name}</div> <div class="toolFormBody"> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/ldda_info.mako --- a/templates/library/common/ldda_info.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/ldda_info.mako Fri Jan 22 11:24:28 2010 -0500 @@ -8,8 +8,6 @@ current_version = True else: current_version = False - if cntrller == 'library': - roles = trans.get_current_user_roles() %>
%if current_version: @@ -42,15 +40,15 @@ %if not library.deleted and not ldda.library_dataset.folder.deleted and not ldda.deleted: <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a> <div popupmenu="dataset-${ldda.id}-popup"> - %if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda.library_dataset ): + %if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset ): <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_edit_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ) )}">Edit this dataset's information</a> %else: <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_display_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ) )}">View this dataset's information</a> %endif - %if cntrller=='library_admin' or trans.app.security_agent.can_manage_dataset( roles, ldda.dataset ) and trans.app.security_agent.can_manage_library_item( roles, ldda.library_dataset ): + %if cntrller=='library_admin' or trans.app.security_agent.can_manage_dataset( current_user_roles, ldda.dataset ) and trans.app.security_agent.can_manage_library_item( current_user_roles, ldda.library_dataset ): <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_permissions', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ) )}">Edit this dataset's permissions</a> %endif - %if current_version and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, ldda.library_dataset ) ): + %if current_version and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset ) ): <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), replace_id=trans.security.encode_id( ldda.library_dataset.id ) )}">Upload a new version of this dataset</a> %endif %if cntrller=='library' and ldda.has_data: diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/ldda_permissions.mako --- a/templates/library/common/ldda_permissions.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/ldda_permissions.mako Fri Jan 22 11:24:28 2010 -0500 @@ -3,11 +3,6 @@ <%namespace file="/dataset/security_common.mako" import="render_permission_form" />
<% - from galaxy import util - - roles = trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) if len( lddas ) > 1: name_str = '%d selected datasets' % len( lddas ) else: diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/library_dataset_info.mako --- a/templates/library/common/library_dataset_info.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/library_dataset_info.mako Fri Jan 22 11:24:28 2010 -0500 @@ -2,11 +2,6 @@ <%namespace file="/message.mako" import="render_msg" /> <%namespace file="/library/common/common.mako" import="render_template_info" />
-<% - if cntrller=='library': - roles = trans.get_current_user_roles() -%> - %if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset: <b><i>This is the latest version of this library dataset</i></b> %else: @@ -24,7 +19,7 @@ ${render_msg( msg, messagetype )} %endif
-%if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( roles, library_dataset ): +%if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ): <div class="toolForm"> <div class="toolFormTitle">Edit attributes of ${library_dataset.name}</div> <div class="toolFormBody"> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/library_dataset_permissions.mako --- a/templates/library/common/library_dataset_permissions.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/library_dataset_permissions.mako Fri Jan 22 11:24:28 2010 -0500 @@ -2,11 +2,6 @@ <%namespace file="/message.mako" import="render_msg" /> <%namespace file="/dataset/security_common.mako" import="render_permission_form" />>
-<% - if cntrller == 'library': - roles = trans.get_current_user_roles() -%> - %if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset: <b><i>This is the latest version of this library dataset</i></b> %else: @@ -24,12 +19,7 @@ ${render_msg( msg, messagetype )} %endif
-%if trans.app.security_agent.can_manage_library_item( user_roles, library_dataset ): - <% - roles = trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) - %> +%if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset ): ## LIBRARY_ACCESS is a special permission that is set only at the library level. ${render_permission_form( library_dataset, library_dataset.name, h.url_for( controller='library_common', action='library_dataset_permissions', cntrller=cntrller, id=trans.security.encode_id( library_dataset.id ), library_id=library_id ), roles, do_not_render=[ 'LIBRARY_ACCESS' ] )} %endif diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/library_info.mako --- a/templates/library/common/library_info.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/library_info.mako Fri Jan 22 11:24:28 2010 -0500 @@ -2,11 +2,6 @@ <%namespace file="/message.mako" import="render_msg" /> <%namespace file="/library/common/common.mako" import="render_template_info" />
-<% - if not trans.user_is_admin(): - roles = trans.get_current_user_roles() -%> - <br/><br/> <ul class="manage-table-actions"> <li> @@ -18,7 +13,7 @@ ${render_msg( msg, messagetype )} %endif
-%if cntrller == 'library_admin' or trans.app.security_agent.can_modify_library_item( roles, library ): +%if cntrller == 'library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, library ): <div class="toolForm"> <div class="toolFormTitle">Change library name and description</div> <div class="toolFormBody"> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/library/common/library_permissions.mako --- a/templates/library/common/library_permissions.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/library/common/library_permissions.mako Fri Jan 22 11:24:28 2010 -0500 @@ -2,11 +2,6 @@ <%namespace file="/message.mako" import="render_msg" /> <%namespace file="/dataset/security_common.mako" import="render_permission_form" />
-<% - if not trans.user_is_admin(): - roles = trans.get_current_user_roles() -%> - <br/><br/> <ul class="manage-table-actions"> <li> @@ -18,11 +13,6 @@ ${render_msg( msg, messagetype )} %endif
-%if trans.user_is_admin or trans.app.security_agent.can_manage_library_item( user_roles, library ): - <% - roles = trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) - %> +%if cntrller == 'library_admin' or trans.app.security_agent.can_manage_library_item( current_user_roles, library ): ${render_permission_form( library, library.name, h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), cntrller=cntrller ), roles )} %endif diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/mobile/history/detail.mako --- a/templates/mobile/history/detail.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/mobile/history/detail.mako Fri Jan 22 11:24:28 2010 -0500 @@ -36,8 +36,8 @@
<div class="secondary"> ## Body for history items, extra info and actions, data "peek" - <% roles = trans.get_current_user_roles() %> - %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ): + <% current_user_roles = trans.get_current_user_roles() %> + %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): <div>You do not have permission to view this dataset.</div> %elif data_state == "queued": <div>Job is waiting to run</div> diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/mobile/manage_library.mako --- a/templates/mobile/manage_library.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/mobile/manage_library.mako Fri Jan 22 11:24:28 2010 -0500 @@ -3,13 +3,13 @@ <%namespace file="/dataset/security_common.mako" import="render_permission_form" /> <%namespace file="/library/common/common.mako" import="render_template_info" />
-<% roles = trans.get_current_user_roles() %> +<% current_user_roles = trans.get_current_user_roles() %>
%if msg: ${render_msg( msg, messagetype )} %endif
-%if trans.app.security_agent.can_modify_library_item( roles, library ): +%if trans.app.security_agent.can_modify_library_item( current_user_roles, library ): <div class="toolForm"> <div class="toolFormTitle">Change library name and description</div> <div class="toolFormBody"> @@ -49,12 +49,8 @@ </div> </div> %endif -%if trans.app.security_agent.can_manage_library_item( roles, library ): - <% - roles = trans.sa_session.query( trans.app.model.Role ) \ - .filter( trans.app.model.Role.table.c.deleted==False ) \ - .order_by( trans.app.model.Role.table.c.name ) - %> +%if trans.app.security_agent.can_manage_library_item( current_user_roles, library ): + <% roles = library.get_legitimate_roles( trans ) %> ${render_permission_form( library, library.name, h.url_for( controller='library_common', cntrller='mobile', action='library_permissions', id=trans.security.encode_id( library.id ) ), roles )} %endif
diff -r 4cd66d01aaf0 -r 8916a67cc639 templates/root/history_common.mako --- a/templates/root/history_common.mako Fri Jan 22 10:49:38 2010 -0500 +++ b/templates/root/history_common.mako Fri Jan 22 11:24:28 2010 -0500 @@ -7,9 +7,9 @@ data_state = "queued" else: data_state = data.state - roles = trans.get_current_user_roles() + current_user_roles = trans.get_current_user_roles() %> - %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ): + %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): <div class="historyItemWrapper historyItem historyItem-${data_state} historyItem-noPermission" id="historyItem-${data.id}"> %else: <div class="historyItemWrapper historyItem historyItem-${data_state}" id="historyItem-${data.id}"> @@ -49,7 +49,7 @@ ## Body for history items, extra info and actions, data "peek"
<div id="info${data.id}" class="historyItemBody"> - %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( roles, data.dataset ): + %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): <div>You do not have permission to view this dataset.</div> %elif data_state == "upload": <div>Dataset is uploading</div> diff -r 4cd66d01aaf0 -r 8916a67cc639 test/base/twilltestcase.py --- a/test/base/twilltestcase.py Fri Jan 22 10:49:38 2010 -0500 +++ b/test/base/twilltestcase.py Fri Jan 22 11:24:28 2010 -0500 @@ -1454,7 +1454,7 @@ tc.fv( "1", "dbkey", dbkey ) tc.fv( "1", "message", message.replace( '+', ' ' ) ) for role_id in roles: - tc.fv( "1", "roles", role_id ) # form field 7 is the select list named out_groups, note the buttons... + tc.fv( "1", "roles", role_id ) # Add template field contents, if any... if template_field_name1: tc.fv( "1", template_field_name1, template_field_contents1 ) @@ -1463,7 +1463,6 @@ check_str = "Added 1 datasets to the library '%s' (each is selected)." % folder_name else: check_str = "Added 1 datasets to the folder '%s' (each is selected)." % folder_name - data = self.last_page() self.library_wait( library_id ) self.home() def set_library_dataset_permissions( self, cntrller, library_id, folder_id, ldda_id, ldda_name, role_ids_str, permissions_in, permissions_out ): diff -r 4cd66d01aaf0 -r 8916a67cc639 test/functional/test_security_and_libraries.py --- a/test/functional/test_security_and_libraries.py Fri Jan 22 10:49:38 2010 -0500 +++ b/test/functional/test_security_and_libraries.py Fri Jan 22 11:24:28 2010 -0500 @@ -243,6 +243,14 @@ global regular_user3 regular_user3 = sa_session.query( galaxy.model.User ).filter( galaxy.model.User.table.c.email==email ).first() assert regular_user3 is not None, 'Problem retrieving user with email "%s" from the database' % email + global regular_user3_private_role + regular_user3_private_role = None + for role in regular_user3.all_roles(): + if role.name == regular_user3.email and role.description == 'Private Role for %s' % regular_user3.email: + regular_user3_private_role = role + break + if not regular_user3_private_role: + raise AssertionError( "Private role not found for user '%s'" % regular_user3.email ) # Make sure DefaultUserPermissions were created if not regular_user3.default_permissions: raise AssertionError( 'No DefaultUserPermissions were created for user %s when the admin created the account' % email ) @@ -510,16 +518,32 @@ galaxy.model.Library.table.c.deleted==False ) ) \ .first() assert library_one is not None, 'Problem retrieving library named "%s" from the database' % name - # Set permissions on the library, sort for later testing + # Make sure library_one is public + assert 'access library' not in [ a.action for a in library_one.actions ], 'Library %s is not public when first created' % library_one.name + # Set permissions on the library, sort for later testing. permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ] permissions_out = [] - # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted to - # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE for library items. + # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for + # LIBRARY_ACCESS, LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents. self.library_permissions( self.security.encode_id( library_one.id ), library_one.name, str( role_one.id ), permissions_in, - permissions_out ) + permissions_out ) + # Make sure the library is accessible by admin_user + self.visit_url( '%s/library/browse_libraries' % self.url ) + self.check_page_for_string( library_one.name ) + # Make sure the library is not accessible by regular_user2 since regular_user2 does not have Role1. + self.logout() + self.login( email=regular_user2.email ) + self.visit_url( '%s/library/browse_libraries' % self.url ) + try: + self.check_page_for_string( library_one.name ) + raise AssertionError, 'Library %s is accessible by %s when it should be restricted' % ( library_one.name, regular_user2.email ) + except: + pass + self.logout() + self.login( email=admin_user.email ) # Rename the library rename = "Library One's been Renamed" redescription = "This is Library One's Re-described" @@ -593,7 +617,11 @@ def test_085_add_public_dataset_to_root_folder( self ): """Testing adding a public dataset to the root folder, making sure library template is inherited""" # Logged in as admin_user - actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + #actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + actions = [] + for k, v in galaxy.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + actions.append( v.action ) actions.sort() message = 'Testing adding a public dataset to the root folder' # The form_one template should be inherited to the library dataset upload form. @@ -625,8 +653,8 @@ .all() ldda_permissions = [ lddap_obj.action for lddap_obj in ldda_permissions ] ldda_permissions.sort() - assert actions == ldda_permissions, "Permissions for ldda id %s not correctly inherited from library %s" \ - % ( ldda_one.id, library_one.name ) + assert actions == ldda_permissions, "Permissions (%s) for ldda id %s not correctly inherited from library %s which has permissions (%s)." \ + % ( str( ldda_permissions ), ldda_one.id, library_one.name, str( actions ) ) # Make sure DatasetPermissions are correct - default is 'manage permissions' if len( ldda_one.dataset.actions ) > 1: raise AssertionError( '%d DatasetPermissionss were created for dataset id %d when it was created ( should have been 1 )' \ @@ -640,15 +668,56 @@ self.visit_url( "%s/library_common/ldda_edit_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \ ( self.url, self.security.encode_id( library_one.id ), self.security.encode_id( library_one.root_folder.id ), self.security.encode_id( ldda_one.id ) ) ) self.check_page_for_string( template_contents ) - # Make sure other users can access the dataset from the Libraries view + # Make sure only users that have Role1 can access library_one even though it now contains a public dataset self.logout() + # regular_user2 does not have Role1 self.login( email=regular_user2.email ) - self.home() - self.visit_url( '%s/library_common/browse_library?cntrller=library_admin&id=%s' % ( self.url, self.security.encode_id( library_one.id ) ) ) - self.check_page_for_string( "1.bed" ) + self.visit_url( '%s/library/browse_libraries' % self.url ) + try: + self.check_page_for_string( library_one.name ) + raise AssertionError, 'Library %s is accessible by %s when it should be restricted' % ( library_one.name, regular_user2.email ) + except: + pass self.logout() self.login( email=admin_user.email ) self.home() + # Make sure only legitimate roles are displayed on the permissions form for the public dataset. + # Legitimate roles are as follows: + # 'Role One' since the LIBRARY_ACCESS permission is associated with Role One. # Role one members are: admin_user, regular_user1, regular_user3. + # 'test@bx.psu.edu' ( admin_user's private role ) since admin_user has Role One + # 'Role Two' since admin_user has Role Two + # 'Role Three' since admin_user has Role Three + # 'test1@bx.psu.edu' ( regular_user1's private role ) since regular_user1 has Role One + # 'test3@bx.psu.edu' ( regular_user3's private role ) since regular_user3 has Role One + library_id = self.security.encode_id( library_one.id ) + folder_id = self.security.encode_id( library_one.root_folder.id ) + id = self.security.encode_id( ldda_one.id ) + self.visit_url( '%s/library_common/ldda_permissions?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s' % \ + ( self.url, library_id, folder_id, id ) ) + self.check_page_for_string( role_one.name ) + self.check_page_for_string( admin_user_private_role.name ) + self.check_page_for_string( role_two.name ) + self.check_page_for_string( role_three.name ) + self.check_page_for_string( regular_user1_private_role.name ) + self.check_page_for_string( regular_user3_private_role.name ) + try: + self.check_page_for_string( regular_user2_private_role.name ) + raise AssertionError, "Role (%s) incorrectly displayed on permission form for library dataset (%s)." % \ + ( regular_user2_private_role.name, ldda_one.name ) + except: + pass + # Even though the dataset is public, only users with Role1 should be able to see the library_one + # from the Data Libraries view. Role one members are: admin_user, regular_user1, regular_user3. + self.logout() + self.login( email=regular_user1.email ) + self.visit_url( '%s/library/browse_libraries' % self.url ) + self.check_page_for_string( library_one.name ) + self.logout() + self.login( email=regular_user2.email ) + self.visit_url( '%s/library/browse_libraries' % self.url ) + self.check_page_for_string( "You are not authorized to access any libraries" ) + self.logout() + self.login( email=admin_user.email ) def test_090_add_new_folder_to_root_folder( self ): """Testing adding a folder to a library root folder""" # logged in as admin_user @@ -696,7 +765,11 @@ # logged in as admin_user name = "Folder One's Subfolder" description = "This is the Folder One's subfolder" - self.add_folder( 'library_admin', self.security.encode_id( library_one.id ), self.security.encode_id( folder_one.id ), name=name, description=description ) + self.add_folder( 'library_admin', + self.security.encode_id( library_one.id ), + self.security.encode_id( folder_one.id ), + name=name, + description=description ) global subfolder_one subfolder_one = sa_session.query( galaxy.model.LibraryFolder ) \ .filter( and_( galaxy.model.LibraryFolder.table.c.parent_id==folder_one.id, @@ -728,6 +801,18 @@ tc.submit( 'edit_info_button' ) self.check_page_for_string( 'The information has been updated.' ) self.check_page_for_string( template_contents ) + # Make sure no roles except Role1 are displayed on the permissions form for the sub-folder. + library_id = self.security.encode_id( library_one.id ) + id = self.security.encode_id( subfolder_one.id ) + self.visit_url( '%s/library_common/folder_permissions?cntrller=library_admin&id=%s&library_id=%s' % \ + ( self.url, id, library_id ) ) + self.check_page_for_string( role_one.name ) + try: + self.check_page_for_string( role_two.name ) + raise AssertionError, "Role (%s) incorrectly displayed on permission form for library dataset (%s)." % \ + ( role_two.name, ldda_one.name ) + except: + pass def test_100_add_2nd_new_folder_to_root_folder( self ): """Testing adding a 2nd folder to a library root folder""" # logged in as admin_user @@ -762,7 +847,11 @@ def test_105_add_public_dataset_to_root_folders_2nd_subfolder( self ): """Testing adding a public dataset to the root folder's 2nd sub-folder""" # Logged in as admin_user - actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + #actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + actions = [] + for k, v in galaxy.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + actions.append( v.action ) actions.sort() message = "Testing adding a public dataset to the folder named %s" % folder_two.name # The form_one template should be inherited to the library dataset upload form. @@ -796,7 +885,11 @@ def test_110_add_2nd_public_dataset_to_root_folders_2nd_subfolder( self ): """Testing adding a 2nd public dataset to the root folder's 2nd sub-folder""" # Logged in as admin_user - actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + #actions = [ v.action for k, v in galaxy.model.Library.permitted_actions.items() ] + actions = [] + for k, v in galaxy.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + actions.append( v.action ) actions.sort() message = "Testing adding a 2nd public dataset to the folder named %s" % folder_two.name # The form_one template should be inherited to the library dataset upload form. @@ -830,6 +923,9 @@ def test_115_add_dataset_with_private_role_restriction_to_folder( self ): """Testing adding a dataset with a private role restriction to a folder""" # Logged in as admin_user + # + # Keep in mind that # LIBRARY_ACCESS = "Role One" on the whole library + # # Add a dataset restricted by the following: # DATASET_MANAGE_PERMISSIONS = "test@bx.psu.edu" via DefaultUserPermissions # DATASET_ACCESS = "regular_user1" private role via this test method @@ -877,7 +973,20 @@ def test_120_accessing_dataset_with_private_role_restriction( self ): """Testing accessing a dataset with a private role restriction""" # Logged in as admin_user - # admin_user should not be able to see 2.bed from the analysis view's access libraries + # + # Keep in mind that # LIBRARY_ACCESS = "Role One" on the whole library + # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will be permitted for + # LIBRARY_ACCESS, LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents. + # + # Legitimate roles displayed on the permission form are as follows: + # 'Role One' since the LIBRARY_ACCESS permission is associated with Role One. # Role one members are: admin_user, regular_user1, regular_user3. + # 'test@bx.psu.edu' ( admin_user's private role ) since admin_user has Role One + # 'Role Two' since admin_user has Role Two + # 'Role Three' since admin_user has Role Three + # 'test1@bx.psu.edu' ( regular_user1's private role ) since regular_user1 has Role One + # 'test3@bx.psu.edu' ( regular_user3's private role ) since regular_user3 has Role One + # + # admin_user should not be able to see 4.bed from the analysis view's access libraries self.home() self.visit_url( '%s/library_common/browse_library?cntrller=library&id=%s' % ( self.url, self.security.encode_id( library_one.id ) ) ) try: @@ -901,23 +1010,15 @@ self.check_page_for_string( folder_one.name ) self.check_page_for_string( '4.bed' ) self.logout() - # regular_user2 should not be able to see 1.bed from the analysis view's access librarys + # regular_user2 should not be to see the library since they do not have + # Role One which is associated with the LIBRARY_ACCESS permission self.login( email='test2@bx.psu.edu' ) - try: - self.check_page_for_string( folder_one.name ) - raise AssertionError( '%s can see library folder %s when it contains only datasets restricted by role %s' \ - % ( regular_user2.email, folder_one.name, regular_user1_private_role.description ) ) - except: - pass - try: - self.check_page_for_string( '4.bed' ) - raise AssertionError( '%s can see dataset 4.bed in library folder %s when it was restricted by role %s' \ - % ( regular_user2.email, folder_one.name, regular_user1_private_role.description ) ) - except: - pass + self.visit_url( '%s/library/browse_libraries' % self.url ) + self.check_page_for_string( "You are not authorized to access any libraries" ) self.logout() - # regular_user3 should not be able to see 2.bed from the analysis view's access librarys + # regular_user3 should not be able to see 4.bed from the analysis view's access librarys self.login( email='test3@bx.psu.edu' ) + self.visit_url( '%s/library_common/browse_library?cntrller=library&id=%s' % ( self.url, self.security.encode_id( library_one.id ) ) ) try: self.check_page_for_string( folder_one.name ) raise AssertionError( '%s can see library folder %s when it contains only datasets restricted by role %s' \ @@ -929,16 +1030,18 @@ raise AssertionError( '%s can see dataset 4.bed in library folder %s when it was restricted by role %s' \ % ( regular_user3.email, folder_one.name, regular_user1_private_role.description ) ) except: - pass # This is the behavior we want + pass self.logout() self.login( email=admin_user.email ) self.home() def test_125_change_dataset_access_permission( self ): """Testing changing the access permission on a dataset with a private role restriction""" # Logged in as admin_user - # We need admin_user to be able to access 2.bed - permissions_in = [ k for k, v in galaxy.model.Dataset.permitted_actions.items() ] + \ - [ k for k, v in galaxy.model.Library.permitted_actions.items() ] + # We need admin_user to be able to access 4.bed + permissions_in = [ k for k, v in galaxy.model.Dataset.permitted_actions.items() ] + for k, v in galaxy.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + permissions_in.append( k ) permissions_out = [] role_ids_str = '%s,%s' % ( str( role_one.id ), str( admin_user_private_role.id ) ) self.set_library_dataset_permissions( 'library_admin', @@ -960,6 +1063,22 @@ # Add a dataset restricted by role_two, which is currently associated as follows: # groups: group_two # users: test@bx.psu.edu, test1@bx.psu.edu via group_two + # + # We first need to make library_one public + permissions_in = [] + for k, v in galaxy.model.Library.permitted_actions.items(): + if k != 'LIBRARY_ACCESS': + permissions_in.append( k ) + permissions_out = [] + # Role one members are: admin_user, regular_user1, regular_user3. Each of these users will now be permitted for + # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on this library and it's contents. The library will be public from + # this point on. + self.library_permissions( self.security.encode_id( library_one.id ), + library_one.name, + str( role_one.id ), + permissions_in, + permissions_out ) + sa_session.refresh( library_one ) message = 'Testing adding a dataset with a role that is associated with a group and users' # The form_one template should be inherited to the library dataset upload form. template_contents = "%s contents for %s 5.bed" % ( form_one_field_label, folder_one.name ) diff -r 4cd66d01aaf0 -r 8916a67cc639 test/functional/test_toolbox.py --- a/test/functional/test_toolbox.py Fri Jan 22 10:49:38 2010 -0500 +++ b/test/functional/test_toolbox.py Fri Jan 22 11:24:28 2010 -0500 @@ -69,6 +69,7 @@ name, file, sort = output_tuple # Get the correct hid elem = data_list[ elem_index ] + self.assertTrue( elem ) elem_hid = elem.get( 'hid' ) elem_index += 1 self.verify_dataset_correctness( file, hid=elem_hid, maxseconds=testdef.maxseconds, sort=sort )
galaxy-dev@lists.galaxyproject.org