From 083e9fa54712511b1f27f32f7c6baa0b99ebc155 Mon Sep 17 00:00:00 2001 From: Greg Von Kuster Date: Fri, 10 Sep 2010 12:06:54 -0400 Subject: [PATCH] =?UTF-8?q?(no=20commit=20message)(1)=20Add=20the=20abilit?= =?UTF-8?q?y=20to=20make=20any=20library=20item=20public=20(=20and=20it's?= =?UTF-8?q?=20contents=20if=20it=20has=20any=20).=20=C2=AC=E2=80=A0There?= =?UTF-8?q?=20are=20now=20options=20on=20library=20item=20pop-up=20menus?= =?UTF-8?q?=20to=20make=20a=20library=20dataset=20public,=20make=20all=20c?= =?UTF-8?q?ontents=20of=20a=20folder=20public,=20or=20make=20an=20entire?= =?UTF-8?q?=20data=20library=20public.=20(2)=20Enhance=20and=20cleanup=20t?= =?UTF-8?q?he=20test=5Flibrary=5Fsecurity.py=20functional=20test=20script?= =?UTF-8?q?=20to=20cover=20new=20features.=20(3)=20Clean=20up=20security?= =?UTF-8?q?=20checking=20code=20recently=20added=20to=20the=20library-comm?= =?UTF-8?q?on=20controller=20by=20creating=20methods=20for=20checking=20pe?= =?UTF-8?q?rmissions=20and=20calling=20the=20methods=20when=20necessary.?= =?UTF-8?q?=20(4)=20Add=20checks=20to=20the=20security=20controller=20meth?= =?UTF-8?q?ods=20to=20only=20flush=20to=20the=20db=20when=20necessary.=20(?= =?UTF-8?q?5)=20Add=20a=20pop-up=20menu=20for=20folders=20in=20the=20Data?= =?UTF-8?q?=20Libraries=20perspective=20to=20enable=20users=20to=20view=20?= =?UTF-8?q?folder=20information=20since=20it=20may=20include=20template=20?= =?UTF-8?q?information.=20(6)=20Fix=20all=20currently=20broken=20library-r?= =?UTF-8?q?elated=20functional=20test=20-=20should=20now=20all=20be=20gree?= =?UTF-8?q?n.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/galaxy/security/__init__.py | 119 +++- lib/galaxy/web/controllers/library_common.py | 502 +++++---------- templates/library/common/browse_library.mako | 19 +- templates/library/common/common.mako | 11 +- test/base/twilltestcase.py | 38 +- test/functional/test_library_features.py | 11 + test/functional/test_library_security.py | 637 +++++++++---------- 7 files changed, 638 insertions(+), 699 deletions(-) diff --git a/lib/galaxy/security/__init__.py b/lib/galaxy/security/__init__.py index 1520d74b2b3..e82e5b4eba0 100644 --- a/lib/galaxy/security/__init__.py +++ b/lib/galaxy/security/__init__.py @@ -68,16 +68,20 @@ class RBACAgent: raise "Unimplemented Method" def set_dataset_permission( self, dataset, permission ): raise "Unimplemented Method" - def dataset_is_public( self, dataset ): - raise "Unimplemented Method" - def make_dataset_public( self, dataset ): - raise "Unimplemented Method" def set_all_library_permissions( self, dataset, permissions ): raise "Unimplemented Method" def library_is_public( self, library ): raise "Unimplemented Method" def make_library_public( self, library ): raise "Unimplemented Method" + def folder_is_public( self, library ): + raise "Unimplemented Method" + def make_folder_public( self, folder, count=0 ): + raise "Unimplemented Method" + def dataset_is_public( self, dataset ): + raise "Unimplemented Method" + def make_dataset_public( self, dataset ): + raise "Unimplemented Method" def get_permissions( self, library_dataset ): raise "Unimplemented Method" def get_legitimate_roles( self, trans, item, cntrller ): @@ -343,6 +347,7 @@ class GalaxyRBACAgent( RBACAgent ): self.model.Role.table.c.type == self.model.Role.types.SHARING ) ) def user_set_default_permissions( self, user, permissions={}, history=False, dataset=False, bypass_manage_permission=False, default_access_private = False ): # bypass_manage_permission is used to change permissions of datasets in a userless history when logging in + flush_needed = False if user is None: return None if not permissions: @@ -354,13 +359,16 @@ class GalaxyRBACAgent( RBACAgent ): # Delete all of the current default permissions for the user for dup in user.default_permissions: self.sa_session.delete( dup ) + flush_needed = True # Add the new default permissions for the user for action, roles in permissions.items(): if isinstance( action, Action ): action = action.action for dup in [ self.model.DefaultUserPermissions( user, action, role ) for role in roles ]: self.sa_session.add( dup ) - self.sa_session.flush() + flush_needed = True + if flush_needed: + self.sa_session.flush() if history: for history in user.active_histories: self.history_set_default_permissions( history, permissions=permissions, dataset=dataset, bypass_manage_permission=bypass_manage_permission ) @@ -375,6 +383,7 @@ class GalaxyRBACAgent( RBACAgent ): return permissions def history_set_default_permissions( self, history, permissions={}, dataset=False, bypass_manage_permission=False ): # bypass_manage_permission is used to change permissions of datasets in a user-less history when logging in + flush_needed = False user = history.user if not user: # default permissions on a user-less history are None @@ -384,13 +393,16 @@ class GalaxyRBACAgent( RBACAgent ): # Delete all of the current default permission for the history for dhp in history.default_permissions: self.sa_session.delete( dhp ) + flush_needed = True # Add the new default permissions for the history for action, roles in permissions.items(): if isinstance( action, Action ): action = action.action for dhp in [ self.model.DefaultHistoryPermissions( history, action, role ) for role in roles ]: self.sa_session.add( dhp ) - self.sa_session.flush() + flush_needed = True + if flush_needed: + self.sa_session.flush() if dataset: # Only deal with datasets that are not purged for hda in history.activatable_datasets: @@ -417,21 +429,26 @@ class GalaxyRBACAgent( RBACAgent ): Set new permissions on a dataset, eliminating all current permissions permissions looks like: { Action : [ Role, Role ] } """ + flush_needed = False # Delete all of the current permissions on the dataset for dp in dataset.actions: self.sa_session.delete( dp ) + flush_needed = True # Add the new permissions on the dataset for action, roles in permissions.items(): if isinstance( action, Action ): action = action.action for dp in [ self.model.DatasetPermissions( action, dataset, role ) for role in roles ]: self.sa_session.add( dp ) - self.sa_session.flush() + flush_needed = True + if flush_needed: + self.sa_session.flush() def set_dataset_permission( self, dataset, permission={} ): """ Set a specific permission on a dataset, leaving all other current permissions on the dataset alone permissions looks like: { Action : [ Role, Role ] } """ + flush_needed = False for action, roles in permission.items(): if isinstance( action, Action ): action = action.action @@ -439,21 +456,13 @@ class GalaxyRBACAgent( RBACAgent ): for dp in dataset.actions: if dp.action == action: self.sa_session.delete( dp ) + flush_needed = True # Add the new specific permission on the dataset for dp in [ self.model.DatasetPermissions( action, dataset, role ) for role in roles ]: self.sa_session.add( dp ) - self.sa_session.flush() - def dataset_is_public( self, dataset ): - # A dataset is considered public if there are no "access" actions associated with it. Any - # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. - return self.permitted_actions.DATASET_ACCESS.action not in [ a.action for a in dataset.actions ] - def make_dataset_public( self, dataset ): - # A dataset is considered public if there are no "access" actions associated with it. Any - # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. - for dp in dataset.actions: - if dp.action == self.permitted_actions.DATASET_ACCESS.action: - self.sa_session.delete( dp ) - self.sa_session.flush() + flush_needed = True + if flush_needed: + self.sa_session.flush() def get_permissions( self, item ): """ Return a dictionary containing the actions and associated roles on item @@ -503,8 +512,10 @@ class GalaxyRBACAgent( RBACAgent ): self.set_dataset_permission( dataset, { self.permitted_actions.DATASET_ACCESS : [ sharing_role ] } ) def set_all_library_permissions( self, library_item, permissions={} ): # Set new permissions on library_item, eliminating all current permissions + flush_needed = False for role_assoc in library_item.actions: self.sa_session.delete( role_assoc ) + flush_needed = True # Add the new permissions on library_item for item_class, permission_class in self.library_item_assocs: if isinstance( library_item, item_class ): @@ -513,6 +524,7 @@ class GalaxyRBACAgent( RBACAgent ): action = action.action for role_assoc in [ permission_class( action, library_item, role ) for role in roles ]: self.sa_session.add( role_assoc ) + flush_needed = True if isinstance( library_item, self.model.LibraryDatasetDatasetAssociation ) and \ action == self.permitted_actions.LIBRARY_MANAGE.action: # Handle the special case when we are setting the LIBRARY_MANAGE_PERMISSION on a @@ -521,16 +533,58 @@ class GalaxyRBACAgent( RBACAgent ): permissions = {} permissions[ self.permitted_actions.DATASET_MANAGE_PERMISSIONS ] = roles self.set_dataset_permission( library_item.dataset, permissions ) - self.sa_session.flush() - def library_is_public( self, library ): + if flush_needed: + self.sa_session.flush() + def library_is_public( self, library, contents=False ): + if contents: + # Check all contained folders and datasets to find any that are not public + if not self.folder_is_public( library.root_folder ): + return False # A library is considered public if there are no "access" actions associated with it. return self.permitted_actions.LIBRARY_ACCESS.action not in [ a.action for a in library.actions ] - def make_library_public( self, library ): - # A library is considered public if there are no "access" actions associated with it. + def make_library_public( self, library, contents=False ): + flush_needed = False + if contents: + # Make all contained folders (include deleted folders, but not purged folders), public + self.make_folder_public( library.root_folder ) + # A library is considered public if there are no LIBRARY_ACCESS actions associated with it. for lp in library.actions: if lp.action == self.permitted_actions.LIBRARY_ACCESS.action: self.sa_session.delete( lp ) - self.sa_session.flush() + flush_needed = True + if flush_needed: + self.sa_session.flush() + def folder_is_public( self, folder ): + for sub_folder in folder.folders: + if not self.folder_is_public( sub_folder ): + return False + for library_dataset in folder.datasets: + if not self.dataset_is_public( library_dataset.library_dataset_dataset_association.dataset ): + return False + return True + def make_folder_public( self, folder ): + # Make all of the contents (include deleted contents, but not purged contents) of folder public + for sub_folder in folder.folders: + if not sub_folder.purged: + self.make_folder_public( sub_folder ) + for library_dataset in folder.datasets: + dataset = library_dataset.library_dataset_dataset_association.dataset + if not dataset.purged and not self.dataset_is_public( dataset ): + self.make_dataset_public( dataset ) + def dataset_is_public( self, dataset ): + # A dataset is considered public if there are no "access" actions associated with it. Any + # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. + return self.permitted_actions.DATASET_ACCESS.action not in [ a.action for a in dataset.actions ] + def make_dataset_public( self, dataset ): + # A dataset is considered public if there are no "access" actions associated with it. Any + # other actions ( 'manage permissions', 'edit metadata' ) are irrelevant. + flush_needed = False + for dp in dataset.actions: + if dp.action == self.permitted_actions.DATASET_ACCESS.action: + self.sa_session.delete( dp ) + flush_needed = True + if flush_needed: + self.sa_session.flush() 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 ). The @@ -700,8 +754,11 @@ class GalaxyRBACAgent( RBACAgent ): def set_entity_user_associations( self, users=[], roles=[], groups=[], delete_existing_assocs=True ): for user in users: if delete_existing_assocs: + flush_needed = False for a in user.non_private_roles + user.groups: self.sa_session.delete( a ) + flush_needed = True + if flush_needed: self.sa_session.flush() self.sa_session.refresh( user ) for role in roles: @@ -713,8 +770,11 @@ class GalaxyRBACAgent( RBACAgent ): def set_entity_group_associations( self, groups=[], users=[], roles=[], delete_existing_assocs=True ): for group in groups: if delete_existing_assocs: + flush_needed = False for a in group.roles + group.users: self.sa_session.delete( a ) + flush_needed = True + if flush_needed: self.sa_session.flush() for role in roles: self.associate_components( group=group, role=role ) @@ -723,8 +783,11 @@ class GalaxyRBACAgent( RBACAgent ): def set_entity_role_associations( self, roles=[], users=[], groups=[], delete_existing_assocs=True ): for role in roles: if delete_existing_assocs: + flush_needed = False for a in role.users + role.groups: self.sa_session.delete( a ) + flush_needed = True + if flush_needed: self.sa_session.flush() for user in users: self.associate_components( user=user, role=role ) @@ -805,15 +868,15 @@ class GalaxyRBACAgent( RBACAgent ): # Add the new permissions on request_type item_class = self.model.RequestType permission_class = self.model.RequestTypePermissions + flush_needed = False for action, roles in permissions.items(): if isinstance( action, Action ): action = action.action for role_assoc in [ permission_class( action, request_type, role ) for role in roles ]: self.sa_session.add( role_assoc ) - self.sa_session.flush() - - - + flush_needed = True + if flush_needed: + self.sa_session.flush() class HostAgent( RBACAgent ): """ diff --git a/lib/galaxy/web/controllers/library_common.py b/lib/galaxy/web/controllers/library_common.py index db8a20baac2..26bb37b65d0 100644 --- a/lib/galaxy/web/controllers/library_common.py +++ b/lib/galaxy/web/controllers/library_common.py @@ -151,25 +151,9 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) except: library = None - # Deny that the library exists if the user does not have the LIBRARY_ACCESS permission. - if not library or not ( is_admin or trans.app.security_agent.can_access_library( current_user_roles, library ) ): - message = "Invalid library id ( %s ) specified." % str( library_id ) - return trans.response.send_redirect( web.url_for( controller=cntrller, - action='browse_libraries', - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'library_info_button', False ): - # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission. - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library ) ): - message = "You are not authorized to modify library '%s'." % library.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_modify( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) old_name = library.name new_name = util.restore_text( params.get( 'name', 'No name' ) ) if not new_name: @@ -227,24 +211,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) except: library = None - # Deny that the library exists if the user does not have the LIBRARY_ACCESS permission. - if not library or not ( is_admin or trans.app.security_agent.can_access_library( current_user_roles, library ) ): - message = "Invalid library id ( %s ) specified." % str( library_id ) - return trans.response.send_redirect( web.url_for( controller=cntrller, - action='browse_libraries', - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not have the LIBRARY_MANAGE permission. - if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, library ) ): - message = "You are not authorized to manage permissions on library '%s'." % library.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'update_roles_button', False ): # The user clicked the Save button on the 'Associate With Roles' form permissions = {} @@ -291,37 +259,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): # library, which could be anything. if parent_folder: parent_library = parent_folder.parent_library - # Deny that the parent folder exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to see the folder's contents. - if not parent_folder or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, parent_folder, trans.user ) ): - message = "Invalid parent folder id ( %s ) specified." % str( parent_id ) - if cntrller == 'api': - return 400, message - # This doesn't give away the library's existence since - # browse_library will simply punt to browse_libraries if the - # user-supplied id is invalid or inaccessible. - 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not have the LIBRARY_ADD permission. - if not ( is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, parent_folder ) ): - message = "You are not authorized to create a folder in parent folder '%s'." % parent_folder.name - # Redirect to the real parent library since we know we have access to it. - if cntrller == 'api': - return 403, message - 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, parent_folder, current_user_roles, use_panels, library_id, show_deleted ) + self._check_add( trans, cntrller, is_admin, parent_folder, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'new_folder_button', False ) or cntrller == 'api': new_folder = trans.app.model.LibraryFolder( name=util.restore_text( params.name ), description=util.restore_text( params.description ) ) @@ -391,29 +330,9 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) ) except: folder = None - # Deny that the parent folder exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to see the folder's contents. - if not folder or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ): - message = "Invalid folder id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'rename_folder_button', False ): - # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, folder ) ): - message = "You are not authorized to modify folder '%s'." % folder.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_modify( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) old_name = folder.name new_name = util.restore_text( params.name ) new_description = util.restore_text( params.description ) @@ -468,28 +387,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) ) except: folder = None - # Deny that the parent folder exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to see the folder's contents. - if not folder or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ): - message = "Invalid folder id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not have the LIBRARY_MANAGE permission. - if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) ): - message = "You are not authorized to manage permissions on folder id ( %s )." % str( id ) - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'update_roles_button', False ): # The user clicked the Save button on the 'Associate With Roles' form permissions = {} @@ -538,28 +437,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) except: ldda = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not ldda or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, ldda, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not have the LIBRARY_MODIFY permission. - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ) ): - message = "You are not authorized to modify library dataset '%s'." % ldda.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, ldda, current_user_roles, use_panels, library_id, show_deleted ) + self._check_modify( trans, cntrller, is_admin, ldda, current_user_roles, use_panels, library_id, show_deleted ) dbkey = params.get( 'dbkey', '?' ) if isinstance( dbkey, list ): dbkey = dbkey[0] @@ -653,18 +532,7 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) except: ldda = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not ldda or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, ldda, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, ldda, current_user_roles, use_panels, library_id, show_deleted ) if is_admin: # Get all associated hdas and lddas that use the same disk file. associated_hdas = trans.sa_session.query( trans.model.HistoryDatasetAssociation ) \ @@ -720,31 +588,7 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): ldda = None if ldda: library = ldda.library_dataset.folder.parent_library - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not ldda or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, ldda, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not - # have the LIBRARY_MANAGE and DATASET_MANAGE_PERMISSIONS permissions. - if not ( is_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 ) ) ): - message = "You are not authorized to manage permissions on library dataset '%s'." % ldda.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, ldda, current_user_roles, use_panels, library_id, show_deleted ) lddas.append( ldda ) libraries.append( library ) library = libraries[0] @@ -869,33 +713,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): replace_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( replace_id ) ) except: replace_dataset = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not replace_dataset or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, replace_dataset, trans.user ) ): - message = "Invalid library dataset id ( %s ) to replace specified." % replace_id - if cntrller == 'api': - return 400, message - 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access if the user is not an admin and does not have the LIBRARY_MODIFY permission. - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, replace_dataset ) ): - message = "You are not authorized to replace library dataset '%s'." % replace_dataset.name - if cntrller == 'api': - return 403, message - 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, replace_dataset, current_user_roles, use_panels, library_id, show_deleted ) + self._check_modify( trans, cntrller, is_admin, replace_dataset, current_user_roles, use_panels, library_id, show_deleted ) library = replace_dataset.folder.parent_library folder = replace_dataset.folder # The name is stored - by the time the new ldda is created, replace_dataset.name @@ -910,33 +729,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) ) except: folder = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to see the folder's contents. - if not folder or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ): - message = "Invalid parent folder id ( %s ) specified." % str( folder_id ) - if cntrller == 'api': - return 400, message - 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access if the user is not an admin and does not have the LIBRARY_ADD permission. - if not ( is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, folder ) ): - message = "You are not authorized to create a library dataset in parent folder '%s'." % folder.name - if cntrller == 'api': - return 403, message - 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) + self._check_add( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) library = folder.parent_library if folder and last_used_build in [ 'None', None, '?' ]: last_used_build = folder.genome_build @@ -1356,29 +1150,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): replace_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( replace_id ) ) except: replace_dataset = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not replace_dataset or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, replace_dataset, trans.user ) ): - message = "Invalid library dataset id ( %s ) to replace specified." % replace_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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access if the user is not an admin and does not have the LIBRARY_MODIFY permission. - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, replace_dataset ) ): - message = "You are not authorized to replace library dataset '%s'." % replace_dataset.name - 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, replace_dataset, current_user_roles, use_panels, library_id, show_deleted ) + self._check_modify( trans, cntrller, is_admin, replace_dataset, current_user_roles, use_panels, library_id, show_deleted ) library = replace_dataset.folder.parent_library folder = replace_dataset.folder last_used_build = replace_dataset.library_dataset_dataset_association.dbkey @@ -1387,29 +1160,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) ) except: folder = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to see the folder's contents. - if not folder or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ): - message = "Invalid parent folder id ( %s ) specified." % str( folder_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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access if the user is not an admin and does not have the LIBRARY_ADD permission. - if not ( is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, folder ) ): - message = "You are not authorized to create a library dataset in parent folder '%s'." % folder.name - 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) + self._check_add( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) library = folder.parent_library last_used_build = folder.genome_build # See if the current history is empty @@ -1434,18 +1186,7 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( trans.security.decode_id( hda_id ) ) except: hda = None - # Deny that the dataset exists if the user does not have the DATASET_ACCESS permission. - if not hda or \ - not ( trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset ) and \ - hda.history.user == trans.user ): - message = "Invalid history dataset id ( %s ) specified." % hda_id - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, hda, current_user_roles, use_panels, library_id, show_deleted ) ldda = hda.to_library_dataset_dataset_association( target_folder=folder, replace_dataset=replace_dataset ) created_ldda_ids = '%s,%s' % ( created_ldda_ids, str( ldda.id ) ) dataset_names.append( ldda.name ) @@ -1531,18 +1272,7 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): ldda = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) except: ldda = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not ldda or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, ldda, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, ldda, current_user_roles, use_panels, library_id, show_deleted ) composite_extensions = trans.app.datatypes_registry.get_composite_extensions( ) ext = ldda.extension if ext in composite_extensions: @@ -1584,29 +1314,9 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): library_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( id ) ) except: library_dataset = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not library_dataset or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, library_dataset, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, library_dataset, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'edit_attributes_button', False ): - # Deny access if the user is not an admin and does not have the LIBRARY_MODIFY permission. - if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ) ): - message = "You are not authorized to modify library dataset '%s'." % library_dataset.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status = 'error' ) ) + self._check_modify( trans, cntrller, is_admin, library_dataset, current_user_roles, use_panels, library_id, show_deleted ) old_name = library_dataset.name new_name = util.restore_text( params.get( 'name', '' ) ) new_info = util.restore_text( params.get( 'info', '' ) ) @@ -1653,31 +1363,8 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): library_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( id ) ) except: library_dataset = None - # Deny that the dataset exists if the user does not have the LIBRARY_ACCESS permission on - # its parent library, or if they are not able to view the dataset itself. - if not library_dataset or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, library_dataset, trans.user ) ): - message = "Invalid library dataset id ( %s ) specified." % 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, - message=util.sanitize_text( message ), - status='error' ) ) - # Deny access (even to view) if the user is not an admin and does not - # have the LIBRARY_MANAGE and DATASET_MANAGE_PERMISSIONS permissions. - if not ( is_admin or \ - ( trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset ) and - trans.app.security_agent.can_manage_dataset( current_user_roles, library_dataset.library_dataset_dataset_association.dataset ) ) ): - message = "You are not authorized to manage permissions on library dataset '%s'." % library_dataset.name - return trans.response.send_redirect( web.url_for( controller='library_common', - action='browse_library', - id=library_id, - cntrller=cntrller, - use_panels=use_panels, - message=util.sanitize_text( message ), - status='error' ) ) + self._check_access( trans, cntrller, is_admin, library_dataset, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, library_dataset, current_user_roles, use_panels, library_id, show_deleted ) if params.get( 'update_roles_button', False ): # The user clicked the Save button on the 'Associate With Roles' form permissions = {} @@ -1708,6 +1395,48 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): message=message, status=status ) @web.expose + def make_library_item_public( self, trans, cntrller, library_id, item_type, id, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) + use_panels = util.string_as_bool( params.get( 'use_panels', False ) ) + current_user_roles = trans.get_current_user_roles() + is_admin = trans.user_is_admin() and cntrller == 'library_admin' + if item_type == 'library': + library = trans.sa_session.query( trans.model.Library ).get( trans.security.decode_id( id ) ) + self._check_access( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, library, current_user_roles, use_panels, library_id, show_deleted ) + contents = util.string_as_bool( params.get( 'contents', 'False' ) ) + trans.app.security_agent.make_library_public( library, contents=contents ) + if contents: + message = "The data library (%s) and all it's contents have been made publicly accessible." % library.name + else: + message = "The data library (%s) has been made publicly accessible, but access to it's contents has been left unchanged." % library.name + elif item_type == 'folder': + folder = trans.sa_session.query( trans.model.LibraryFolder ).get( trans.security.decode_id( id ) ) + self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) + trans.app.security_agent.make_folder_public( folder ) + message = "All of the contents of folder (%s) have been made publicly accessible." % folder.name + elif item_type == 'ldda': + ldda = trans.sa_session.query( trans.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) + self._check_access( trans, cntrller, is_admin, ldda.library_dataset, current_user_roles, use_panels, library_id, show_deleted ) + self._check_manage( trans, cntrller, is_admin, ldda.library_dataset, current_user_roles, use_panels, library_id, show_deleted ) + trans.app.security_agent.make_dataset_public( ldda.dataset ) + message = "The libary dataset (%s) has been made publicly accessible." % ldda.name + else: + message = "Invalid item_type (%s) received." % str( item_type ) + status = 'error' + 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, + message=util.sanitize_text( message ), + status=status ) ) + @web.expose def act_on_multiple_datasets( self, trans, cntrller, library_id, ldda_ids='', **kwd ): class NgxZip( object ): def __init__( self, url_base ): @@ -2462,6 +2191,97 @@ class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): show_deleted=show_deleted, message=message, status=status ) ) + def _check_access( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): + if isinstance( item, trans.model.HistoryDatasetAssociation ): + # Deny that the dataset exists if the user does not have the DATASET_ACCESS permission. + if not item or \ + not ( trans.app.security_agent.can_access_dataset( current_user_roles, item.dataset ) and item.history.user==trans.user ): + message = "Invalid history dataset id (%s) specified." % str( item.id ) + return trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + cntrller=cntrller, + id=library_id, + show_deleted=show_deleted, + message=util.sanitize_text( message ), + status='error' ) ) + # Deny that the item exists if the user does not have the LIBRARY_ACCESS permission on its parent library, + # or if they are not able to access the item itself. + if not item or ( not is_admin and not trans.app.security_agent.can_access_library_item( current_user_roles, item, trans.user ) ): + message = "Invalid item id (%s) specified." % str( item.id ) + if cntrller == 'api': + return 400, message + if isinstance( item, trans.model.Library ): + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_libraries', + cntrller=cntrller, + use_panels=use_panels, + message=util.sanitize_text( message ), + status='error' ) ) + 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, + message=util.sanitize_text( message ), + status='error' ) ) + def _check_add( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): + # Deny access if the user is not an admin and does not have the LIBRARY_ADD permission. + if not ( is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, item ) ): + message = "You are not authorized to add an item to '%s'." % item.name + # Redirect to the real parent library since we know we have access to it. + if cntrller == 'api': + return 403, message + 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, + message=util.sanitize_text( message ), + status='error' ) ) + def _check_manage( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): + if isinstance( item, trans.model.LibraryDataset ): + # Deny access if the user is not an admin and does not have the LIBRARY_MANAGE and DATASET_MANAGE_PERMISSIONS permissions. + if not ( is_admin or \ + ( trans.app.security_agent.can_manage_library_item( current_user_roles, item ) and + trans.app.security_agent.can_manage_dataset( current_user_roles, library_dataset.library_dataset_dataset_association.dataset ) ) ): + message = "You are not authorized to manage permissions on library dataset '%s'." % library_dataset.name + if cntrller == 'api': + return 403, message + return trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + id=library_id, + cntrller=cntrller, + use_panels=use_panels, + message=util.sanitize_text( message ), + status='error' ) ) + # Deny access if the user is not an admin and does not have the LIBRARY_MANAGE permission. + if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, item ) ): + message = "You are not authorized to manage permissions on '%s'." % item.name + if cntrller == 'api': + return 403, message + return trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + id=library_id, + cntrller=cntrller, + use_panels=use_panels, + message=util.sanitize_text( message ), + status='error' ) ) + def _check_modify( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): + # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission. + if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, item ) ): + message = "You are not authorized to modify '%s'." % item.name + if cntrller == 'api': + return 403, message + return trans.response.send_redirect( web.url_for( controller='library_common', + action='browse_library', + cntrller=cntrller, + id=library_id, + use_panels=use_panels, + show_deleted=show_deleted, + message=util.sanitize_text( message ), + status='error' ) ) # ---- Utility methods ------------------------------------------------------- diff --git a/templates/library/common/browse_library.mako b/templates/library/common/browse_library.mako index 7af5197f231..7d457e56e25 100644 --- a/templates/library/common/browse_library.mako +++ b/templates/library/common/browse_library.mako @@ -226,6 +226,9 @@ Delete template %endif %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_manage: + %if not trans.app.security_agent.dataset_is_public( ldda.dataset ): + Make public + %endif Edit permissions %endif %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify: @@ -314,7 +317,7 @@ %if folder.deleted: %endif - %if not branch_deleted( folder ) and ( can_add or can_modify or can_manage ): + %if not branch_deleted( folder ): %if not library.deleted:
@@ -322,8 +325,12 @@ Add datasets Add sub-folder %endif - %if not branch_deleted( folder ) and can_modify: - Edit information + %if not branch_deleted( folder ): + %if can_modify: + Edit information + %else: + View information + %endif %endif %if not branch_deleted( folder ) and can_modify and not info_association: Add template @@ -333,6 +340,9 @@ Delete template %endif %if not branch_deleted( folder ) and can_manage: + %if not trans.app.security_agent.folder_is_public( folder ): + Make public + %endif Edit permissions %endif %if can_modify: @@ -445,6 +455,9 @@ Delete template %endif %if can_manage: + %if not trans.app.security_agent.library_is_public( library, contents=True ): + Make public + %endif Edit permissions %endif %elif can_modify and not library.purged: diff --git a/templates/library/common/common.mako b/templates/library/common/common.mako index e0cc71adb3c..1f0eec64fde 100644 --- a/templates/library/common/common.mako +++ b/templates/library/common/common.mako @@ -7,21 +7,21 @@ if isinstance( field[ 'widget' ], TextArea ) and field[ 'widget' ].value: has_contents = True label = field[ 'label' ] - widget = field[ 'widget' ] + value = '
%s
' % field[ 'widget' ].value elif isinstance( field[ 'widget' ], TextField ) and field[ 'widget' ].value: has_contents = True label = field[ 'label' ] - widget = field[ 'widget' ] + value = field[ 'widget' ].value elif isinstance( field[ 'widget' ], SelectField ) and field[ 'widget' ].options: for option_label, option_value, selected in field['widget'].options: if selected: has_contents = True label = field[ 'label' ] - widget = field[ 'widget' ] + value = option_value elif isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked: has_contents = True label = field[ 'label' ] - widget = field[ 'widget' ] + value = 'checked' elif isinstance( field[ 'widget' ], WorkflowField ) and str( field[ 'widget' ].value ).lower() not in [ 'none' ]: has_contents = True label = field[ 'label' ] @@ -40,11 +40,12 @@ widget = field[ 'widget' ] address = trans.sa_session.query( trans.model.UserAddress ).get( int( widget.value ) ) label = address.desc + value = address.get_html() %> %if has_contents:
- ${widget.get_html( disabled=True )} + ${value}
${field[ 'helptext' ]}
diff --git a/test/base/twilltestcase.py b/test/base/twilltestcase.py index 71d807e9725..16c620f35cc 100644 --- a/test/base/twilltestcase.py +++ b/test/base/twilltestcase.py @@ -1705,12 +1705,18 @@ class TwillTestCase( unittest.TestCase ): raise AssertionError, "String (%s) incorrectly displayed when browing library." % not_displayed1 except: pass - def browse_libraries_regular_user( self, check_str1='', check_str2='' ): + def browse_libraries_regular_user( self, check_str1='', check_str2='', not_displayed1='' ): self.visit_url( '%s/library/browse_libraries' % self.url ) if check_str1: self.check_page_for_string( check_str1 ) if check_str2: self.check_page_for_string( check_str2 ) + if not_displayed1: + try: + self.check_page_for_string( not_displayed1 ) + raise AssertionError, "String (%s) incorrectly displayed when browing library." % not_displayed1 + except: + pass def browse_library( self, cntrller, id, show_deleted=False, check_str1='', check_str2='', check_str3='', not_displayed='', not_displayed2='' ): self.visit_url( '%s/library_common/browse_library?cntrller=%s&id=%s&show_deleted=%s' % ( self.url, cntrller, id, str( show_deleted ) ) ) @@ -1798,11 +1804,25 @@ class TwillTestCase( unittest.TestCase ): check_str = "Permissions updated for library '%s'." % library_name self.check_page_for_string( check_str ) self.home() + def make_library_item_public( self, library_id, id, cntrller='library_admin', item_type='library', + contents=False, library_name='', folder_name='', ldda_name='' ): + url = "%s/library_common/make_library_item_public?cntrller=%s&library_id=%s&item_type=%s&id=%s&contents=%s" % \ + ( self.url, cntrller, library_id, item_type, id, str( contents ) ) + self.visit_url( url ) + if item_type == 'library': + if contents: + check_str = "The data library (%s) and all it's contents have been made publicly accessible." % library_name + else: + check_str = "The data library (%s) has been made publicly accessible, but access to it's contents has been left unchanged." % library_name + elif item_type == 'folder': + check_str = "All of the contents of folder (%s) have been made publicly accessible." % folder_name + elif item_type == 'ldda': + check_str = "The libary dataset (%s) has been made publicly accessible." % ldda_name + self.check_page_for_string( check_str ) # Library folder stuff def add_folder( self, cntrller, library_id, folder_id, name='Folder One', description='This is Folder One' ): """Create a new folder""" - self.home() url = "%s/library_common/create_folder?cntrller=%s&library_id=%s&parent_id=%s" % ( self.url, cntrller, library_id, folder_id ) self.visit_url( url ) self.check_page_for_string( 'Create a new folder' ) @@ -2049,7 +2069,19 @@ class TwillTestCase( unittest.TestCase ): tc.fv( "1", template_field_name1, template_field_contents1 ) tc.submit( "runtool_btn" ) if check_str_after_submit: - self.check_page_for_string( check_str_after_submit ) + try: + self.check_page_for_string( check_str_after_submit ) + except: + self.library_wait( library_id ) + try: + self.check_page_for_string( check_str_after_submit ) + except: + self.library_wait( library_id ) + try: + self.check_page_for_string( check_str_after_submit ) + except: + self.library_wait( library_id ) + self.check_page_for_string( check_str_after_submit ) self.library_wait( library_id ) self.home() def act_on_multiple_datasets( self, cntrller, library_id, do_action, ldda_ids='', check_str1='' ): diff --git a/test/functional/test_library_features.py b/test/functional/test_library_features.py index 23c1c7ea8b9..d5ff03e9fa8 100644 --- a/test/functional/test_library_features.py +++ b/test/functional/test_library_features.py @@ -276,6 +276,17 @@ class TestLibraryFeatures( TwillTestCase ): # logged in as regular_user3 self.logout() self.login( email=admin_user.email ) + self.add_library_dataset( 'library_admin', + '1.bed', + self.security.encode_id( library_one.id ), + self.security.encode_id( library_one.root_folder.id ), + library_one.root_folder.name, + file_type='bed', + dbkey='hg18', + root=True ) + global ldda_one + ldda_one = get_latest_ldda() + assert ldda_one is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_one from the database' for format in ( 'tbz', 'tgz', 'zip' ): archive = self.download_archive_of_library_files( cntrller='library', library_id=self.security.encode_id( library_one.id ), diff --git a/test/functional/test_library_security.py b/test/functional/test_library_security.py index 25716a3eec1..08ae8b549fb 100644 --- a/test/functional/test_library_security.py +++ b/test/functional/test_library_security.py @@ -35,175 +35,175 @@ class TestLibrarySecurity( TwillTestCase ): def test_005_create_required_groups_and_roles( self ): """Testing creating all required groups and roles for this script""" # Logged in as admin_user - # Create role_one - name = 'library security Role One' - description = "library security This is Role One's description" - user_ids = [ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ] + # Create Role1: admin_user, regular_user1, regular_user3 + name = 'Role1' + description = "Role1 description" self.create_role( name=name, description=description, - in_user_ids=user_ids, + in_user_ids=[ str( admin_user.id ), str( regular_user1.id ), str( regular_user3.id ) ], in_group_ids=[], create_group_for_role='no', private_role=admin_user.email ) - # Get the role object for later tests - global role_one - role_one = get_role_by_name( name ) - # Create group_one - name = 'Group One' - self.create_group( name=name, in_user_ids=[ str( regular_user1.id ) ], in_role_ids=[ str( role_one.id ) ] ) - # Get the group object for later tests - global group_one - group_one = get_group_by_name( name ) - assert group_one is not None, 'Problem retrieving group named "Group One" from the database' + global role1 + role1 = get_role_by_name( name ) + # Create Group1: regular_user1, admin_user, regular_user3 + name = 'Group1' + self.create_group( name=name, in_user_ids=[ str( regular_user1.id ) ], in_role_ids=[ str( role1.id ) ] ) + global group1 + group1 = get_group_by_name( name ) + assert group1 is not None, 'Problem retrieving group named "Group1" from the database' # NOTE: To get this to work with twill, all select lists on the ~/admin/role page must contain at least # 1 option value or twill throws an exception, which is: ParseError: OPTION outside of SELECT # Due to this bug in twill, we create the role, we bypass the page and visit the URL in the # associate_users_and_groups_with_role() method. # - #create role_two - name = 'library security Role Two' - description = 'library security This is Role Two' - user_ids = [ str( admin_user.id ) ] - group_ids = [ str( group_one.id ) ] + #create Role2: admin_user, regular_user1, regular_user3 + name = 'Role2' + description = 'Role2 description' private_role = admin_user.email self.create_role( name=name, description=description, - in_user_ids=user_ids, - in_group_ids=group_ids, + in_user_ids=[ str( admin_user.id ) ], + in_group_ids=[ str( group1.id ) ], private_role=private_role ) - # Get the role object for later tests - global role_two - role_two = get_role_by_name( name ) - assert role_two is not None, 'Problem retrieving role named "Role Two" from the database' - def test_010_create_library( self ): - """Testing creating a new library, then renaming it""" + global role2 + role2 = get_role_by_name( name ) + assert role2 is not None, 'Problem retrieving role named "Role2" from the database' + def test_010_create_libraries( self ): + """Creating new libraries used in this script""" # Logged in as admin_user - name = "library security Library1" - description = "library security Library1 description" - synopsis = "library security Library1 synopsis" - self.create_library( name=name, description=description, synopsis=synopsis ) - # Get the library object for later tests - global library_one - library_one = get_library( name, description, synopsis ) - assert library_one is not None, 'Problem retrieving library named "%s" from the database' % name - # 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 + for index in range( 0, 2 ): + name = 'library%s' % str( index + 1 ) + description = '%s description' % name + synopsis = '%s synopsis' % name + self.create_library( name=name, description=description, synopsis=synopsis ) + # Get the libraries for later use + global library1 + library1 = get_library( 'library1', 'library1 description', 'library1 synopsis' ) + assert library1 is not None, 'Problem retrieving library (library1) from the database' + global library2 + library2 = get_library( 'library2', 'library2 description', 'library2 synopsis' ) + assert library2 is not None, 'Problem retrieving library (library2) from the database' + def test_015_restrict_access_to_library1( self ): + """Testing restricting access to library1""" + # Logged in as admin_user + # Make sure library1 is public + assert 'access library' not in [ a.action for a in library1.actions ], 'Library %s is not public when first created' % library1.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 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 ), + # Role1 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 library1 and it's contents. + self.library_permissions( self.security.encode_id( library1.id ), + library1.name, + str( role1.id ), permissions_in, 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 ) + self.check_page_for_string( library1.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 ) + self.check_page_for_string( library1.name ) + raise AssertionError, 'Library %s is accessible by %s when it should be restricted' % ( library1.name, regular_user2.email ) except: pass self.logout() self.login( email=admin_user.email ) - def test_015_add_new_folder_to_root_folder( self ): - """Testing adding a folder to a library root folder""" + def test_020_add_folder_to_library1( self ): + """Testing adding a folder1 to a library1""" # logged in as admin_user - root_folder = library_one.root_folder - name = "Root Folder's Folder One" - description = "This is the root folder's Folder One" + root_folder = library1.root_folder + name = "Folder1" + description = "Folder1 description" self.add_folder( 'library_admin', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), self.security.encode_id( root_folder.id ), name=name, description=description ) - global folder_one - folder_one = get_folder( root_folder.id, name, description ) - assert folder_one is not None, 'Problem retrieving library folder named "%s" from the database' % name - def test_020_add_dataset_with_private_role_restriction_to_folder( self ): - """Testing adding a dataset with a private role restriction to a folder""" + global folder1 + folder1 = get_folder( root_folder.id, name, description ) + assert folder1 is not None, 'Problem retrieving folder1 from the database' + def test_025_create_ldda1_with_private_role_restriction( self ): + """Testing create ldda1 with a private role restriction""" # Logged in as admin_user # - # Keep in mind that # LIBRARY_ACCESS = "Role One" on the whole library + # Library1 LIBRARY_ACCESS = Role1: admin_user, regular_user1, regular_user3 # # 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 - # LIBRARY_ADD = "Role One" via inheritance from parent folder - # LIBRARY_MODIFY = "Role One" via inheritance from parent folder - # LIBRARY_MANAGE = "Role One" via inheritance from parent folder - # "Role One" members are: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu - # This means that only user test1@bx.psu.edu can see the dataset from the Libraries view - message ='This is a test of the fourth dataset uploaded' + # DATASET_MANAGE_PERMISSIONS = admin_user via DefaultUserPermissions + # DATASET_ACCESS = regular_user1 private role via this test method + # LIBRARY_ADD = "Role1" via inheritance from parent folder + # LIBRARY_MODIFY = "Role1" via inheritance from parent folder + # LIBRARY_MANAGE = "Role1" via inheritance from parent folder + # + # This means that only regular_user1 can see the dataset from the Data Libraries view + message ='ldda1' self.add_library_dataset( 'library_admin', '1.bed', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), - folder_one.name, + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + folder1.name, file_type='bed', dbkey='hg18', roles=[ str( regular_user1_private_role.id ) ], - message=message.replace( ' ', '+' ), + message=message, root=False ) - global ldda_one - ldda_one = get_latest_ldda() - assert ldda_one is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_one from the database' + global ldda1 + ldda1 = get_latest_ldda() + assert ldda1 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda1 from the database' self.browse_library( 'library_admin', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), check_str1='1.bed', check_str2=message, check_str3=admin_user.email ) - def test_025_accessing_dataset_with_private_role_restriction( self ): - """Testing accessing a dataset with a private role restriction""" + def test_030_access_ldda1_with_private_role_restriction( self ): + """Testing accessing ldda1 with a private role restriction""" # Logged in as admin_user # - # 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 = Role1: 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 + # 'Role1' since the LIBRARY_ACCESS permission is associated with Role1. # Role one members are: admin_user, regular_user1, regular_user3. + # 'test@bx.psu.edu' ( admin_user's private role ) since admin_user has Role1 + # 'Role2' since admin_user has Role2 # '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 + # 'test1@bx.psu.edu' ( regular_user1's private role ) since regular_user1 has Role1 + # 'test3@bx.psu.edu' ( regular_user3's private role ) since regular_user3 has Role1 # # admin_user should not be able to see 1.bed from the analysis view's access libraries self.browse_library( 'library', - self.security.encode_id( library_one.id ), - not_displayed=folder_one.name, + self.security.encode_id( library1.id ), + not_displayed=folder1.name, not_displayed2='1.bed' ) self.logout() - # regular_user1 should be able to see 1.bed from the analysis view's access librarys + # regular_user1 should be able to see 1.bed from the Data Libraries view # since it was associated with regular_user1's private role self.login( email=regular_user1.email ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - check_str1=folder_one.name, + self.security.encode_id( library1.id ), + check_str1=folder1.name, check_str2='1.bed' ) self.logout() - # regular_user2 should not be to see the library since they do not have - # Role One which is associated with the LIBRARY_ACCESS permission + # regular_user2 should not be to see library1 since they do not have + # Role1 which is associated with the LIBRARY_ACCESS permission self.login( email=regular_user2.email ) - self.browse_libraries_regular_user( check_str1="No Items" ) + self.browse_libraries_regular_user( not_displayed1=library1.name ) self.logout() # regular_user3 should not be able to see 1.bed from the analysis view's access librarys self.login( email=regular_user3.email ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - not_displayed=folder_one.name, + self.security.encode_id( library1.id ), + not_displayed=folder1.name, not_displayed2='1.bed' ) self.logout() self.login( email=admin_user.email ) - def test_030_change_dataset_access_permission( self ): - """Testing changing the access permission on a dataset with a private role restriction""" + def test_035_change_ldda1_access_permission( self ): + """Testing changing the access permission on ldda1 with a private role restriction""" # Logged in as admin_user # We need admin_user to be able to access 1.bed permissions_in = [ k for k, v in galaxy.model.Dataset.permitted_actions.items() ] @@ -213,146 +213,165 @@ class TestLibrarySecurity( TwillTestCase ): permissions_out = [] # Attempt to associate multiple roles with the library dataset, with one of the # roles being private. - role_ids_str = '%s,%s' % ( str( role_one.id ), str( admin_user_private_role.id ) ) + role_ids_str = '%s,%s' % ( str( role1.id ), str( admin_user_private_role.id ) ) check_str = "At least 1 user must have every role associated with accessing datasets. " check_str += "Since you are associating more than 1 role, no private roles are allowed." self.ldda_permissions( 'library_admin', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), - self.security.encode_id( ldda_one.id ), + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + self.security.encode_id( ldda1.id ), role_ids_str, permissions_in, permissions_out, check_str1=check_str ) - role_ids_str = str( role_one.id ) + role_ids_str = str( role1.id ) self.ldda_permissions( 'library_admin', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), - self.security.encode_id( ldda_one.id ), + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + self.security.encode_id( ldda1.id ), role_ids_str, permissions_in, permissions_out, - ldda_name=ldda_one.name ) + ldda_name=ldda1.name ) # admin_user should now be able to see 1.bed from the analysis view's access libraries self.browse_library( 'library', - self.security.encode_id( library_one.id ), - check_str1=ldda_one.name ) - def test_035_add_dataset_with_role_associated_with_group_and_users( self ): - """Testing adding a dataset with a role that is associated with a group and users""" + self.security.encode_id( library1.id ), + check_str1=ldda1.name ) + def test_040_create_ldda2_with_role2_associated_with_group_and_users( self ): + """Testing creating ldda2 with a role that is associated with a group and users""" # Logged in as admin_user - # Add a dataset restricted by role_two, which is currently associated as follows: - # groups: group_one - # users: test@bx.psu.edu, test1@bx.psu.edu via group_one + # Add a dataset restricted by role2, which is currently associated as follows: + # groups: group1 + # users: test@bx.psu.edu, test1@bx.psu.edu via group1 # - # 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 ) - refresh( library_one ) - message = 'Testing adding a dataset with a role that is associated with a group and users' + # We first need to make library1 public, but leave it's contents permissions unchanged + self.make_library_item_public( self.security.encode_id( library1.id ), + self.security.encode_id( library1.id ), + item_type='library', + contents=False, + library_name=library1.name ) + refresh( library1 ) + message = 'ldda2: a dataset with role2 that is associated with a group and users' self.add_library_dataset( 'library_admin', '2.bed', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), - folder_one.name, + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + folder1.name, file_type='bed', dbkey='hg17', - roles=[ str( role_two.id ) ], + roles=[ str( role2.id ) ], message=message.replace( ' ', '+' ), root=False ) - global ldda_two - ldda_two = get_latest_ldda() - assert ldda_two is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda_two from the database' + global ldda2 + ldda2 = get_latest_ldda() + assert ldda2 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda2 from the database' self.browse_library( 'library', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), check_str1='2.bed', check_str2=message, check_str3=admin_user.email ) - def test_040_accessing_dataset_with_role_associated_with_group_and_users( self ): - """Testing accessing a dataset with a role that is associated with a group and users""" + def test_045_accessing_ldda2_with_role_associated_with_group_and_users( self ): + """Testing accessing ldda2 with a role that is associated with a group and users""" # Logged in as admin_user - # admin_user should be able to see 2.bed since she is associated with role_two + # admin_user should be able to see 2.bed since she is associated with role2 self.browse_library( 'library', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), check_str1='2.bed', check_str2=admin_user.email ) self.logout() # regular_user1 should be able to see 2.bed since she is associated with group_two self.login( email = 'test1@bx.psu.edu' ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - check_str1=folder_one.name, + self.security.encode_id( library1.id ), + check_str1=folder1.name, check_str2='2.bed', check_str3=admin_user.email ) # Check the permissions on the dataset 2.bed - they are as folows: # DATASET_MANAGE_PERMISSIONS = test@bx.psu.edu - # DATASET_ACCESS = Role Two - # Role Two associations: test@bx.psu.edu and Group Two - # Group Two members: Role One, Role Two, test1@bx.psu.edu - # Role One associations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu - # LIBRARY_ADD = Role One - # Role One aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu - # LIBRARY_MODIFY = Role One - # Role One aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu - # LIBRARY_MANAGE = Role One - # Role One aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu + # DATASET_ACCESS = Role2 + # Role2 associations: test@bx.psu.edu and Group2 + # Group2 members: Role1, Role2, test1@bx.psu.edu + # Role1 associations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu + # LIBRARY_ADD = Role1 + # Role1 aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu + # LIBRARY_MODIFY = Role1 + # Role1 aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu + # LIBRARY_MANAGE = Role1 + # Role1 aassociations: test@bx.psu.edu, test1@bx.psu.edu, test3@bx.psu.edu self.ldda_edit_info( 'library', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), - self.security.encode_id( ldda_two.id ), - ldda_two.name, + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + self.security.encode_id( ldda2.id ), + ldda2.name, check_str1='2.bed', check_str2='This is the latest version of this library dataset', check_str3='Edit attributes of 2.bed' ) self.act_on_multiple_datasets( 'library', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), 'import_to_history', - ldda_ids=self.security.encode_id( ldda_two.id ), + ldda_ids=self.security.encode_id( ldda2.id ), check_str1='1 dataset(s) have been imported into your history' ) self.logout() - # regular_user2 should not be able to see 2.bed - self.login( email = 'test2@bx.psu.edu' ) + # regular_user2 should not be able to see ldda2 + self.login( email=regular_user2.email ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - not_displayed=folder_one.name, - not_displayed2='2.bed' ) + self.security.encode_id( library1.id ), + not_displayed=folder1.name, + not_displayed2=ldda2.name ) self.logout() - # regular_user3 should not be able to see folder_one ( even though it does not contain any datasets that she - # can access ) since she has Role One, and Role One has all library permissions ( see above ). - self.login( email = 'test3@bx.psu.edu' ) + # regular_user3 should not be able to see ldda2 + self.login( email=regular_user3.email ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - check_str1=folder_one.name, - not_displayed='2.bed' ) + self.security.encode_id( library1.id ), + check_str1=folder1.name, + not_displayed=ldda2.name ) self.logout() - self.login( email='test@bx.psu.edu' ) - def test_045_upload_directory_of_files_from_admin_view( self ): - """Testing uploading a directory of files to a root folder from the Admin view""" + self.login( email=admin_user.email ) + # Now makse ldda2 publicly accessible + self.make_library_item_public( self.security.encode_id( library1.id ), + self.security.encode_id( ldda2.id ), + item_type='ldda', + ldda_name=ldda2.name ) + self.logout() + # regular_user2 should now be able to see ldda2 + self.login( email=regular_user2.email ) + self.browse_library( 'library', + self.security.encode_id( library1.id ), + check_str1=folder1.name, + check_str2=ldda2.name ) + self.logout() + self.login( email=admin_user.email ) + # Now make folder1 publicly acessible + self.make_library_item_public( self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), + item_type='folder', + folder_name=folder1.name ) + self.logout() + # regular_user3 should now be able to see ldda1 + self.login( email=regular_user3.email ) + self.browse_library( 'library', + self.security.encode_id( library1.id ), + check_str1=folder1.name, + check_str2=ldda1.name ) + self.logout() + self.login( email=admin_user.email ) + def test_050_upload_directory_of_files_from_admin_view( self ): + """Testing uploading a directory of files to library1 from the Admin view""" # logged in as admin_user message = 'This is a test for uploading a directory of files' - check_str_after_submit="Added 3 datasets to the library '%s' (each is selected)." % library_one.root_folder.name + check_str_after_submit="Added 3 datasets to the library '%s' (each is selected)." % library1.root_folder.name self.upload_directory_of_files( 'library_admin', - self.security.encode_id( library_one.id ), - self.security.encode_id( library_one.root_folder.id ), + self.security.encode_id( library1.id ), + self.security.encode_id( library1.root_folder.id ), server_dir='library', message=message, check_str_after_submit=check_str_after_submit ) self.browse_library( 'library_admin', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), check_str1=admin_user.email, check_str2=message ) - def test_050_change_permissions_on_datasets_uploaded_from_library_dir( self ): + def test_055_change_permissions_on_datasets_uploaded_from_library_dir( self ): """Testing changing the permissions on datasets uploaded from a directory from the Admin view""" # logged in as admin_user # It would be nice if twill functioned such that the above test resulted in a @@ -366,10 +385,10 @@ class TestLibrarySecurity( TwillTestCase ): ldda_ids = ldda_ids.rstrip( ',' ) # Set permissions self.ldda_permissions( 'library_admin', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), ldda_ids, - str( role_one.id ), + str( role1.id ), permissions_in=[ 'DATASET_ACCESS', 'LIBRARY_MANAGE' ], check_str1='Permissions updated for 3 datasets.' ) # Make sure the permissions have been correctly updated for the 3 datasets. Permissions should @@ -379,7 +398,7 @@ class TestLibrarySecurity( TwillTestCase ): for ldda in lddas: # Import each library dataset into our history self.act_on_multiple_datasets( 'library', - self.security.encode_id( library_one.id ), + self.security.encode_id( library1.id ), 'import_to_history', ldda_ids=self.security.encode_id( ldda.id ) ) # Determine the new HistoryDatasetAssociation id created when the library dataset was imported into our history @@ -389,34 +408,34 @@ class TestLibrarySecurity( TwillTestCase ): check_str2=check_str2, check_str3=check_str3, check_str4=check_str4 ) - # admin_user is associated with role_one, so should have all permissions on imported datasets + # admin_user is associated with role1, so should have all permissions on imported datasets check_edit_page( latest_3_lddas, check_str1='Manage dataset permissions on', check_str2='Role members can manage the roles associated with permissions on this dataset', check_str3='Role members can import this dataset into their history for analysis' ) self.logout() - # regular_user1 is associated with role_one, so should have all permissions on imported datasets - self.login( email='test1@bx.psu.edu' ) + # regular_user1 is associated with role1, so should have all permissions on imported datasets + self.login( email=regular_user1.email ) check_edit_page( latest_3_lddas ) self.logout() - # Since regular_user2 is not associated with role_one, she should not have - # access to any of the 3 datasets, so she will not see folder_one on the libraries page - self.login( email='test2@bx.psu.edu' ) + # Since regular_user2 is not associated with role1, she should not have + # access to any of the 3 datasets, so she will not see folder1 on the libraries page + self.login( email=regular_user2.email ) self.browse_library( 'library', - self.security.encode_id( library_one.id ), - not_displayed=folder_one.name ) + self.security.encode_id( library1.id ), + not_displayed=folder1.name ) self.logout() - # regular_user3 is associated with role_one, so should have all permissions on imported datasets - self.login( email='test3@bx.psu.edu' ) + # regular_user3 is associated with role1, so should have all permissions on imported datasets + self.login( email=regular_user3.email ) check_edit_page( latest_3_lddas ) self.logout() - self.login( email='test@bx.psu.edu' ) + self.login( email=admin_user.email ) # Change the permissions and test again self.ldda_permissions( 'library_admin', - self.security.encode_id( library_one.id ), - self.security.encode_id( folder_one.id ), + self.security.encode_id( library1.id ), + self.security.encode_id( folder1.id ), ldda_ids, - str( role_one.id ), + str( role1.id ), permissions_in=[ 'DATASET_ACCESS' ], check_str1='Permissions updated for 3 datasets.' ) check_edit_page( latest_3_lddas, @@ -424,152 +443,131 @@ class TestLibrarySecurity( TwillTestCase ): not_displayed1='Manage dataset permissions on', not_displayed2='Role members can manage roles associated with permissions on this library item', not_displayed3='Role members can import this dataset into their history for analysis' ) - def test_055_library_permissions( self ): - """Test library permissions""" + def test_060_restrict_access_to_library2( self ): + """Testing restricting access to library2""" # Logged in as admin_user - form_name = 'Library template Form One' - form_desc = 'This is Form One' - form_type = galaxy.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE - # Create form for library template - self.create_form( name=form_name, desc=form_desc, formtype=form_type ) - global form_one - form_one = get_form( form_name ) - assert form_one is not None, 'Problem retrieving form named (%s) from the database' % form_name - # Make sure the template fields are displayed on the library information page - field_dict = form_one.fields[ 0 ] - global form_one_field_label - form_one_field_label = '%s' % str( field_dict.get( 'label', 'Field 0' ) ) - global form_one_field_help - form_one_field_help = '%s' % str( field_dict.get( 'helptext', 'Field 0 help' ) ) - global form_one_field_required - form_one_field_required = '%s' % str( field_dict.get( 'required', 'optional' ) ).capitalize() - # Add information to the library using the template - global form_one_field_name - form_one_field_name = 'field_0' - # Create a library, adding no template - name = "library security Library Two" - description = "library security This is Library Two" - synopsis = "library security Library Two synopsis" - self.create_library( name=name, description=description, synopsis=synopsis ) - self.browse_libraries_admin( check_str1=name, check_str2=description ) - global library_two - library_two = get_library( name, description, synopsis ) - assert library_two is not None, 'Problem retrieving library named "%s" from the database' % name - # Set library permissions for regular_user1 and regular_user2. Each of these users will be permitted to - # LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE for library items. + # Make sure library2 is public + assert 'access library' not in [ a.action for a in library2.actions ], 'Library %s is not public when first created' % library2.name + # Set permissions on the library2 permissions_in = [ k for k, v in galaxy.model.Library.permitted_actions.items() ] permissions_out = [] - role_ids_str = '%s,%s' % ( str( regular_user1_private_role.id ), str( regular_user2_private_role.id ) ) - self.library_permissions( self.security.encode_id( library_two.id ), - library_two.name, - role_ids_str, + # Only admin_user will be permitted for + # LIBRARY_ACCESS, LIBRARY_ADD, LIBRARY_MODIFY, LIBRARY_MANAGE on library2 and it's contents. + self.library_permissions( self.security.encode_id( library1.id ), + library1.name, + str( admin_user_private_role.id ), permissions_in, permissions_out ) + # Make sure library2 is not accessible by regular_user2. self.logout() - # Login as regular_user1 and make sure they can see the library - self.login( email=regular_user1.email ) - self.browse_libraries_regular_user( check_str1=name ) - self.logout() - # Login as regular_user2 and make sure they can see the library self.login( email=regular_user2.email ) - self.browse_libraries_regular_user( check_str1=name ) - # Add a dataset to the library - message = 'Testing adding 1.bed to Library Two root folder' - self.add_library_dataset( 'library', - '1.bed', - self.security.encode_id( library_two.id ), - self.security.encode_id( library_two.root_folder.id ), - library_two.root_folder.name, + self.visit_url( '%s/library/browse_libraries' % self.url ) + try: + self.check_page_for_string( library2.name ) + raise AssertionError, 'Library %s is accessible by %s when it should be restricted' % ( library2.name, regular_user2.email ) + except: + pass + self.logout() + self.login( email=admin_user.email ) + def test_065_create_ldda6( self ): + """Testing create ldda6, restricting access on upload form to admin_user's private role""" + self.add_library_dataset( 'library_admin', + '6.bed', + self.security.encode_id( library2.id ), + self.security.encode_id( library2.root_folder.id ), + library2.root_folder.name, file_type='bed', dbkey='hg18', - message=message, - root=True ) - # Add a folder to the library - name = "Root Folder's Folder X" - description = "This is the root folder's Folder X" - self.add_folder( 'library', - self.security.encode_id( library_two.id ), - self.security.encode_id( library_two.root_folder.id ), + roles=[ str( admin_user_private_role.id ) ], + message='ldda6', + root=False ) + global ldda6 + ldda6 = get_latest_ldda() + assert ldda6 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda6 from the database' + def test_070_add_folder2_to_library2( self ): + """Testing adding folder2 to a library2""" + # logged in as admin_user + root_folder = library2.root_folder + name = "Folder2" + description = "Folder2 description" + self.add_folder( 'library_admin', + self.security.encode_id( library2.id ), + self.security.encode_id( root_folder.id ), name=name, description=description ) - global folder_x - folder_x = get_folder( library_two.root_folder.id, name, description ) - # Add an information template to the folder - template_name = 'Folder Template 1' - self.add_library_template( 'library', - 'folder', - self.security.encode_id( library_one.id ), - self.security.encode_id( form_one.id ), - form_one.name, - folder_id=self.security.encode_id( folder_x.id ) ) - # Modify the folder's information - contents = '%s folder contents' % form_one_field_label - new_name = "Root Folder's Folder Y" - new_description = "This is the root folder's Folder Y" - self.folder_info( 'library', - self.security.encode_id( folder_x.id ), - self.security.encode_id( library_two.id ), - name, - new_name, - new_description, - contents=contents, - field_name=form_one_field_name ) - # Twill barfs when self.check_page_for_string() is called after dealing with an information template, - # the exception is: TypeError: 'str' object is not callable - # the work-around it to end this method so any calls are in the next method. - def test_060_template_features_and_permissions( self ): - """Test library template and more permissions behavior from the Data Libraries view""" - # Logged in as regular_user2 - refresh( folder_x ) - # Add a dataset to the folder - message = 'Testing adding 2.bed to Library Three root folder' - self.add_library_dataset( 'library', - '2.bed', - self.security.encode_id( library_two.id ), - self.security.encode_id( folder_x.id ), - folder_x.name, + global folder2 + folder2 = get_folder( root_folder.id, name, description ) + assert folder2 is not None, 'Problem retrieving folder2 from the database' + def test_075_create_ldda7( self ): + """Testing create ldda7, restricting access on upload form to admin_user's private role""" + self.add_library_dataset( 'library_admin', + '7.bed', + self.security.encode_id( library2.id ), + self.security.encode_id( folder2.id ), + folder2.name, file_type='bed', dbkey='hg18', - message=message.replace( ' ', '+' ), + roles=[ str( admin_user_private_role.id ) ], + message='ldda7', root=False ) - global ldda_x - ldda_x = get_latest_ldda() - assert ldda_x is not None, 'Problem retrieving ldda_x from the database' - # Add an information template to the library - template_name = 'Library Template 3' - self.add_library_template( 'library', - 'library', - self.security.encode_id( library_two.id ), - self.security.encode_id( form_one.id ), - form_one.name ) - # Add information to the library using the template - contents = '%s library contents' % form_one_field_label - self.visit_url( '%s/library_common/library_info?cntrller=library&id=%s' % ( self.url, self.security.encode_id( library_two.id ) ) ) - # There are 2 forms on this page and the template is the 2nd form - tc.fv( '2', form_one_field_name, contents ) - tc.submit( 'edit_info_button' ) - # For some reason, the following check: - # self.check_page_for_string ( 'The information has been updated.' ) - # ...throws the following exception - I have not idea why! - # TypeError: 'str' object is not callable - # The work-around is to not make ANY self.check_page_for_string() calls until the next method - def test_065_permissions_as_different_regular_user( self ): - """Test library template and more permissions behavior from the Data Libraries view as a different user""" - # Logged in as regular_user2 + global ldda7 + ldda7 = get_latest_ldda() + assert ldda7 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda7 from the database' + def test_080_add_subfolder2_to_folder2( self ): + """Testing adding subfolder2 to a folder2""" + # logged in as admin_user + name = "Subfolder2" + description = "Subfolder2 description" + self.add_folder( 'library_admin', + self.security.encode_id( library2.id ), + self.security.encode_id( folder2.id ), + name=name, + description=description ) + global subfolder2 + subfolder2 = get_folder( folder2.id, name, description ) + assert subfolder2 is not None, 'Problem retrieving subfolder2 from the database' + def test_085_create_ldda8( self ): + """Testing create ldda8, restricting access on upload form to admin_user's private role""" + self.add_library_dataset( 'library_admin', + '8.bed', + self.security.encode_id( library2.id ), + self.security.encode_id( subfolder2.id ), + subfolder2.name, + file_type='bed', + dbkey='hg18', + roles=[ str( admin_user_private_role.id ) ], + message='ldda8', + root=False ) + global ldda8 + ldda8 = get_latest_ldda() + assert ldda8 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda8 from the database' + def test_090_make_library2_and_contents_public( self ): + """Testing making library2 and all of it's contetns public""" + self.make_library_item_public( self.security.encode_id( library2.id ), + self.security.encode_id( library2.id ), + item_type='library', + contents=True, + library_name=library2.name ) + # Make sure library2 is now accessible by regular_user2 self.logout() - self.login( email=regular_user1.email ) + self.login( email=regular_user2.email ) + self.visit_url( '%s/library/browse_libraries' % self.url ) + self.check_page_for_string( library2.name ) self.browse_library( 'library', - self.security.encode_id( library_two.id ), - check_str1=ldda_x.name ) + self.security.encode_id( library2.id ), + check_str1=ldda6.name, + check_str2=ldda7.name, + check_str3=ldda8.name ) def test_999_reset_data_for_later_test_runs( self ): """Reseting data to enable later test runs to pass""" - # Logged in as regular_user1 + """ + # Logged in as regular_user2 self.logout() self.login( email=admin_user.email ) ################## # Purge all libraries ################## - for library in [ library_one, library_two ]: + for library in [ library1, library2 ]: self.delete_library_item( 'library_admin', self.security.encode_id( library.id ), self.security.encode_id( library.id ), @@ -579,7 +577,7 @@ class TestLibrarySecurity( TwillTestCase ): ################## # Eliminate all non-private roles ################## - for role in [ role_one, role_two ]: + for role in [ role1, role2 ]: self.mark_role_deleted( self.security.encode_id( role.id ), role.name ) self.purge_role( self.security.encode_id( role.id ), role.name ) # Manually delete the role from the database @@ -589,7 +587,7 @@ class TestLibrarySecurity( TwillTestCase ): ################## # Eliminate all groups ################## - for group in [ group_one ]: + for group in [ group1 ]: self.mark_group_deleted( self.security.encode_id( group.id ), group.name ) self.purge_group( self.security.encode_id( group.id ), group.name ) # Manually delete the group from the database @@ -603,3 +601,4 @@ class TestLibrarySecurity( TwillTestCase ): refresh( user ) if len( user.roles) != 1: raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) ) + """