diff --git a/lib/galaxy/security/__init__.py b/lib/galaxy/security/__init__.py
index a4872281f95..f6c4bcd026f 100644
--- a/lib/galaxy/security/__init__.py
+++ b/lib/galaxy/security/__init__.py
@@ -18,8 +18,6 @@ class Action( object ):
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 permissions on this dataset", "grant" ),
DATASET_ACCESS = Action( "access", "Role members can import this dataset into their history for analysis", "restrict" ),
@@ -79,9 +77,9 @@ class RBACAgent:
raise "Unimplemented Method"
def get_permissions( self, library_dataset ):
raise "Unimplemented Method"
- def get_legitimate_roles( self, trans, item ):
+ def get_legitimate_roles( self, trans, item, cntrller ):
raise "Unimplemented Method"
- def derive_roles_from_access( self, trans, item_id, library=False, **kwd ):
+ def derive_roles_from_access( self, trans, item_id, cntrller, library=False, **kwd ):
raise "Unimplemented Method"
def get_component_associations( self, **kwd ):
raise "Unimplemented Method"
@@ -109,15 +107,26 @@ class GalaxyRBACAgent( RBACAgent ):
def sa_session( self ):
"""Returns a SQLAlchemy session"""
return self.model.context
- def get_legitimate_roles( self, trans, item ):
+ def get_legitimate_roles( self, trans, item, cntrller ):
"""
Return a sorted list of legitimate roles that can be associated with a permission on
- item where item is a Library or a Dataset. If item is public, all non-private roles,
- except for the current user's private role, are legitimate. If item is restricted,
- legitimate roles are derived from the users and groups associated with each role that
- is associated with the access permission ( i.e., DATASET_MANAGE_PERMISSIONS or
- LIBRARY_MANAGE ) on item.
+ item where item is a Library or a Dataset. The cntrller param is the controller from
+ which the request is sent. We cannot use trans.user_is_admin() because the controller is
+ what is important since admin users do not necessarily have permission to do things
+ on items outside of the admin view.
+ If cntrller is from the admin side ( e.g., library_admin ):
+ -if item is public, all roles, including private roles, are legitimate.
+ -if item is restricted, legitimate roles are derived from the users and groups associated
+ with each role that is associated with the access permission ( i.e., DATASET_MANAGE_PERMISSIONS or
+ LIBRARY_MANAGE ) on item. Legitimate roles will include private roles.
+ If cntrller is not from the admin side ( e.g., root, library ):
+ -if item is public, all non-private roles, except for the current user's private role,
+ are legitimate.
+ -if item is restricted, legitimate roles are derived from the users and groups associated
+ with each role that is associated with the access permission on item. Private roles, except
+ for the current user's private role, will be excluded.
"""
+ admin_controller = cntrller in [ 'library_admin' ]
def sort_by_attr( seq, attr ):
"""
Sort the sequence of objects by object's attribute
@@ -142,29 +151,37 @@ class GalaxyRBACAgent( RBACAgent ):
self.model.Role.table.c.type != self.model.Role.types.PRIVATE,
self.model.Role.table.c.type != self.model.Role.types.SHARING ) ) \
.order_by( self.model.Role.table.c.name )
- # Add the current user's private role
- roles.add( self.get_private_user_role( trans.user ) )
- # Add the current user's sharing roles
- for role in self.get_sharing_roles( trans.user ):
- roles.add( role )
- # Add all remaining non-private, non-sharing roles
- for role in trans.sa_session.query( trans.app.model.Role ) \
- .filter( and_( self.model.Role.table.c.deleted==False,
- self.model.Role.table.c.type != self.model.Role.types.PRIVATE,
- self.model.Role.table.c.type != self.model.Role.types.SHARING ) ) \
- .order_by( self.model.Role.table.c.name ):
- roles.add( role )
- return sort_by_attr( [ role for role in roles ], 'name' )
+ if admin_controller:
+ # The library is public and the user is an admin, so all roles are legitimate
+ for role in trans.sa_session.query( trans.app.model.Role ) \
+ .filter( self.model.Role.table.c.deleted==False ) \
+ .order_by( self.model.Role.table.c.name ):
+ roles.add( role )
+ return sort_by_attr( [ role for role in roles ], 'name' )
+ else:
+ # Add the current user's private role
+ roles.add( self.get_private_user_role( trans.user ) )
+ # Add the current user's sharing roles
+ for role in self.get_sharing_roles( trans.user ):
+ roles.add( role )
+ # Add all remaining non-private, non-sharing roles
+ for role in trans.sa_session.query( trans.app.model.Role ) \
+ .filter( and_( self.model.Role.table.c.deleted==False,
+ self.model.Role.table.c.type != self.model.Role.types.PRIVATE,
+ self.model.Role.table.c.type != self.model.Role.types.SHARING ) ) \
+ .order_by( self.model.Role.table.c.name ):
+ roles.add( role )
+ return sort_by_attr( [ role for role in roles ], 'name' )
# If item has roles associated with the access permission, we need to start with them.
access_roles = item.get_access_roles( trans )
for role in access_roles:
- if self.ok_to_display( trans, role ):
+ if admin_controller or self.ok_to_display( trans.user, role ):
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:
user = ura.user
for ura2 in user.roles:
- if self.ok_to_display( trans, ura2.role ):
+ if admin_controller or self.ok_to_display( trans.user, ura2.role ):
roles.add( ura2.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.
@@ -173,20 +190,20 @@ class GalaxyRBACAgent( RBACAgent ):
for uga in group.users:
user = uga.user
for ura in user.roles:
- if self.ok_to_display( trans, ura.role ):
+ if admin_controller or self.ok_to_display( trans.user, ura.role ):
roles.add( ura.role )
return sort_by_attr( [ role for role in roles ], 'name' )
- def ok_to_display( self, trans, role ):
+ def ok_to_display( self, user, role ):
"""
Method for checking if:
- a role is private and is the current user's private role
- a role is a sharing role and belongs to the current user
"""
- if trans.user:
+ if user:
if role.type == self.model.Role.types.PRIVATE:
- return role == self.get_private_user_role( trans.user )
+ return role == self.get_private_user_role( user )
if role.type == self.model.Role.types.SHARING:
- return role in self.get_sharing_roles( trans.user )
+ return role in self.get_sharing_roles( user )
# If role.type is neither private nor sharing, it's ok to display
return True
return role.type != self.model.Role.types.PRIVATE and role.type != self.model.Role.types.SHARING
@@ -490,17 +507,21 @@ class GalaxyRBACAgent( RBACAgent ):
if lp.action == self.permitted_actions.LIBRARY_ACCESS.action:
self.sa_session.delete( lp )
self.sa_session.flush()
- def derive_roles_from_access( self, trans, item_id, library=False, **kwd ):
+ def derive_roles_from_access( self, trans, item_id, cntrller, library=False, **kwd ):
# Check the access permission on a dataset. If library is true, item_id refers to a library. If library
- # is False, item_id refers to a dataset ( item_id must currently be decoded before being sent ).
+ # is False, item_id refers to a dataset ( item_id must currently be decoded before being sent ). The
+ # cntrller param is the calling controller, which needs to be passed to get_legitimate_roles().
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 self.get_legitimate_roles()
+ # legitimate will be True only if all roles in DATASET_ACCESS_in are in the set of roles returned from
+ # get_legitimate_roles()
legitimate = False
- error = None
+ # private_role_found will be true only if more than 1 role is being associated with the DATASET_ACCESS
+ # permission on item, and at least 1 of the roles is private.
+ private_role_found = False
+ error = False
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:
@@ -514,22 +535,18 @@ class GalaxyRBACAgent( RBACAgent ):
# will keep ill-legitimate roles from being associated with the DATASET_ACCESS permission on the
# dataset (i.e., in the case where item is a library, if Role1 is associated with LIBRARY_ACCESS,
# then only those users that have Role1 should be associated with DATASET_ACCESS.
- legitimate_roles = self.get_legitimate_roles( trans, item )
+ legitimate_roles = self.get_legitimate_roles( trans, item, cntrller )
ill_legitimate_roles = []
for role in in_roles:
if role not in legitimate_roles:
ill_legitimate_roles.append( role )
if ill_legitimate_roles:
- # NOTE: this condition should never occur since ill-legitimate roles are filtered out of the set of
- # roles displayed on the permissions forms, but just in case there is a bug somewhere that incorrectly
+ # This condition should never occur since ill-legitimate roles are filtered out of the set of
+ # roles displayed on the forms, but just in case there is a bug somewhere that incorrectly
# filters, we'll display this message.
- error = self.ILL_LEGITIMATE
- if library:
- 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: "
- else:
- msg += "The following roles are not associated with users that have the 'access' permission on this "
- msg += "dataset, so they were incorrectly displayed on the permission form: "
+ error = True
+ msg += "The following roles are not associated with users that have the 'access' permission on this "
+ msg += "item, so they were incorrectly displayed: "
for role in ill_legitimate_roles:
msg += "%s, " % role.name
msg = msg.rstrip( ", " )
@@ -540,6 +557,14 @@ class GalaxyRBACAgent( RBACAgent ):
in_roles = new_in_roles
else:
legitimate = True
+ if len( in_roles ) > 1:
+ # At least 1 user must have every role associated with the access
+ # permission on this dataset, or the dataset is not accessible.
+ # Since we have more than 1 role, none of them can be private.
+ for role in in_roles:
+ if role.type == self.model.Role.types.PRIVATE:
+ private_role_found = True
+ break
if len( in_roles ) == 1:
accessible = True
else:
@@ -556,7 +581,7 @@ class GalaxyRBACAgent( RBACAgent ):
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
+ # 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:
@@ -564,14 +589,16 @@ class GalaxyRBACAgent( RBACAgent ):
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
+ if private_role_found or not accessible:
+ error = True
+ # Don't set the permissions for DATASET_ACCESS if inaccessible or multiple roles with
+ # at least 1 private, 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."
+ msg = "At least 1 user must have every role associated with accessing datasets. "
+ if private_role_found:
+ msg += "Since you are associating more than 1 role, no private roles are allowed."
+ if not accessible:
+ msg += "The roles you attempted to associate for access would make the datasets in-accessible by everyone."
else:
permissions[ self.get_action( v.action ) ] = in_roles
else:
diff --git a/lib/galaxy/tools/actions/upload.py b/lib/galaxy/tools/actions/upload.py
index bbc7d8c01c5..cb341f9b6a9 100644
--- a/lib/galaxy/tools/actions/upload.py
+++ b/lib/galaxy/tools/actions/upload.py
@@ -15,7 +15,9 @@ class UploadToolAction( ToolAction ):
precreated_datasets = upload_common.get_precreated_datasets( trans, incoming, trans.app.model.HistoryDatasetAssociation )
incoming = upload_common.persist_uploads( incoming )
- uploaded_datasets = upload_common.get_uploaded_datasets( trans, incoming, precreated_datasets, dataset_upload_inputs )
+ # We can pass an empty string as the cntrller here since it is used to check whether we
+ # are in an admin view, and this tool is currently not used there.
+ uploaded_datasets = upload_common.get_uploaded_datasets( trans, '', incoming, precreated_datasets, dataset_upload_inputs )
upload_common.cleanup_unused_precreated_datasets( precreated_datasets )
if not uploaded_datasets:
diff --git a/lib/galaxy/tools/actions/upload_common.py b/lib/galaxy/tools/actions/upload_common.py
index 099bbfb5c3c..fbfb82d78bc 100644
--- a/lib/galaxy/tools/actions/upload_common.py
+++ b/lib/galaxy/tools/actions/upload_common.py
@@ -121,10 +121,9 @@ def new_history_upload( trans, uploaded_dataset, state=None ):
trans.app.security_agent.set_all_dataset_permissions( hda.dataset, permissions )
trans.sa_session.flush()
return hda
-def new_library_upload( trans, uploaded_dataset, library_bunch, state=None ):
+def new_library_upload( trans, cntrller, uploaded_dataset, library_bunch, state=None ):
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( "," ) ):
+ if not ( cntrller in [ 'library_admin' ] or trans.app.security_agent.can_add_library_item( current_user_roles, library_bunch.folder ) ):
# 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." )
folder = library_bunch.folder
@@ -203,19 +202,19 @@ def new_library_upload( trans, uploaded_dataset, library_bunch, state=None ):
trans.sa_session.add( dp )
trans.sa_session.flush()
return ldda
-def new_upload( trans, uploaded_dataset, library_bunch=None, state=None ):
+def new_upload( trans, cntrller, uploaded_dataset, library_bunch=None, state=None ):
if library_bunch:
- return new_library_upload( trans, uploaded_dataset, library_bunch, state )
+ return new_library_upload( trans, cntrller, uploaded_dataset, library_bunch, state )
else:
return new_history_upload( trans, uploaded_dataset, state )
-def get_uploaded_datasets( trans, params, precreated_datasets, dataset_upload_inputs, library_bunch=None ):
+def get_uploaded_datasets( trans, cntrller, params, precreated_datasets, dataset_upload_inputs, library_bunch=None ):
uploaded_datasets = []
for dataset_upload_input in dataset_upload_inputs:
uploaded_datasets.extend( dataset_upload_input.get_uploaded_datasets( trans, params ) )
for uploaded_dataset in uploaded_datasets:
data = get_precreated_dataset( precreated_datasets, uploaded_dataset.name )
if not data:
- data = new_upload( trans, uploaded_dataset, library_bunch )
+ data = new_upload( trans, cntrller, uploaded_dataset, library_bunch )
else:
data.extension = uploaded_dataset.file_type
data.dbkey = uploaded_dataset.dbkey
diff --git a/lib/galaxy/web/controllers/library_common.py b/lib/galaxy/web/controllers/library_common.py
index 6010389fcf0..56a551fa2a5 100644
--- a/lib/galaxy/web/controllers/library_common.py
+++ b/lib/galaxy/web/controllers/library_common.py
@@ -107,18 +107,18 @@ class LibraryCommon( BaseController ):
msg += "message \"This job is running\" is cleared from the \"Information\" column below for each selected dataset."
messagetype = "info"
return trans.fill_template( '/library/common/browse_library.mako',
- use_panels=use_panels,
cntrller=cntrller,
+ use_panels=use_panels,
library=library,
created_ldda_ids=created_ldda_ids,
hidden_folder_ids=hidden_folder_ids,
- default_action=params.get( 'default_action', None ),
show_deleted=show_deleted,
comptypes=comptypes,
current_user_roles=current_user_roles,
msg=msg,
messagetype=messagetype )
- return trans.response.send_redirect( web.url_for( controller=cntrller,
+ return trans.response.send_redirect( web.url_for( use_panels=use_panels,
+ controller=cntrller,
action='browse_libraries',
default_action=params.get( 'default_action', None ),
msg=util.sanitize_text( msg ),
@@ -128,6 +128,7 @@ class LibraryCommon( BaseController ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
library_id = params.get( 'id', None )
library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
# See if we have any associated templates
@@ -158,12 +159,14 @@ class LibraryCommon( BaseController ):
return trans.response.send_redirect( web.url_for( controller='library_common',
action='library_info',
cntrller=cntrller,
+ use_panels=use_panels,
id=trans.security.encode_id( library.id ),
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
messagetype='done' ) )
return trans.fill_template( '/library/common/library_info.mako',
cntrller=cntrller,
+ use_panels=use_panels,
library=library,
widgets=widgets,
current_user_roles=current_user_roles,
@@ -177,6 +180,7 @@ class LibraryCommon( BaseController ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
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()
@@ -195,13 +199,15 @@ class LibraryCommon( BaseController ):
return trans.response.send_redirect( web.url_for( controller='library_common',
action='library_permissions',
cntrller=cntrller,
+ use_panels=use_panels,
id=trans.security.encode_id( library.id ),
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
messagetype='done' ) )
- roles = trans.app.security_agent.get_legitimate_roles( trans, library )
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
return trans.fill_template( '/library/common/library_permissions.mako',
cntrller=cntrller,
+ use_panels=use_panels,
library=library,
current_user_roles=current_user_roles,
roles=roles,
@@ -214,12 +220,14 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
parent_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( parent_id ) )
if not parent_folder:
msg = "Invalid parent folder id (%s) specified" % str( parent_id )
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -248,6 +256,7 @@ class LibraryCommon( BaseController ):
msg += "Additional information about this folder may be added using the inherited template."
return trans.fill_template( '/library/common/folder_info.mako',
cntrller=cntrller,
+ use_panels=use_panels,
folder=new_folder,
library_id=library_id,
widgets=widgets,
@@ -262,6 +271,7 @@ class LibraryCommon( BaseController ):
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -270,6 +280,7 @@ class LibraryCommon( BaseController ):
# cannot occur before the associated item is saved.
return trans.fill_template( '/library/common/new_folder.mako',
cntrller=cntrller,
+ use_panels=use_panels,
library_id=library_id,
folder=parent_folder,
show_deleted=show_deleted,
@@ -281,6 +292,7 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) )
current_user_roles = trans.get_current_user_roles()
# See if we have any associated templates
@@ -308,6 +320,7 @@ class LibraryCommon( BaseController ):
messagetype='error'
return trans.fill_template( '/library/common/folder_info.mako',
cntrller=cntrller,
+ use_panels=use_panels,
folder=folder,
library_id=library_id,
widgets=widgets,
@@ -323,12 +336,14 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) )
if not folder:
msg = "Invalid folder specified, id: %s" % str( id )
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -354,6 +369,7 @@ class LibraryCommon( BaseController ):
return trans.response.send_redirect( web.url_for( controller='library_common',
action='folder_permissions',
cntrller=cntrller,
+ use_panels=use_panels,
id=trans.security.encode_id( folder.id ),
library_id=library_id,
show_deleted=show_deleted,
@@ -362,9 +378,10 @@ class LibraryCommon( BaseController ):
# 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 = trans.app.security_agent.get_legitimate_roles( trans, library )
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
return trans.fill_template( '/library/common/folder_permissions.mako',
cntrller=cntrller,
+ use_panels=use_panels,
folder=folder,
library_id=library_id,
current_user_roles=current_user_roles,
@@ -378,12 +395,14 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) )
if not ldda:
msg = "Invalid LibraryDatasetDatasetAssociation specified, id: %s" % str( id )
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -471,6 +490,7 @@ class LibraryCommon( BaseController ):
ldda.metadata.dbkey = ldda.dbkey
return trans.fill_template( "/library/common/ldda_edit_info.mako",
cntrller=cntrller,
+ use_panels=use_panels,
ldda=ldda,
library_id=library_id,
file_formats=file_formats,
@@ -487,12 +507,14 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) )
if not ldda:
msg = "Invalid LibraryDatasetDatasetAssociation specified, id: %s" % str( id )
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -506,6 +528,7 @@ class LibraryCommon( BaseController ):
current_user_roles = trans.get_current_user_roles()
return trans.fill_template( '/library/common/ldda_info.mako',
cntrller=cntrller,
+ use_panels=use_panels,
ldda=ldda,
library=library,
show_deleted=show_deleted,
@@ -521,6 +544,7 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ use_panels = util.string_as_bool( params.get( 'use_panels', False ) )
ids = util.listify( id )
lddas = []
for id in [ trans.security.decode_id( id ) for id in ids ]:
@@ -530,6 +554,7 @@ class LibraryCommon( BaseController ):
trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -544,26 +569,25 @@ class LibraryCommon( BaseController ):
ldda = lddas[0]
if trans.app.security_agent.dataset_is_public( ldda.dataset ):
# The dataset is public, so check access to the library
- roles = trans.app.security_agent.get_legitimate_roles( trans, library )
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
else:
- roles = trans.app.security_agent.get_legitimate_roles( trans, ldda.dataset )
+ roles = trans.app.security_agent.get_legitimate_roles( trans, ldda.dataset, cntrller )
if params.get( 'update_roles_button', False ):
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 ) ):
+ a = trans.app.security_agent.get_action( trans.app.security_agent.permitted_actions.DATASET_ACCESS.action )
permissions, in_roles, error, msg = \
- trans.app.security_agent.derive_roles_from_access( trans, trans.app.security.decode_id( library_id ), library=True, **kwd )
+ trans.app.security_agent.derive_roles_from_access( trans, trans.app.security.decode_id( library_id ), cntrller, library=True, **kwd )
for ldda in lddas:
# Set the DATASET permissions on the Dataset.
- if error == trans.app.security_agent.IN_ACCESSIBLE:
- # If derive_roles_from_access() returned an "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 )
+ if error:
+ # Keep the original role associations for the DATASET_ACCESS permission on the ldda.
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
+ # Set the LIBRARY permissions on the LibraryDataset. The LibraryDataset and
+ # LibraryDatasetDatasetAssociation will be set with the same permissions.
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
if k != 'LIBRARY_ACCESS':
@@ -586,6 +610,7 @@ class LibraryCommon( BaseController ):
messagetype = 'error'
return trans.fill_template( "/library/common/ldda_permissions.mako",
cntrller=cntrller,
+ use_panels=use_panels,
lddas=lddas,
library_id=library_id,
roles=roles,
@@ -613,6 +638,7 @@ class LibraryCommon( BaseController ):
trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
+ use_panels=use_panels,
id=library_id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
@@ -620,6 +646,7 @@ class LibraryCommon( BaseController ):
# Display permission form, permissions will be updated for all lddas simultaneously.
return trans.fill_template( "/library/common/ldda_permissions.mako",
cntrller=cntrller,
+ use_panels=use_panels,
lddas=lddas,
library_id=library_id,
roles=roles,
@@ -632,7 +659,6 @@ class LibraryCommon( BaseController ):
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
deleted = util.string_as_bool( params.get( 'deleted', False ) )
- show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
dbkey = params.get( 'dbkey', '?' )
if isinstance( dbkey, list ):
last_used_build = dbkey[0]
@@ -662,19 +688,27 @@ class LibraryCommon( BaseController ):
( 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 ):
# 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.
+ # on the dataset that would cause accessibility issues.
roles = params.get( 'roles', False )
error = None
if roles:
vars = dict( DATASET_ACCESS_in=roles )
permissions, in_roles, error, msg = \
- trans.app.security_agent.derive_roles_from_access( trans, trans.app.security.decode_id( library_id ), library=True, **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:
+ trans.app.security_agent.derive_roles_from_access( trans, trans.app.security.decode_id( library_id ), cntrller, library=True, **vars )
+ if error:
+ messagetype = 'error'
+
+ trans.response.send_redirect( web.url_for( controller='library_common',
+ action='upload_library_dataset',
+ cntrller=cntrller,
+ library_id=library_id,
+ folder_id=folder_id,
+ replace_id=replace_id,
+ upload_option=upload_option,
+ msg=util.sanitize_text( msg ),
+ messagetype='error' ) )
+
+ else:
# See if we have any inherited templates, but do not inherit contents.
info_association, inherited = folder.get_info_association( inherited=True )
if info_association and info_association.inheritable:
@@ -683,7 +717,7 @@ class LibraryCommon( BaseController ):
else:
template_id = 'None'
widgets = []
- created_outputs = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans,
+ created_outputs_dict = trans.webapp.controllers[ 'library_common' ].upload_dataset( trans,
cntrller=cntrller,
library_id=library_id,
folder_id=folder_id,
@@ -691,9 +725,10 @@ class LibraryCommon( BaseController ):
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 created_outputs_dict:
+ total_added = len( created_outputs_dict.keys() )
+ ldda_id_list = [ str( v.id ) for k, v in created_outputs_dict.items() ]
+ created_ldda_ids=",".join( ldda_id_list )
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:
@@ -722,20 +757,19 @@ class LibraryCommon( BaseController ):
cntrller=cntrller,
id=library_id,
default_action=default_action,
- created_ldda_ids=",".join( ldda_id_list ),
- show_deleted=show_deleted,
+ created_ldda_ids=created_ldda_ids,
msg=util.sanitize_text( msg ),
messagetype='done' ) )
else:
+ created_ldda_ids = ''
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() ] ),
- show_deleted=show_deleted,
+ created_ldda_ids=created_ldda_ids,
msg=util.sanitize_text( msg ),
messagetype=messagetype ) )
# See if we have any inherited templates, but do not inherit contents.
@@ -757,12 +791,12 @@ class LibraryCommon( BaseController ):
# 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 = trans.app.security_agent.get_legitimate_roles( trans, library )
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
# Send the current history to the form to enable importing datasets from history to library
history = trans.get_history()
trans.sa_session.refresh( history )
# If we're using nginx upload, override the form action
- action = web.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, show_deleted=show_deleted )
+ action = web.url_for( controller='library_common', action='upload_library_dataset' )
if upload_option == 'upload_file' and trans.app.config.nginx_upload_path:
# url_for is intentionally not used on the base URL here -
# nginx_upload_path is expected to include the proxy prefix if the
@@ -785,7 +819,6 @@ class LibraryCommon( BaseController ):
roles=roles,
history=history,
widgets=widgets,
- show_deleted=show_deleted,
msg=msg,
messagetype=messagetype )
def upload_dataset( self, trans, cntrller, library_id, folder_id, replace_dataset=None, **kwd ):
@@ -833,11 +866,11 @@ class LibraryCommon( BaseController ):
precreated_datasets = upload_common.get_precreated_datasets( trans, tool_params, trans.app.model.LibraryDatasetDatasetAssociation, controller=cntrller )
if upload_option == 'upload_file':
tool_params = upload_common.persist_uploads( tool_params )
- uploaded_datasets = upload_common.get_uploaded_datasets( trans, tool_params, precreated_datasets, dataset_upload_inputs, library_bunch=library_bunch )
+ uploaded_datasets = upload_common.get_uploaded_datasets( trans, cntrller, tool_params, precreated_datasets, dataset_upload_inputs, library_bunch=library_bunch )
elif upload_option == 'upload_directory':
- uploaded_datasets, err_redirect, msg = self.get_server_dir_uploaded_datasets( trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg )
+ uploaded_datasets, err_redirect, msg = self.get_server_dir_uploaded_datasets( trans, cntrller, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg )
elif upload_option == 'upload_paths':
- uploaded_datasets, err_redirect, msg = self.get_path_paste_uploaded_datasets( trans, params, library_bunch, err_redirect, msg )
+ uploaded_datasets, err_redirect, msg = self.get_path_paste_uploaded_datasets( trans, cntrller, params, library_bunch, err_redirect, msg )
upload_common.cleanup_unused_precreated_datasets( precreated_datasets )
if upload_option == 'upload_file' and not uploaded_datasets:
msg = 'Select a file, enter a URL or enter text'
@@ -855,7 +888,7 @@ class LibraryCommon( BaseController ):
json_file_path = upload_common.create_paramfile( trans, uploaded_datasets )
data_list = [ ud.data for ud in uploaded_datasets ]
return upload_common.create_job( trans, tool_params, tool, json_file_path, data_list, folder=library_bunch.folder )
- def make_library_uploaded_dataset( self, trans, params, name, path, type, library_bunch, in_folder=None ):
+ def make_library_uploaded_dataset( self, trans, cntrller, params, name, path, type, library_bunch, in_folder=None ):
library_bunch.replace_dataset = None # not valid for these types of upload
uploaded_dataset = util.bunch.Bunch()
uploaded_dataset.name = name
@@ -867,14 +900,14 @@ class LibraryCommon( BaseController ):
uploaded_dataset.space_to_tab = params.space_to_tab
if in_folder:
uploaded_dataset.in_folder = in_folder
- uploaded_dataset.data = upload_common.new_upload( trans, uploaded_dataset, library_bunch )
+ uploaded_dataset.data = upload_common.new_upload( trans, cntrller, uploaded_dataset, library_bunch )
if params.get( 'link_data_only', False ):
uploaded_dataset.link_data_only = True
uploaded_dataset.data.file_name = os.path.abspath( path )
trans.sa_session.add( uploaded_dataset.data )
trans.sa_session.flush()
return uploaded_dataset
- def get_server_dir_uploaded_datasets( self, trans, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ):
+ def get_server_dir_uploaded_datasets( self, trans, cntrller, params, full_dir, import_dir_desc, library_bunch, err_redirect, msg ):
files = []
try:
for entry in os.listdir( full_dir ):
@@ -900,9 +933,9 @@ class LibraryCommon( BaseController ):
uploaded_datasets = []
for file in files:
name = os.path.basename( file )
- uploaded_datasets.append( self.make_library_uploaded_dataset( trans, params, name, file, 'server_dir', library_bunch ) )
+ uploaded_datasets.append( self.make_library_uploaded_dataset( trans, cntrller, params, name, file, 'server_dir', library_bunch ) )
return uploaded_datasets, None, None
- def get_path_paste_uploaded_datasets( self, trans, params, library_bunch, err_redirect, msg ):
+ def get_path_paste_uploaded_datasets( self, trans, cntrller, params, library_bunch, err_redirect, msg ):
if params.get( 'filesystem_paths', '' ) == '':
msg = "No paths entered in the upload form"
err_redirect = True
@@ -922,7 +955,7 @@ class LibraryCommon( BaseController ):
if not bad_paths:
if os.path.isfile( path ):
name = os.path.basename( path )
- uploaded_datasets.append( self.make_library_uploaded_dataset( trans, params, name, path, 'path_paste', library_bunch ) )
+ uploaded_datasets.append( self.make_library_uploaded_dataset( trans, cntrller, params, name, path, 'path_paste', library_bunch ) )
for basedir, dirs, files in os.walk( line ):
for file in files:
file_path = os.path.abspath( os.path.join( basedir, file ) )
@@ -930,7 +963,14 @@ class LibraryCommon( BaseController ):
in_folder = os.path.dirname( file_path.replace( path, '', 1 ).lstrip( '/' ) )
else:
in_folder = None
- uploaded_datasets.append( self.make_library_uploaded_dataset( trans, params, file, file_path, 'path_paste', library_bunch, in_folder ) )
+ uploaded_datasets.append( self.make_library_uploaded_dataset( trans,
+ cntrller,
+ params,
+ file,
+ file_path,
+ 'path_paste',
+ library_bunch,
+ in_folder ) )
if bad_paths:
msg = "Invalid paths: