Many history-related feature enhancements, some fixes and enhanced functional tests:

- history sharing is now modeled after workflow sharing - fixes ticket # 63.
- all history features pass encoded history ids between requests
- new, empty histories are no longer created when a user logs in, instead their last accessed history is displayed
- some other things I'm forgetting, I'm sure
This commit also includes a fix for remote user authentication where private roles and default permissions were not created for users ( Ross's and Assaf's issues ).
Many functional test enhancements.
This commit is contained in:
Greg Von Kuster
2009-06-29 16:30:16 -04:00
parent 93d484355b
commit ca6ba6e011
29 changed files with 1478 additions and 734 deletions
+19 -13
View File
@@ -214,22 +214,29 @@ class History( object ):
if genome_build not in [None, '?']:
self.genome_build = genome_build
self.datasets.append( dataset )
def copy( self, target_user = None ):
def copy( self, name=None, target_user=None ):
if not name:
name = self.name
if not target_user:
target_user = self.user
des = History( user = target_user )
des.flush()
des.name = self.name
new_history = History( name=name, user=target_user )
new_history.flush()
for data in self.datasets:
new_data = data.copy( copy_children = True, target_history = des )
des.add_dataset( new_data, set_hid = False )
new_data = data.copy( copy_children=True, target_history=new_history )
new_history.add_dataset( new_data, set_hid = False )
new_data.flush()
des.hid_counter = self.hid_counter
des.flush()
return des
new_history.hid_counter = self.hid_counter
new_history.flush()
return new_history
@property
def activatable_datasets( self ):
return [ hda for hda in self.datasets if not hda.dataset.deleted ] #this needs to be a list
# This needs to be a list
return [ hda for hda in self.datasets if not hda.dataset.deleted ]
class HistoryUserShareAssociation( object ):
def __init__( self ):
self.history = None
self.user = None
class UserRoleAssociation( object ):
def __init__( self, user, role ):
@@ -988,7 +995,7 @@ class GalaxySession( object ):
remote_host=None,
remote_addr=None,
referer=None,
current_history_id=None,
current_history=None,
session_key=None,
is_valid=False,
prev_session_id=None ):
@@ -997,12 +1004,11 @@ class GalaxySession( object ):
self.remote_host = remote_host
self.remote_addr = remote_addr
self.referer = referer
self.current_history_id = current_history_id
self.current_history = current_history
self.session_key = session_key
self.is_valid = is_valid
self.prev_session_id = prev_session_id
self.histories = []
def add_history( self, history, association=None ):
if association is None:
self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
+13 -1
View File
@@ -56,7 +56,14 @@ History.table = Table( "history", metadata,
Column( "hid_counter", Integer, default=1 ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ),
Column( "genome_build", TrimmedString( 40 ) ) )
Column( "genome_build", TrimmedString( 40 ) ),
Column( "importable", Boolean, default=False ) )
HistoryUserShareAssociation.table = Table( "history_user_share_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True )
)
HistoryDatasetAssociation.table = Table( "history_dataset_association", metadata,
Column( "id", Integer, primary_key=True ),
@@ -575,6 +582,11 @@ assign_mapper( context, History, History.table,
active_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & ( not_( HistoryDatasetAssociation.table.c.deleted ) ) ), order_by=asc( HistoryDatasetAssociation.table.c.hid ), lazy=False, viewonly=True )
) )
assign_mapper( context, HistoryUserShareAssociation, HistoryUserShareAssociation.table,
properties=dict( user=relation( User, backref='histories_shared_by_others' ),
history=relation( History, backref='users_shared_with' )
) )
assign_mapper( context, User, User.table,
properties=dict( histories=relation( History, backref="user",
order_by=desc(History.table.c.update_time) ),
@@ -0,0 +1,59 @@
from sqlalchemy import *
from migrate import *
import datetime
now = datetime.datetime.utcnow
# Need our custom types, but don't import anything else from model
from galaxy.model.custom_types import *
metadata = MetaData( migrate_engine )
HistoryUserShareAssociation_table = Table( "history_user_share_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True )
)
def upgrade():
# Load existing tables
metadata.reflect()
# Create the history_user_share_association table
try:
HistoryUserShareAssociation_table.create()
except Exception, e:
log.debug( "Creating history_user_share_association table failed: %s" % str( e ) )
# Add 1 column to the history table
try:
History_table = Table( "history", metadata, autoload=True )
except NoSuchTableError:
History_table = None
log.debug( "Failed loading table history" )
if History_table:
try:
col = Column( 'importable', Boolean, index=True, default=False )
col.create( History_table )
assert col is History_table.c.importable
except Exception, e:
log.debug( "Adding column 'importable' to history table failed: %s" % ( str( e ) ) )
def downgrade():
# Load existing tables
metadata.reflect()
# Drop 1 column from the history table
try:
History_table = Table( "history", metadata, autoload=True )
except NoSuchTableError:
History_table = None
log.debug( "Failed loading table history" )
if History_table:
try:
col = History_table.c.importable
col.drop()
except Exception, e:
log.debug( "Dropping column 'importable' from history table failed: %s" % ( str( e ) ) )
# Drop the history_user_share_association table
try:
HistoryUserShareAssociation_table.drop()
except Exception, e:
log.debug( "Dropping history_user_share_association table failed: %s" % str( e ) )
+4 -1
View File
@@ -275,6 +275,8 @@ class GalaxyRBACAgent( RBACAgent ):
def set_all_dataset_permissions( self, dataset, permissions={} ):
# Set new permissions on a dataset, eliminating all current permissions
# Delete all of the current permissions on the dataset
# TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset,
# or the dataset is inaccessible. See admin/library_dataset_dataset_association()
for dp in dataset.actions:
dp.delete()
dp.flush()
@@ -285,8 +287,9 @@ class GalaxyRBACAgent( RBACAgent ):
for dp in [ self.model.DatasetPermissions( action, dataset, role ) for role in roles ]:
dp.flush()
def set_dataset_permission( self, dataset, permission={} ):
# TODO: is this method needed - see above method
# Set a specific permission on a dataset, leaving all other current permissions on the dataset alone
# TODO: If setting ACCESS permission, at least 1 user must have every role associated with this dataset,
# or the dataset is inaccessible. See admin/library_dataset_dataset_association()
for action, roles in permission.items():
if isinstance( action, Action ):
action = action.action
+2 -3
View File
@@ -1106,7 +1106,7 @@ class DataToolParameter( ToolParameter ):
except IndexError:
pass #no valid options
assert trans is not None, "DataToolParameter requires a trans"
history = trans.history
history = trans.get_history()
assert history is not None, "DataToolParameter requires a history"
if value is not None:
if type( value ) != list:
@@ -1170,11 +1170,10 @@ class DataToolParameter( ToolParameter ):
if trans.workflow_building_mode:
return DummyDataset()
assert trans is not None, "DataToolParameter requires a trans"
history = trans.history
history = trans.get_history()
assert history is not None, "DataToolParameter requires a history"
if self.optional:
return None
history = trans.history
most_recent_dataset = [None]
filter_value = None
if self.options:
+359 -186
View File
@@ -1,6 +1,9 @@
from galaxy.web.base.controller import *
from galaxy.web.framework.helpers import time_ago, iff, grids
from galaxy import util
from galaxy.model.mapping import desc
from galaxy.model.orm import *
from galaxy.util.json import *
import webhelpers, logging
from datetime import datetime
from cgi import escape
@@ -11,16 +14,19 @@ log = logging.getLogger( __name__ )
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
class HistoryListGrid( grids.Grid ):
title = "Stored histories"
model_class = model.History
default_sort_key = "-create_time"
columns = [
grids.GridColumn( "Name", key="name",
link=( lambda item: iff( item.deleted, None, dict( operation="switch", id=item.id ) ) ),
attach_popup=True ),
link=( lambda item: iff( item.deleted, None, dict( operation="switch", id=item.id ) ) ),
attach_popup=True ),
grids.GridColumn( "Datasets (by state)", method='_build_datasets_by_state', ncells=4 ),
grids.GridColumn( "Status", method='_build_status' ),
grids.GridColumn( "Status", method='_build_status',
link=( lambda item: iff( item.users_shared_with,
dict( operation="sharing", id=item.id ),
None ) ),
attach_popup=False ),
grids.GridColumn( "Age", key="create_time", format=time_ago ),
grids.GridColumn( "Last update", key="update_time", format=time_ago ),
# Valid for filtering but invisible
@@ -39,13 +45,10 @@ class HistoryListGrid( grids.Grid ):
grids.GridColumnFilter( "All", args=dict( deleted='All' ) )
]
default_filter = dict( deleted=False )
def get_current_item( self, trans ):
return trans.history
return trans.get_history()
def apply_default_filter( self, trans, query ):
return query.filter_by( user=trans.user, purged=False )
def _build_datasets_by_state( self, trans, history ):
rval = []
for state in ( 'ok', 'running', 'queued', 'error' ):
@@ -55,10 +58,11 @@ class HistoryListGrid( grids.Grid ):
else:
rval.append( '' )
return rval
def _build_status( self, trans, history ):
if history.deleted:
return "deleted"
elif history.users_shared_with:
return "shared"
return ""
class HistoryController( BaseController ):
@@ -68,9 +72,7 @@ class HistoryController( BaseController ):
return ""
@web.expose
def list_as_xml( self, trans ):
"""
XML history list for functional tests
"""
"""XML history list for functional tests"""
return trans.fill_template( "/history/list_as_xml.mako" )
list_grid = HistoryListGrid()
@@ -79,29 +81,32 @@ class HistoryController( BaseController ):
@web.require_login( "work with multiple histories" )
def list( self, trans, **kwargs ):
"""List all available histories"""
current_history = trans.history
current_history = trans.get_history()
status = message = None
if 'operation' in kwargs:
history_ids = util.listify( kwargs.get( 'id', [] ) )
histories = []
shared_by_others = []
operation = kwargs['operation'].lower()
if operation == "share":
return self.share( trans, **kwargs )
elif operation == "rename":
return self.rename( trans, **kwargs )
elif operation == 'sharing':
return self.sharing( trans, id=kwargs['id'] )
# Display no message by default
status, message = None, None
refresh_history = False
# Load the histories and ensure they all belong to the current user
history_ids = util.listify( kwargs.get( 'id', [] ) )
histories = []
for hid in history_ids:
history = model.History.get( hid )
for history_id in history_ids:
history = get_history( trans, history_id )
if history:
# Ensure history is owned by current user
if history.user_id != None and trans.user:
assert trans.user.id == history.user_id, "History does not belong to current user"
histories.append( history )
else:
log.warn( "Invalid history id '%r' passed to list", hid )
log.warn( "Invalid history id '%r' passed to list", history_id )
if histories:
if operation == "switch":
status, message = self._list_switch( trans, histories )
@@ -110,33 +115,36 @@ class HistoryController( BaseController ):
elif operation == "delete":
status, message = self._list_delete( trans, histories )
if current_history in histories:
# Deleted the current history, so a new, empty history was
# created automatically, and we need to refresh the history frame
trans.template_context['refresh_frames'] = ['history']
elif operation == "undelete":
status, message = self._list_undelete( trans, histories )
trans.sa_session.flush()
# Render the list view
return self.list_grid( trans, status=status, message=message, **kwargs )
return self.list_grid( trans, status=status, message=message, template='/history/grid.mako', **kwargs )
def _list_delete( self, trans, histories ):
"""Delete histories"""
n_deleted = 0
deleted_current = False
message_parts = []
for history in histories:
if not history.deleted:
if history.users_shared_with:
message_parts.append( "History (%s) has been shared with others, unshare it before deleting it. " % history.name )
elif not history.deleted:
# We'll not eliminate any DefaultHistoryPermissions in case we undelete the history later
# Mark history as deleted in db
history.deleted = True
# If deleting the current history, make a new current.
if history == trans.history:
if history == trans.get_history():
deleted_current = True
trans.new_history()
trans.log_event( "History id %d marked as deleted" % history.id )
trans.log_event( "History (%s) marked as deleted" % history.name )
n_deleted += 1
status = SUCCESS
message_parts = []
if n_deleted:
message_parts.append( "Deleted %d histories." % n_deleted )
message_parts.append( "Deleted %d histories. " % n_deleted )
if deleted_current:
message_parts.append( "Your active history was deleted, a new empty history is now active.")
message_parts.append( "Your active history was deleted, a new empty history is now active. " )
status = INFO
return ( status, " ".join( message_parts ) )
def _list_undelete( self, trans, histories ):
@@ -151,20 +159,20 @@ class HistoryController( BaseController ):
if not history.default_permissions:
# For backward compatibility - for a while we were deleting all DefaultHistoryPermissions on
# the history when we deleted the history. We are no longer doing this.
# Need to add default DefaultHistoryPermissions since they were deleted when the history was deleted
# Need to add default DefaultHistoryPermissions in case they were deleted when the history was deleted
default_action = trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS
private_user_role = trans.app.security_agent.get_private_user_role( history.user )
default_permissions = {}
default_permissions[ default_action ] = [ private_user_role ]
trans.app.security_agent.history_set_default_permissions( history, default_permissions )
n_undeleted += 1
trans.log_event( "History id %d marked as undeleted" % history.id )
trans.log_event( "History (%s) %d marked as undeleted" % history.name )
status = SUCCESS
message_parts = []
if n_undeleted:
message_parts.append( "Undeleted %d histories." % n_undeleted )
if n_already_purged:
message_parts.append( "%d have already been purged and cannot be undeleted." % n_already_purged )
message_parts.append( "%d histories have already been purged and cannot be undeleted." % n_already_purged )
status = WARNING
return status, "".join( message_parts )
def _list_switch( self, trans, histories ):
@@ -172,25 +180,39 @@ class HistoryController( BaseController ):
new_history = histories[0]
galaxy_session = trans.get_galaxy_session()
try:
association = trans.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first()
association = trans.app.model.GalaxySessionToHistoryAssociation \
.filter_by( session_id=galaxy_session.id, history_id=trans.security.decode_id( new_history.id ) ).first()
except:
association = None
new_history.add_galaxy_session( galaxy_session, association=association )
new_history.flush()
trans.set_history( new_history )
trans.log_event( "History switched to id: %s, name: '%s'" % (str(new_history.id), new_history.name ) )
# No message
return None, None
@web.expose
def list_shared( self, trans, **kwd ):
"""List histories shared with current user by others"""
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
shared_by_others = trans.sa_session \
.query( model.HistoryUserShareAssociation ) \
.filter_by( user=trans.user ) \
.join( 'history' ) \
.filter( model.History.deleted == False ) \
.order_by( desc( model.History.update_time ) ) \
.all()
return trans.fill_template( "/history/list_shared.mako", shared_by_others=shared_by_others, msg=msg, messagetype='done' )
@web.expose
def delete_current( self, trans ):
"""Delete just the active history -- this does not require a logged in user."""
history = trans.get_history()
if history.users_shared_with:
return trans.show_error_message( "History (%s) has been shared with others, unshare it before deleting it. " % history.name )
if not history.deleted:
history.deleted = True
history.flush()
trans.log_event( "History id %d marked as deleted" % history.id )
# Regardless of whether it was previously deleted, we make a new
# history active
# Regardless of whether it was previously deleted, we make a new history active
trans.new_history()
return trans.show_ok_message( "History deleted, a new history is active", refresh_frames=['history'] )
@web.expose
@@ -200,7 +222,7 @@ class HistoryController( BaseController ):
# user (if logged in) or the current history
assert history is not None
if history.user is None:
assert history == trans.history
assert history == trans.get_history()
else:
assert history.user == trans.user
# Rename
@@ -208,48 +230,49 @@ class HistoryController( BaseController ):
trans.sa_session.flush()
@web.expose
def imp( self, trans, id=None, confirm=False, **kwd ):
# TODO clean this up and make sure functionally correct
"""Import another user's history via a shared URL"""
msg = ""
user = trans.get_user()
user_history = trans.get_history()
if not id:
return trans.show_error_message( "You must specify a history you want to import.")
id = trans.security.decode_id( id )
import_history = trans.app.model.History.get( id )
return trans.show_error_message( "You must specify a history you want to import." )
import_history = get_history( trans, id )
if not import_history:
return trans.show_error_message( "The specified history does not exist.")
if not import_history.importable:
error( "The owner of this history has disabled imports via this link." )
if user:
if import_history.user_id == user.id:
return trans.show_error_message( "You cannot import your own history.")
new_history = import_history.copy( target_user=trans.user )
new_history.name = "imported: "+new_history.name
return trans.show_error_message( "You cannot import your own history." )
new_history = import_history.copy( target_user=user )
new_history.name = "imported: " + new_history.name
new_history.user_id = user.id
galaxy_session = trans.get_galaxy_session()
try:
association = trans.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first()
association = trans.app.model.GalaxySessionToHistoryAssociation \
.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first()
except:
association = None
new_history.add_galaxy_session( galaxy_session, association=association )
new_history.flush()
if not user_history.datasets:
trans.set_history( new_history )
trans.log_event( "History imported, id: %s, name: '%s': " % (str(new_history.id) , new_history.name ) )
return trans.show_ok_message( """
History "%s" has been imported. Click <a href="%s">here</a>
to begin.""" % ( new_history.name, web.url_for( '/' ) ) )
elif not user_history.datasets or confirm:
new_history = import_history.copy()
new_history.name = "imported: "+new_history.name
new_history.name = "imported: " + new_history.name
new_history.user_id = None
galaxy_session = trans.get_galaxy_session()
try:
association = trans.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first()
association = trans.app.model.GalaxySessionToHistoryAssociation \
.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first()
except:
association = None
new_history.add_galaxy_session( galaxy_session, association=association )
new_history.flush()
trans.set_history( new_history )
trans.log_event( "History imported, id: %s, name: '%s': " % (str(new_history.id) , new_history.name ) )
return trans.show_ok_message( """
History "%s" has been imported. Click <a href="%s">here</a>
to begin.""" % ( new_history.name, web.url_for( '/' ) ) )
@@ -262,106 +285,33 @@ class HistoryController( BaseController ):
def share( self, trans, id=None, email="", **kwd ):
# If a history contains both datasets that can be shared and others that cannot be shared with the desired user,
# then the entire history is shared, and the protected datasets will be visible, but inaccessible ( greyed out )
# in the shared history
# in the cloned history
params = util.Params( kwd )
action = params.get( 'action', None )
if action == "no_share":
trans.response.send_redirect( url_for( controller='root', action='history_options' ) )
if not id:
id = trans.get_history().id
id = util.listify( id )
send_to_err = ""
histories = []
for hid in id:
histories.append( trans.app.model.History.get( hid ) )
if not email:
return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err )
user = trans.get_user()
send_to_users = []
for email_address in util.listify( email ):
email_address = email_address.strip()
if email_address:
if email_address == user.email:
send_to_err += "You can't send histories to yourself. "
else:
send_to_user = trans.app.model.User.filter( trans.app.model.User.table.c.email==email_address ).first()
if send_to_user:
send_to_users.append( send_to_user )
else:
send_to_err += "%s is not a valid Galaxy user. " % email_address
if not email:
if not id:
# Default to the current history
id = trans.security.encode_id( trans.history.id )
id = util.listify( id )
send_to_err = ""
histories = []
for history_id in id:
histories.append( get_history( trans, history_id ) )
return trans.fill_template( "/history/share.mako",
histories=histories,
email=email,
send_to_err=send_to_err )
histories, send_to_users, send_to_err = self._get_histories_and_users( trans, user, id, email )
if not send_to_users:
if not send_to_err:
send_to_err += "%s is not a valid Galaxy user. " % email
return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err )
if params.get( 'share_proceed_button', False ) and action == 'share':
# We need to filter out all histories that cannot be shared
filtered_histories = {}
for history in histories:
for send_to_user in send_to_users:
# Only deal with datasets that have not been purged
for hda in history.activatable_datasets:
# The history can be shared if it contains at least 1 public dataset or 1 dataset that the
# other user can access. Inaccessible datasets contained in the history will be displayed
# in the shared history, but "greyed out", so they cannot be viewed or used.
if trans.app.security_agent.dataset_is_public( hda.dataset ) or \
trans.app.security_agent.allow_action( send_to_user,
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
dataset=hda ):
if send_to_user in filtered_histories:
filtered_histories[ send_to_user ].append( history )
else:
filtered_histories[ send_to_user ] = [ history ]
break
return self._share_histories( trans, user, send_to_users, send_to_err, filtered_histories=filtered_histories )
elif params.get( 'history_share_btn', False ) or action != 'share':
# The user is attempting to share histories whose datasets cannot all be accessed by other users. In this case,
# the user sharing the histories can:
# 1) action=='public': chose to make the datasets public if he is permitted to do so
# 2) action=='private': automatically create a new "sharing role" allowing protected
# datasets to be accessed only by the desired users
# 3) action=='share': share only what can be shared when no permissions are changed - this case is handled above
# 4) action=='no_share': Do not share anything - this case is handled above.
can_change = {}
cannot_change = {}
no_change_needed = {}
for history in histories:
# Only deal with datasets that have not been purged
for hda in history.activatable_datasets:
if trans.app.security_agent.dataset_is_public( hda.dataset ):
if history not in no_change_needed:
no_change_needed[ history ] = [ hda ]
else:
no_change_needed[ history ].append( hda )
elif not trans.app.security_agent.allow_action( send_to_user,
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
dataset=hda ):
# The user with which we are sharing the history does not have access permission on the current dataset
if trans.app.security_agent.allow_action( user,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=hda ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
if action == "private":
trans.app.security_agent.privately_share_dataset( hda.dataset, users=[ user, send_to_user ] )
elif action == "public":
trans.app.security_agent.make_dataset_public( hda.dataset )
elif history not in can_change:
# Build the set of histories / datasets on which the current user has authority
# to "manage permissions". This is used in /history/share.mako
can_change[ history ] = [ hda ]
else:
can_change[ history ].append( hda )
else:
if action in [ "private", "public" ]:
# Don't change stuff that the user doesn't have permission to change
continue
elif history not in cannot_change:
# Build the set of histories / datasets on which the current user does
# not have authority to "manage permissions". This is used in /history/share.mako
cannot_change[ history ] = [ hda ]
else:
cannot_change[ history ].append( hda )
return trans.fill_template( "/history/share.mako",
histories=histories,
email=email,
send_to_err=send_to_err )
if params.get( 'share_button', False ):
can_change, cannot_change, no_change_needed = \
self._populate_restricted( trans, user, histories, send_to_users, None )
if can_change or cannot_change:
return trans.fill_template( "/history/share.mako",
histories=histories,
@@ -370,65 +320,253 @@ class HistoryController( BaseController ):
can_change=can_change,
cannot_change=cannot_change,
no_change_needed=no_change_needed )
return self._share_histories( trans, user, send_to_users, send_to_err, histories=histories )
if no_change_needed:
return self._share_histories( trans, user, send_to_err, histories=no_change_needed )
elif not send_to_err:
# User seems to be sharing an empty history
send_to_err = "You cannot share an empty history. "
return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err )
def _share_histories( self, trans, user, send_to_users, send_to_err, histories=[], filtered_histories={} ):
@web.expose
@web.require_login( "share restricted histories with other users" )
def share_restricted( self, trans, id=None, email="", **kwd ):
action = kwd[ 'action' ]
if action == "no_share":
trans.response.send_redirect( url_for( controller='root', action='history_options' ) )
user = trans.get_user()
histories, send_to_users, send_to_err = self._get_histories_and_users( trans, user, id, email )
send_to_err = ''
can_change, cannot_change, no_change_needed = \
self._populate_restricted( trans, user, histories, send_to_users, action )
# Now that we've populated the can_change, cannot_change, and no_change_needed dictionaries,
# we'll populate the histories_for_sharing dictionary from each of them.
histories_for_sharing = {}
if no_change_needed:
# Don't need to change anything in cannot_change, so populate as is
histories_for_sharing, send_to_err = \
self._populate( trans, histories_for_sharing, no_change_needed, send_to_err )
if cannot_change:
# Can't change anything in cannot_change, so populate as is
histories_for_sharing, send_to_err = \
self._populate( trans, histories_for_sharing, cannot_change, send_to_err )
# The action here is either 'public' or 'private', so we'll continue to populate the
# histories_for_sharing dictionary from the can_change dictionary.
for send_to_user, history_dict in can_change.items():
for history in history_dict:
# Make sure the current history has not already been shared with the current send_to_user
if trans.app.model.HistoryUserShareAssociation \
.filter( and_( trans.app.model.HistoryUserShareAssociation.table.c.user_id == send_to_user.id,
trans.app.model.HistoryUserShareAssociation.table.c.history_id == history.id ) ) \
.count() > 0:
send_to_err += "History (%s) already shared with user (%s)" % ( history.name, send_to_user.email )
else:
# Only deal with datasets that have not been purged
for hda in history.activatable_datasets:
# If the current dataset is not public, we may need to perform an action on it to
# make it accessible by the other user.
if not trans.app.security_agent.allow_action( send_to_user,
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
dataset=hda ):
# The user with which we are sharing the history does not have access permission on the current dataset
if trans.app.security_agent.allow_action( user,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=hda ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
if action == "private":
trans.app.security_agent.privately_share_dataset( hda.dataset, users=[ user, send_to_user ] )
elif action == "public":
trans.app.security_agent.make_dataset_public( hda.dataset )
# Populate histories_for_sharing with the history after performing any requested actions on
# it's datasets to make them accessible by the other user.
if send_to_user not in histories_for_sharing:
histories_for_sharing[ send_to_user ] = [ history ]
elif history not in histories_for_sharing[ send_to_user ]:
histories_for_sharing[ send_to_user ].append( history )
return self._share_histories( trans, user, send_to_err, histories=histories_for_sharing )
def _get_histories_and_users( self, trans, user, id, email ):
if not id:
# Default to the current history
id = trans.security.encode_id( trans.history.id )
id = util.listify( id )
send_to_err = ""
histories = []
for history_id in id:
histories.append( get_history( trans, history_id ) )
send_to_users = []
for email_address in util.listify( email ):
email_address = email_address.strip()
if email_address:
if email_address == user.email:
send_to_err += "You cannot send histories to yourself. "
else:
send_to_user = trans.app.model.User.filter( and_( trans.app.model.User.table.c.email==email_address,
trans.app.model.User.table.c.deleted==False ) ).first()
if send_to_user:
send_to_users.append( send_to_user )
else:
send_to_err += "%s is not a valid Galaxy user. " % email_address
return histories, send_to_users, send_to_err
def _populate( self, trans, histories_for_sharing, other, send_to_err ):
# this method will populate the histories_for_sharing dictionary with the users and
# histories in other, eliminating histories that have already been shared with the
# associated user. No security checking on datasets is performed.
# If not empty, the histories_for_sharing dictionary looks like:
# { userA: [ historyX, historyY ], userB: [ historyY ] }
# other looks like:
# ## { userA: {historyX : [hda, hda], historyY : [hda]}, userB: {historyY : [hda]} }
for send_to_user, history_dict in other.items():
for history in history_dict:
# Make sure the current history has not already been shared with the current send_to_user
if trans.app.model.HistoryUserShareAssociation \
.filter( and_( trans.app.model.HistoryUserShareAssociation.table.c.user_id == send_to_user.id,
trans.app.model.HistoryUserShareAssociation.table.c.history_id == history.id ) ) \
.count() > 0:
send_to_err += "History (%s) already shared with user (%s)" % ( history.name, send_to_user.email )
else:
# Build the dict that will be used for sharing
if send_to_user not in histories_for_sharing:
histories_for_sharing[ send_to_user ] = [ history ]
elif history not in histories_for_sharing[ send_to_user ]:
histories_for_sharing[ send_to_user ].append( history )
return histories_for_sharing, send_to_err
def _populate_restricted( self, trans, user, histories, send_to_users, action ):
# The user may be attempting to share histories whose datasets cannot all be accessed by other users.
# If this is the case, the user sharing the histories can:
# 1) action=='public': choose to make the datasets public if he is permitted to do so
# 2) action=='private': automatically create a new "sharing role" allowing protected
# datasets to be accessed only by the desired users
# 3) action=='share_anyway': share only what can be shared when no permissions are changed
# 4) action=='no_share': Do not share anything
# In addition, the user may be sharing a history with a user with which the history was already shared
# and it will not be shared twice.
# This method will populate the can_change, cannot_change and no_change_needed dictionaries.
can_change = {}
cannot_change = {}
no_change_needed = {}
for history in histories:
for send_to_user in send_to_users:
# Make sure the current history has not already been shared with the current send_to_user
if trans.app.model.HistoryUserShareAssociation \
.filter( and_( trans.app.model.HistoryUserShareAssociation.table.c.user_id == send_to_user.id,
trans.app.model.HistoryUserShareAssociation.table.c.history_id == history.id ) ) \
.count() > 0:
send_to_err += "History (%s) already shared with user (%s)" % ( history.name, send_to_user.email )
else:
# Only deal with datasets that have not been purged
for hda in history.activatable_datasets:
if trans.app.security_agent.dataset_is_public( hda.dataset ):
# Build the dict that will show the user what doesn't need to be changed
if send_to_user not in no_change_needed:
no_change_needed[ send_to_user ] = {}
if history not in no_change_needed[ send_to_user ]:
no_change_needed[ send_to_user ][ history ] = [ hda ]
else:
no_change_needed[ send_to_user ][ history ].append( hda )
elif not trans.app.security_agent.allow_action( send_to_user,
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
dataset=hda ):
# The user with which we are sharing the history does not have access permission on the current dataset
if trans.app.security_agent.allow_action( user,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=hda ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
if send_to_user not in can_change:
# Build the set of histories / datasets on which the current user has authority
# to "manage permissions".
can_change[ send_to_user ] = {}
if history not in can_change[ send_to_user ]:
can_change[ send_to_user ][ history ] = [ hda ]
else:
can_change[ send_to_user ][ history ].append( hda )
else:
if action in [ "private", "public" ]:
# Don't change stuff that the user doesn't have permission to change
continue
#elif send_to_user not in cannot_change:
if send_to_user not in cannot_change:
# Build the set of histories / datasets on which the current user does
# not have authority to "manage permissions".
cannot_change[ send_to_user ] = {}
if history not in cannot_change[ send_to_user ]:
cannot_change[ send_to_user ][ history ] = [ hda ]
else:
cannot_change[ send_to_user ][ history ].append( hda )
return can_change, cannot_change, no_change_needed
def _share_histories( self, trans, user, send_to_err, histories={} ):
# histories looks like: { userA: [ historyX, historyY ], userB: [ historyY ] }
msg = ""
if not send_to_users:
msg = "No users have been specified with which to share histories"
sent_to_emails = []
for sent_to_user in send_to_users:
sent_to_emails.append( sent_to_user.email )
for send_to_user in histories.keys():
sent_to_emails.append( send_to_user.email )
emails = ",".join( e for e in sent_to_emails )
if not histories and not filtered_histories:
msg = "No histories can be sent to (%s) without changing dataset permissions associating a sharing role with them" % emails
elif histories:
history_names = []
for history in histories:
history_names.append( history.name )
for send_to_user in send_to_users:
new_history = history.copy( target_user=send_to_user )
new_history.name = history.name + " from " + user.email
new_history.user_id = send_to_user.id
self.app.model.flush()
msg = "Histories (%s) have been shared with: %s. " % ( ",".join( history_names ), emails )
elif filtered_histories:
# filtered_histories is a dictionary like: { user: [ history, history ], user: [ history ] }
for send_to_user, histories in filtered_histories.items():
history_names = []
for history in histories:
history_names.append( history.name )
new_history = history.copy( target_user=send_to_user )
new_history.name = history.name + " from " + user.email
new_history.user_id = send_to_user.id
self.app.model.flush()
msg += "Histories (%s) have been shared with: %s. " % ( ",".join( history_names ), send_to_user.email )
if not histories:
send_to_err += "No users have been specified or no histories can be sent without changing permissions or associating a sharing role. "
else:
for send_to_user, send_to_user_histories in histories.items():
shared_histories = []
for history in send_to_user_histories:
share = trans.app.model.HistoryUserShareAssociation()
share.history = history
share.user = send_to_user
session = trans.sa_session
session.save_or_update( share )
session.flush()
if history not in shared_histories:
shared_histories.append( history )
if send_to_err:
msg += send_to_err
return trans.show_message( msg )
return self.sharing( trans, histories=shared_histories, msg=msg )
@web.expose
@web.require_login( "share histories with other users" )
def sharing( self, trans, histories=[], id=None, **kwd ):
# histories looks like: [ historyX, historyY ]
params = util.Params( kwd )
msg = util.restore_text ( params.get( 'msg', '' ) )
if id:
histories = [ get_history( trans, id ) ]
for history in histories:
if params.get( 'enable_import_via_link', False ):
history.importable = True
history.flush()
elif params.get( 'disable_import_via_link', False ):
history.importable = False
history.flush()
elif params.get( 'unshare_user', False ):
user = trans.app.model.User.get( trans.security.decode_id( kwd[ 'unshare_user' ] ) )
if not user:
msg = 'History (%s) does not seem to be shared with user (%s)' % ( history.name, user.email )
return trans.fill_template( 'history/sharing.mako', histories=histories, msg=msg, messagetype='error' )
association = trans.app.model.HistoryUserShareAssociation.filter_by( user=user, history=history ).one()
association.delete()
association.flush()
if not id:
shared_msg = "History (%s) now shared with: %d users. " % ( history.name, len( history.users_shared_with ) )
msg = '%s%s' % ( shared_msg, msg )
return trans.fill_template( 'history/sharing.mako', histories=histories, msg=msg, messagetype='done' )
@web.expose
@web.require_login( "rename histories" )
def rename( self, trans, id=None, name=None, **kwd ):
user = trans.get_user()
if not isinstance( id, list ):
if id != None:
id = [ id ]
if not isinstance( name, list ):
if name != None:
name = [ name ]
if not id:
# Default to the current history
history = trans.get_history()
if not history.user:
return trans.show_error_message( "You must save your history before renaming it." )
id = trans.security.encode_id( history.id )
id = util.listify( id )
name = util.listify( name )
histories = []
cur_names = []
if not id:
if not trans.get_history().user:
return trans.show_error_message( "You must save your history before renaming it." )
id = [trans.get_history().id]
for history_id in id:
history = trans.app.model.History.get( history_id )
history = get_history( trans, history_id )
if history and history.user_id == user.id:
histories.append(history)
cur_names.append(history.name)
if not name or len(histories)!=len(name):
return trans.fill_template( "/history/rename.mako",histories=histories )
histories.append( history )
cur_names.append( history.name )
if not name or len( histories ) != len( name ):
return trans.fill_template( "/history/rename.mako", histories=histories )
change_msg = ""
for i in range(len(histories)):
if histories[i].user_id == user.id:
@@ -445,3 +583,38 @@ class HistoryController( BaseController ):
else:
change_msg = change_msg + "<p>History: "+cur_names[i]+" does not appear to belong to you.</p>"
return trans.show_message( "<p>%s" % change_msg, refresh_frames=['history'] )
@web.expose
@web.require_login( "clone shared Galaxy history" )
def clone( self, trans, id ):
history = get_history( trans, id, check_ownership=False )
user = trans.get_user()
if history.user == user:
owner = True
else:
if trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ) \
.filter_by( user=user, history=history ).count() == 0:
return trans.show_error_message( "The history you are attempting to clone is not owned by you or shared with you. " )
owner = False
name = "Clone of '%s'" % history.name
if not owner:
name += " shared by '%s'" % history.user.email
new_history = history.copy( name=name, target_user=user )
# Render the list view
return trans.show_ok_message( 'Clone with name "%s" is now included in your list of stored histories.' % new_history.name )
## ---- Utility methods -------------------------------------------------------
def get_history( trans, id, check_ownership=True ):
"""Get a History from the database by id, verifying ownership."""
# Load history from database
id = trans.security.decode_id( id )
history = trans.sa_session.query( model.History ).get( id )
if not history:
err+msg( "History not found" )
# Verify ownership
user = trans.get_user()
if not user:
error( "Must be logged in to manage histories" )
if check_ownership and not( history.user == user ):
error( "History is not owned by current user" )
return history
+7 -7
View File
@@ -50,19 +50,18 @@ class RootController( BaseController ):
@web.expose
def history( self, trans, as_xml=False, show_deleted=False ):
"""
Display the current history, creating a new history if neccesary.
Display the current history, creating a new history if necessary.
NOTE: No longer accepts "id" or "template" options for security reasons.
"""
history = trans.get_history()
if trans.app.config.require_login and not trans.user:
return trans.fill_template( '/no_access.mako', message = 'Please log in to access Galaxy histories.' )
history = trans.get_history( create=True )
if as_xml:
trans.response.set_content_type('text/xml')
return trans.fill_template_mako( "root/history_as_xml.mako", history=history, show_deleted=util.string_as_bool( show_deleted ) )
else:
template = "root/history.mako"
return trans.fill_template( "root/history.mako", history = history, show_deleted = util.string_as_bool( show_deleted ) )
return trans.fill_template( "root/history.mako", history=history, show_deleted=util.string_as_bool( show_deleted ) )
@web.expose
def dataset_state ( self, trans, id=None, stamp=None ):
@@ -350,9 +349,10 @@ class RootController( BaseController ):
@web.expose
def history_options( self, trans ):
"""Displays a list of history related actions"""
"""Displays a list of history related actions"""
return trans.fill_template( "/history/options.mako",
user = trans.get_user(), history = trans.get_history() )
user=trans.get_user(),
history=trans.get_history( create=True ) )
@web.expose
def history_delete( self, trans, id ):
"""
@@ -421,7 +421,7 @@ class RootController( BaseController ):
@web.expose
def history_new( self, trans, name=None ):
trans.new_history( name=name )
trans.log_event( "Created new History, id: %s." % str(trans.get_history().id) )
trans.log_event( "Created new History, id: %s." % str(trans.history.id) )
return trans.show_message( "New history created", refresh_frames = ['history'] )
@web.expose
def history_add_to( self, trans, history_id=None, file_data=None, name="Data Added to History",info=None,ext="txt",dbkey="?",copy_access_from=None,**kwd ):
+1
View File
@@ -81,6 +81,7 @@ class User( BaseController ):
@web.expose
def login( self, trans, email='', password='' ):
log.debug( "###IN login, email:%s, password: %s" % ( email, password ))
email_error = password_error = None
# Attempt login
if trans.app.config.require_login:
+1 -1
View File
@@ -129,7 +129,7 @@ class WorkflowController( BaseController ):
if stored.importable == False:
error( "The owner of this workflow has disabled imports via this link" )
elif stored.user == trans.user:
error( "You are already the ownder of this workflow, can't import" )
error( "You are already the owner of this workflow, can't import" )
elif stored.deleted:
error( "This workflow has been deleted, can't import" )
elif session.query( model.StoredWorkflowUserShareAssociation ) \
+52 -26
View File
@@ -180,7 +180,7 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
except:
event.message = message
try:
event.history = self.history
event.history = self.get_history()
except:
event.history = None
try:
@@ -337,11 +337,11 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
remote_host = self.request.remote_host,
remote_addr = self.request.remote_addr,
referer = self.request.headers.get( 'Referer', None ) )
# Invalidated an existing sesssion for some reason, keep track
if prev_galaxy_session:
# Invalidated an existing session for some reason, keep track
galaxy_session.prev_session_id = prev_galaxy_session.id
# The new session should be immediately associated with a user
if user_for_new_session:
# The new session should be associated with the user
galaxy_session.user = user_for_new_session
return galaxy_session
def __get_or_create_remote_user( self, remote_user_email ):
@@ -350,12 +350,23 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
"""
# remote_user middleware ensures HTTP_REMOTE_USER exists
user = self.app.model.User.filter( self.app.model.User.table.c.email==remote_user_email ).first()
if user is None:
if user:
# GVK: June 29, 2009 - This is to correct the behavior of a previous bug where a private
# role and default user / history permissions were not set for remote users. When a
# remote user authenticates, we'll look for this information, and if missing, create it.
if not self.app.security_agent.get_private_user_role( user ):
self.app.security_agent.create_private_user_role( user )
if not user.default_permissions:
self.app.security_agent.user_set_default_permissions( user, history=True, dataset=True )
elif user is None:
random.seed()
user = self.app.model.User( email=remote_user_email )
user.set_password_cleartext( ''.join( random.sample( string.letters + string.digits, 12 ) ) )
user.external = True
user.flush()
self.app.security_agent.create_private_user_role( user )
# We set default user permissions, before we log in and set the default history permissions
self.app.security_agent.user_set_default_permissions( user )
#self.log_event( "Automatically created account '%s'", user.email )
elif user.deleted:
return self.show_error_message( "Your account is no longer valid, contact your Galaxy administrator to activate your account." )
@@ -365,7 +376,6 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
Update the session cookie to match the current session.
"""
self.set_cookie( self.security.encode_session_key( self.galaxy_session.session_key ), name=name )
def handle_user_login( self, user ):
"""
Login a new user (possibly newly created)
@@ -374,24 +384,39 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
- if old session had a history and it was not associated with a user, associate it with the new session,
otherwise associate the current session's history with the user
"""
# Set the previous session
prev_galaxy_session = self.galaxy_session
prev_galaxy_session.is_valid = False
# Define a new current_session
self.galaxy_session = self.__create_new_session( prev_galaxy_session, user )
# If the session already had a history, we associate it with the new
# session, but only if it does not belong to a different user.
if prev_galaxy_session.current_history and \
( prev_galaxy_session.current_history.user == user or prev_galaxy_session.user is None ):
history = prev_galaxy_session.current_history
elif self.galaxy_session.current_history:
history = self.galaxy_session.current_history
else:
history = self.history
# Associated the current user's last accessed history (if exists) with their new session
history = None
try:
users_last_session = user.galaxy_sessions[0]
last_accessed = True
except:
users_last_session = None
last_accessed = False
if users_last_session and users_last_session.current_history:
history = users_last_session.current_history
if not history:
if prev_galaxy_session.current_history:
if prev_galaxy_session.current_history.user is None or prev_galaxy_session.current_history.user == user:
# If the previous galaxy session had a history, associate it with the new
# session, but only if it didn't belong to a different user.
history = prev_galaxy_session.current_history
elif self.galaxy_session.current_history:
history = self.galaxy_session.current_history
else:
history = self.get_history( create=True )
if history not in self.galaxy_session.histories:
self.galaxy_session.add_history( history )
if history.user is None:
history.user = user
self.galaxy_session.current_history = history
self.app.security_agent.history_set_default_permissions( history, dataset=True, bypass_manage_permission=True )
if not last_accessed:
# Only set default history permissions if current history is not from a previous session
self.app.security_agent.history_set_default_permissions( history, dataset=True, bypass_manage_permission=True )
self.sa_session.flush( [ prev_galaxy_session, self.galaxy_session, history ] )
# This method is not called from the Galaxy reports, so the cookie will always be galaxysession
self.__update_session_cookie( name='galaxysession' )
@@ -403,7 +428,7 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
"""
prev_galaxy_session = self.galaxy_session
prev_galaxy_session.is_valid = False
self.galaxy_session = self.__create_new_session( prev_galaxy_session, None )
self.galaxy_session = self.__create_new_session( prev_galaxy_session )
self.sa_session.flush( [ prev_galaxy_session, self.galaxy_session ] )
# This method is not called from the Galaxy reports, so the cookie will always be galaxysession
self.__update_session_cookie( name='galaxysession' )
@@ -416,16 +441,15 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
def get_history( self, create=False ):
"""
Load the current history.
NOTE: It looks like create was being ignored for a long time, so this
will currently *always* create a new history. This is wasteful
though, and we should verify that callers are using the create
flag correctly and fix.
Load the current history, creating a new one only if there is not
current history and we're told to create"
"""
history = self.galaxy_session.current_history
if history is None:
history = self.new_history()
if not history:
if util.string_as_bool( create ):
history = self.new_history()
else:
raise "get_history() returning None"
return history
def set_history( self, history ):
if history and not history.deleted:
@@ -557,7 +581,8 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
the user (chromInfo in history).
"""
dbnames = list()
datasets = self.app.model.HistoryDatasetAssociation.filter_by(deleted=False, history_id=self.history.id, extension="len").all()
datasets = self.app.model.HistoryDatasetAssociation \
.filter_by(deleted=False, history_id=self.history.id, extension="len").all()
if len(datasets) > 0:
dbnames.append( (util.dbnames.default_value, '--------- User Defined Builds ----------') )
for dataset in datasets:
@@ -569,7 +594,8 @@ class UniverseWebTransaction( base.DefaultWebTransaction ):
"""
Returns the db_file dataset associated/needed by `dataset`, or `None`.
"""
datasets = self.app.model.HistoryDatasetAssociation.filter_by(deleted=False, history_id=self.history.id, extension="len").all()
datasets = self.app.model.HistoryDatasetAssociation \
.filter_by(deleted=False, history_id=self.history.id, extension="len").all()
for ds in datasets:
if dbkey == ds.dbkey:
return ds
+13 -2
View File
@@ -3,7 +3,9 @@ from galaxy.model.orm import *
from galaxy.web import url_for
import sys
import sys, logging
log = logging.getLogger( __name__ )
class Grid( object ):
"""
@@ -12,6 +14,7 @@ class Grid( object ):
title = ""
exposed = True
model_class = None
template = None
columns = []
standard_filters = []
default_filter = None
@@ -22,6 +25,7 @@ class Grid( object ):
def __call__( self, trans, **kwargs ):
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
template = kwargs.get( 'template', None )
session = trans.sa_session
# Build initial query
query = self.build_initial_query( session )
@@ -70,8 +74,15 @@ class Grid( object ):
if len(args) > 0:
new_kwargs.update( args[0] )
new_kwargs.update( kwargs )
# We need to encode item ids
if 'id' in new_kwargs:
id = new_kwargs[ 'id' ]
if isinstance( id, list ):
new_args[ 'id' ] = [ trans.security.encode_id( i ) for i in id ]
else:
new_kwargs[ 'id' ] = trans.security.encode_id( id )
return url_for( **new_kwargs )
return trans.fill_template( "grid.mako",
return trans.fill_template( template,
grid=self,
query=query,
sort_key=sort_key,
-2
View File
@@ -30,9 +30,7 @@ else:
random_pool.stir()
return str( number.getRandomNumber( nbits, random_pool.get_bytes ) )
class SecurityHelper( object ):
# TODO: checking if histories/datasets are owned by the current user) will be moved here.
def __init__( self, **config ):
self.id_secret = config['id_secret']
self.id_cipher = Blowfish.new( self.id_secret )
@@ -25,7 +25,6 @@
})
});
});
## Can this be moved into base.mako?
%if refresh_frames:
%if 'masthead' in refresh_frames:
@@ -73,7 +72,6 @@
</style>
</%def>
<div class="grid-header">
<h2>${grid.title}</h2>
<span class="title">Filter:</span>
@@ -86,7 +84,6 @@
</div>
<form name="history_actions" action="${url()}" method="post" >
<table class="grid">
<thead>
<tr>
@@ -107,7 +104,7 @@
else:
href = url( sort=column.key )
%>
<th \
<th\
%if column.ncells > 1:
colspan="${column.ncells}"
%endif
@@ -122,77 +119,63 @@
%endif
%endfor
<th></th>
</tr>
</thead>
<tbody>
%for i, item in enumerate( query ):
<tr \
%if current_item == item:
class="current" \
%endif
>
## Item selection column
<td style="width: 1.5em;"><input type="checkbox" name="id" value=${item.id} class="grid-row-select-checkbox"></input></td>
## Data columns
%for column in grid.columns:
%if column.visible:
<%
# Link
if column.link and column.link( item ):
href = url( **column.link( item ) )
else:
href = None
# Value (coerced to list so we can loop)
value = column.get_value( trans, grid, item )
if column.ncells == 1:
value = [ value ]
%>
%for cellnum, v in enumerate( value ):
>
## Item selection column
<td style="width: 1.5em;">
<input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" />
</td>
## Data columns
%for column in grid.columns:
%if column.visible:
<%
# Attach popup menu?
if column.attach_popup and cellnum == 0:
extra = '<a id="grid-%d-popup" class="popup-arrow" style="display: none;">&#9660;</a>' % i
# Link
if column.link and column.link( item ):
href = url( **column.link( item ) )
else:
extra = ""
href = None
# Value (coerced to list so we can loop)
value = column.get_value( trans, grid, item )
if column.ncells == 1:
value = [ value ]
%>
%if href:
<td><a href="${href}">${v}</a>&nbsp;${extra}</td>
%else:
<td >${v}${extra}</td>
%endif
</td>
%endfor
%endif
%endfor
## Actions column
<td>
<div popupmenu="grid-${i}-popup">
%for operation in grid.operations:
%if operation.allowed( item ):
<a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a>
%endif
%endfor
</div>
</td>
%for cellnum, v in enumerate( value ):
<%
# Attach popup menu?
if column.attach_popup and cellnum == 0:
extra = '<a id="grid-%d-popup" class="popup-arrow" style="display: none;">&#9660;</a>' % i
else:
extra = ""
%>
%if href:
<td><a href="${href}">${v}</a>&nbsp;${extra}</td>
%else:
<td >${v}${extra}</td>
%endif
</td>
%endfor
%endif
%endfor
## Actions column
<td>
<div popupmenu="grid-${i}-popup">
%for operation in grid.operations:
%if operation.allowed( item ):
<a class="action-button" href="${url( operation=operation.label, id=trans.security.encode_id( item.id ) )}">${operation.label}</a>
%endif
%endfor
</div>
</td>
</tr>
%endfor
</tbody>
<tfoot>
<tr>
<td></td>
@@ -203,14 +186,8 @@
<input type="submit" name="operation" value="${operation.label}" class="action-button">
%endif
%endfor
</td>
</tr>
</tfoot>
</table>
</form>
</form>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<history_ids>
%for i, history in enumerate( t.user.histories ):
<data id="${history.id}" hid="${i+1}" num="${len(history.datasets)}" name="${history.name}" create="${history.create_time}" update="${history.update_time}" >
<data id="${trans.security.encode_id( history.id )}" hid="${i+1}" num="${len(history.datasets)}" name="${history.name}" create="${history.create_time}" update="${history.update_time}" >
</data>
%endfor
</history_ids>
+30
View File
@@ -0,0 +1,30 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if msg:
${render_msg( msg, messagetype )}
%endif
%if shared_by_others:
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr class="header">
<th>Name</th>
<th>Owner</th>
</tr>
%for i, association in enumerate( shared_by_others ):
<% history = association.history %>
<tr>
<td>
${history.name}
<a id="shared-${i}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
<div popupmenu="shared-${i}-popup">
<a class="action-button" href="${h.url_for( controller='history', action='clone', id=trans.security.encode_id( history.id ) )}">Clone</a>
</div>
</td>
<td>${history.user.email}</td>
</tr>
%endfor
</table>
%else:
No histories have been shared with you.
%endif
+16 -10
View File
@@ -11,16 +11,22 @@
%endif
<ul>
%if user:
<li><a href="${h.url_for( controller='history', action='rename', id=history.id )}" target="galaxy_main">Rename</a> current history (stored as "${history.name}")</li>
<li><a href="${h.url_for( controller='history', action='list')}" target="galaxy_main">List</a> previously stored histories</li>
%if len( history.active_datasets ) > 0:
<li><a href="${h.url_for( controller='root', action='history_new' )}">Create</a> a new empty history</li>
%if user:
<li><a href="${h.url_for( controller='history', action='list')}" target="galaxy_main">List</a> previously stored histories</li>
%if len( history.active_datasets ) > 0:
<li><a href="${h.url_for( controller='root', action='history_new' )}">Create</a> a new empty history</li>
<li><a href="${h.url_for( controller='workflow', action='build_from_current_history' )}">Construct workflow</a> from current history</li>
<li><a href="${h.url_for( controller='history', action='clone', id=trans.security.encode_id( history.id ) )}">Clone</a> current history</li>
%endif
<li><a href="${h.url_for( controller='history', action='share' )}" target="galaxy_main">Share</a> current history</div>
<li><a href="${h.url_for( action='history_set_default_permissions' )}">Change default permissions</a> for current history</li>
%endif
<li><a href="${h.url_for( controller='workflow', action='build_from_current_history' )}">Construct workflow</a> from the current history</li>
<li><a href="${h.url_for( controller='history', action='share' )}" target="galaxy_main">Share</a> current history</div>
<li><a href="${h.url_for( action='history_set_default_permissions' )}">Change default permissions</a> for the current history</li>
%endif
<li><a href="${h.url_for( controller='root', action='history', show_deleted=True)}" target="galaxy_history">Show deleted</a> datasets in history</li>
%if len( history.activatable_datasets ) > 0:
<li><a href="${h.url_for( controller='root', action='history', show_deleted=True)}" target="galaxy_history">Show deleted</a> datasets in current history</li>
%endif
<li><a href="${h.url_for( controller='history', action='rename', id=trans.security.encode_id( history.id ) )}" target="galaxy_main">Rename</a> current history (stored as "${history.name}")</li>
<li><a href="${h.url_for( controller='history', action='delete_current' )}" confirm="Are you sure you want to delete the current history?">Delete</a> current history</div>
%if user and user.histories_shared_by_others:
<li><a href="${h.url_for( controller='history', action='list_shared')}" target="galaxy_main">List</a> histories shared with you by others</li>
%endif
</ul>
+2 -1
View File
@@ -3,5 +3,6 @@
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
%if trans.user:
${render_permission_form( trans.history, trans.history.name, h.url_for(), trans.user.all_roles() )}
<% history = trans.get_history() %>
${render_permission_form( history, history.name, h.url_for(), trans.user.all_roles() )}
%endif
+1 -1
View File
@@ -11,7 +11,7 @@
<tr>
<td>
<div class="form-row">
<input type="hidden" name="id" value="${history.id}">
<input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
<label>${_('Current Name')}</label>
<div style="float: left; width: 250px; margin-right: 10px;">
${history.name}
+88 -28
View File
@@ -5,14 +5,16 @@
<div class="toolForm">
<div class="toolFormTitle">Share ${len( histories)} histories</div>
<div class="toolFormBody">
%if not can_change and not cannot_change:
<form action="${h.url_for( controller="history", action='share' )}" method="post" >
%if not can_change and not cannot_change and not no_change_needed:
## We are sharing histories that contain only public datasets
<form name='share' id='share' action="${h.url_for( controller="history", action='share' )}" method="post" >
%for history in histories:
<input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
<div class="toolForm">
<div class="form-row">
<label>${_('History Name:')}</label>
<div style="float: left; width: 250px; margin-right: 10px;">
${history.name}<input type="hidden" name="id" value="${history.id}">
${history.name}
</div>
</div>
<div style="clear: both"></div>
@@ -27,15 +29,7 @@
</td>
</div>
</div>
## TODO: this feature is not currently working
##<div style="clear: both"></div>
##<div class="form-row">
## <label>${_('Share Link')}</label>
## <div style="float: left; width: 250px; margin-right: 10px;">
## <a href="${h.url_for( controller='history', action='imp', id=trans.security.encode_id(history.id) )}">${_('copy link to share')}</a>
## </div>
##</div>
##<div style="clear: both"></div>
<div style="clear: both"></div>
<p/>
</div>
%endfor
@@ -58,15 +52,17 @@
%endif
<div style="clear: both"></div>
<div class="form-row">
<input type="submit" name="history_share_btn" value="Submit">
<input type="submit" name="share_button" value="Submit">
</div>
</form>
%else:
<form action="${h.url_for( controller='history', action='share' )}" method="post">
## We are sharing restricted histories
<form name='share_restricted' id=share_restricted' action="${h.url_for( controller='history', action='share_restricted' )}" method="post">
## Needed for rebuilding dicts
<input type="hidden" name="email" value="${email}" size="40">
%for history in histories:
<input type="hidden" name="id" value="${history.id}">
<input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
%endfor
<input type="hidden" name="email" value="${email}">
%if no_change_needed:
<div style="clear: both"></div>
<div class="form-row">
@@ -74,7 +70,29 @@
The following datasets can be shared with ${email} with no changes
</div>
</div>
%for history, hdas in no_change_needed.items():
## no_change_needed looks like:
## { userA: {historyX : [hda, hda], historyY : [hda]}, userB: {historyY : [hda]} }
<%
# TODO: move generation of these unique dictionaries to the history controller
# Build the list of unique histories and datasets
unique_stuff = {}
%>
%for user, history_dict in no_change_needed.items():
%for history, hdas in history_dict.items():
<%
if history in unique_stuff:
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
else:
unique_stuff[ history ] = []
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
%>
%endfor
%endfor
%for history, hdas in unique_stuff.items():
<div class="form-row">
<label>History</label>
${history.name}
@@ -97,7 +115,29 @@
The following datasets can be shared with ${email} by updating their permissions
</div>
</div>
%for history, hdas in can_change.items():
## can_change looks like:
## { userA: {historyX : [hda, hda], historyY : [hda]}, userB: {historyY : [hda]} }
<%
# TODO: move generation of these unique dictionaries to the history controller
# Build the list of unique histories and datasets
unique_stuff = {}
%>
%for user, history_dict in can_change.items():
%for history, hdas in history_dict.items():
<%
if history in unique_stuff:
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
else:
unique_stuff[ history ] = []
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
%>
%endfor
%endfor
%for history, hdas in unique_stuff.items():
<div class="form-row">
<label>History</label>
${history.name}
@@ -121,7 +161,29 @@
change the permissions on them
</div>
</div>
%for history, hdas in cannot_change.items():
## cannot_change looks like:
## { userA: {historyX : [hda, hda], historyY : [hda]}, userB: {historyY : [hda]} }
<%
# TODO: move generation of these unique dictionaries to the history controller
# Build the list of unique histories and datasets
unique_stuff = {}
%>
%for user, history_dict in can_change.items():
%for history, hdas in history_dict.items():
<%
if history in unique_stuff:
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
else:
unique_stuff[ history ] = []
for hda in hdas:
if hda not in unique_stuff[ history ]:
unique_stuff[ history ].append( hda )
%>
%endfor
%endfor
%for history, hdas in unique_stuff.items():
<div class="form-row">
<label>History</label>
${history.name}
@@ -154,19 +216,17 @@
%endif
</div>
%endif
%if no_change_needed:
<div class="form-row">
<input type="radio" name="action" value="share"> Share anyway
%if can_change:
(don't change any permissions)
%endif
</div>
%endif
<div class="form-row">
<input type="radio" name="action" value="share_anyway"> Share anyway
%if can_change:
(don't change any permissions)
%endif
</div>
<div class="form-row">
<input type="radio" name="action" value="no_share"> Don't share
</div>
<div class="form-row">
<input type="submit" name="share_proceed_button" value="Go"><br/>
<input type="submit" name="share_restricted_button" value="Go"><br/>
</div>
</form>
%endif
+75
View File
@@ -0,0 +1,75 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<h2>Public access via link</h2>
%if msg:
${render_msg( msg, messagetype )}
%endif
%for history in histories:
<p>
%if history.importable:
Send the following URL to users as an easy way for them to import the history, making a copy of their own:
<% url = h.url_for( controller='history', action='imp', id=trans.security.encode_id(history.id), qualified=True ) %>
<blockquote>
<a href="${url}">${url}</a>
</blockquote>
<br/>
<form action="${h.url_for( controller='history', action='sharing', id=trans.security.encode_id( history.id ) )}" method="POST">
<input class="action-button" type="submit" name="disable_import_via_link" value="Disable import via link">
</form>
%else:
This history is currently restricted (only you and the users listed below
can access it). Enabling the following option will generate a URL that you
can give to a user to allow them to import this history.
<br/>
<form action="${h.url_for( action='sharing', id=trans.security.encode_id(history.id) )}" method="POST">
<input class="action-button" type="submit" name="enable_import_via_link" value="Enable import via link">
</form>
%endif
</p>
<h2>Sharing with specific users</h2>
%if history.users_shared_with:
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( controller='history', action='share', id=trans.security.encode_id( history.id ) )}">
<span>Share with another user</span>
</a>
</li>
</ul>
<p>
The following users will see this history in their list of histories
shared with them by others, and they will be able to create their own copy of it:
</p>
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr class="header">
<th>History '${history.name}' currently shared with</th>
<th></th>
</tr>
%for i, association in enumerate( history.users_shared_with ):
<% user = association.user %>
<tr>
<td>
${user.email}
<a id="user-${i}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
</td>
<td>
%if len( histories ) == 1:
## Only allow unsharing if we're dealing with 1 history, otherwise
## page refreshes screw things up
<div popupmenu="user-${i}-popup">
<a class="action-button" href="${h.url_for( controller='history', action='sharing', id=trans.security.encode_id( history.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a>
</div>
%endif
</td>
</tr>
%endfor
</table>
%else:
<p>You have not shared this history with any users.</p>
<a class="action-button" href="${h.url_for( controller='history', action='share', id=trans.security.encode_id(history.id) )}">
<span>Share with another user</span>
</a>
%endif
%endfor
+159 -65
View File
@@ -9,7 +9,8 @@ import twill.commands as tc
from twill.other_packages._mechanize_dist import ClientForm
pkg_resources.require( "elementtree" )
from elementtree import ElementTree
from galaxy.web import security
buffer = StringIO.StringIO()
#Force twill to log to a buffer -- FIXME: Should this go to stdout and be captured by nose?
@@ -23,13 +24,15 @@ log = logging.getLogger( __name__ )
class TwillTestCase( unittest.TestCase ):
def setUp( self ):
# Security helper
self.security = security.SecurityHelper( id_secret='changethisinproductiontoo' )
self.history_id = os.environ.get( 'GALAXY_TEST_HISTORY_ID', None )
self.host = os.environ.get( 'GALAXY_TEST_HOST' )
self.port = os.environ.get( 'GALAXY_TEST_PORT' )
self.url = "http://%s:%s" % ( self.host, self.port )
self.file_dir = os.environ.get( 'GALAXY_TEST_FILE_DIR' )
self.home()
self.set_history()
#self.set_history()
# Functions associated with files
def files_diff( self, file1, file2 ):
@@ -71,6 +74,7 @@ class TwillTestCase( unittest.TestCase ):
def upload_file( self, filename, ftype='auto', dbkey='unspecified (?)' ):
"""Uploads a file"""
filename = self.get_filename(filename)
self.home()
self.visit_page( "tool_runner/index?tool_id=upload1" )
try:
tc.fv("1","file_type", ftype)
@@ -79,9 +83,16 @@ class TwillTestCase( unittest.TestCase ):
tc.submit("runtool_btn")
self.home()
except AssertionError, err:
errmsg = 'The file doesn\'t exsit. Please check' % file
errmsg = "The file (%s) doesn't exist." % filename
errmsg += str( err )
raise AssertionError( errmsg )
# Make sure every history item has a valid hid
hids = self.get_hids_in_history()
for hid in hids:
try:
valid_hid = int( hid )
except:
raise AssertionError, "Invalid hid (%s) created when uploading file %s" % ( hid, filename )
def upload_url_paste( self, url_paste, ftype='auto', dbkey='unspecified (?)' ):
"""Pasted data in the upload utility"""
self.visit_page( "tool_runner/index?tool_id=upload1" )
@@ -94,6 +105,13 @@ class TwillTestCase( unittest.TestCase ):
except Exception, e:
errmsg = "Problem executing upload utility using url_paste: %s" % str( e )
raise AssertionError( e )
# Make sure every history item has a valid hid
hids = self.get_hids_in_history()
for hid in hids:
try:
valid_hid = int( hid )
except:
raise AssertionError, "Invalid hid (%s) created when pasting %s" % ( hid, url_paste )
# Functions associated with histories
def check_history_for_errors( self ):
@@ -115,27 +133,30 @@ class TwillTestCase( unittest.TestCase ):
self.visit_page( "clear_history" )
self.check_history_for_string( 'Your history is empty' )
self.home()
def delete_history( self, id='' ):
def delete_history( self, id ):
"""Deletes one or more histories"""
history_list = self.get_histories()
history_list = self.get_histories_as_data_list()
self.assertTrue( history_list )
num_deleted = 1
if not id:
history = history_list[0]
id = history.get( 'id' )
else:
num_deleted = len( id.split( ',' ) )
num_deleted = len( id.split( ',' ) )
self.home()
self.visit_page( "history/list?operation=delete&id=%s" % ( id ) )
check_str = 'Deleted %d histories' % num_deleted
self.check_page_for_string( check_str )
self.home()
def get_histories( self ):
"""Returns all histories"""
def delete_current_history( self, check_str='' ):
"""Deletes the current history"""
self.home()
self.visit_page( "history/delete_current" )
if check_str:
self.check_page_for_string( check_str )
self.home()
def get_histories_as_data_list( self ):
"""Returns the data elements of all histories"""
tree = self.histories_as_xml_tree()
data_list = [ elem for elem in tree.findall("data") ]
return data_list
def get_history( self, show_deleted=False ):
"""Returns a history"""
def get_history_as_data_list( self, show_deleted=False ):
"""Returns the data elements of a history"""
tree = self.history_as_xml_tree( show_deleted=show_deleted )
data_list = [ elem for elem in tree.findall("data") ]
return data_list
@@ -153,31 +174,24 @@ class TwillTestCase( unittest.TestCase ):
xml = self.last_page()
tree = ElementTree.fromstring(xml)
return tree
def history_options( self, check_str='', upload=False ):
def history_options( self, user=False, active_datasets=False, activatable_datasets=False, histories_shared_by_others=False ):
"""Mimics user clicking on history options link"""
self.visit_page( "history_options" )
if check_str:
self.check_page_for_string( check_str )
else:
self.check_page_for_string( 'Rename</a> current history' )
self.home()
self.visit_page( "root/history_options" )
if user:
self.check_page_for_string( 'List</a> previously stored histories' )
self.check_page_for_string( 'Construct workflow</a> from the current history' )
if active_datasets:
self.check_page_for_string( 'Create</a> a new empty history' )
self.check_page_for_string( 'Construct workflow</a> from current history' )
self.check_page_for_string( 'Clone</a> current history' )
self.check_page_for_string( 'Share</a> current history' )
# Tests for changing default history permissions are done in test_security_and_libraries.py
self.check_page_for_string( 'Change default permissions</a> for the current history' )
self.check_page_for_string( 'Show deleted</a> datasets in history' )
self.check_page_for_string( 'Delete</a> current history' )
# Need to add a history item in order to create a new empty history
try:
self.check_page_for_string( 'Create</a> a new empty history' )
raise AssertionError, "Incorrectly able to create a new empty history when the current history is empty."
except:
pass
if upload:
self.upload_file( '1.bed', dbkey='hg18' )
self.home()
self.visit_page( "history_options" )
self.check_page_for_string( 'Create</a> a new empty history' )
self.check_page_for_string( 'Change default permissions</a> for current history' )
if histories_shared_by_others:
self.check_page_for_string( 'List</a> histories shared with you by others' )
if activatable_datasets:
self.check_page_for_string( 'Show deleted</a> datasets in current history' )
self.check_page_for_string( 'Rename</a> current history' )
self.check_page_for_string( 'Delete</a> current history' )
self.home()
def new_history( self, name=None ):
"""Creates a new, empty history"""
@@ -198,26 +212,63 @@ class TwillTestCase( unittest.TestCase ):
def set_history( self ):
"""Sets the history (stores the cookies for this run)"""
if self.history_id:
self.home()
self.visit_page( "history?id=%s" % self.history_id )
else:
self.new_history()
self.home()
def share_history( self, id, email, check_str, check_str2='', action=None, action_check_str=None ):
"""Share a history different users"""
self.visit_url( "%s/history/share?id=%s&email=%s&history_share_btn=Submit" % ( self.url, id, email ) )
self.check_page_for_string( check_str )
if check_str2:
self.check_page_for_string( check_str2 )
def share_current_history( self, email, check_str='', check_str_after_submit='', check_str_after_submit2='',
action='', action_check_str='', action_check_str_after_submit='' ):
"""Share the current history with different users"""
self.visit_url( "%s/history/share" % self.url )
if check_str:
self.check_page_for_string( check_str )
tc.fv( 'share', 'email', email )
tc.submit( 'share_button' )
if check_str_after_submit:
self.check_page_for_string( check_str_after_submit )
if check_str_after_submit2:
self.check_page_for_string( check_str_after_submit2 )
if action:
# If we have an action, then we are sharing datasets with users that do not have access permissions on them
tc.fv( '1', 'action', action )
tc.submit( "share_proceed_button" )
if action_check_str:
self.check_page_for_string( action_check_str )
tc.fv( 'share_restricted', 'action', action )
tc.submit( "share_restricted_button" )
if action_check_str_after_submit:
self.check_page_for_string( action_check_str_after_submit )
self.home()
def share_histories_with_users( self, ids, emails, check_str1='', check_str2='',
check_str_after_submit='', action=None, action_check_str=None ):
"""Share one or more histories with one or more different users"""
self.visit_url( "%s/history/list?id=%s&operation=Share" % ( self.url, ids ) )
if check_str1:
self.check_page_for_string( check_str1 )
if check_str2:
self.check_page_for_string( check_str2 )
tc.fv( 'share', 'email', emails )
tc.submit( 'share_button' )
if check_str_after_submit:
self.check_page_for_string( check_str_after_submit )
if action:
# If we have an action, then we are sharing datasets with users that do not have access permissions on them
tc.fv( 'share_restricted', 'action', action )
tc.submit( "share_restricted_button" )
if action_check_str:
self.check_page_for_string( action_check_str )
self.home()
def unshare_history( self, history_id, user_id, check_str1='', check_str2='', check_str_after_submit='' ):
"""Unshare a history that has been shared with another user"""
self.visit_url( "%s/history/list?id=%s&operation=sharing" % ( self.url, history_id ) )
if check_str1:
self.check_page_for_string( check_str1 )
if check_str2:
self.check_page_for_string( check_str2 )
self.visit_url( "%s/history/sharing?unshare_user=%s&id=%s" % ( self.url, user_id, history_id ) )
self.home()
def switch_history( self, id='', name='' ):
"""Switches to a history in the current list of histories"""
data_list = self.get_histories()
data_list = self.get_histories_as_data_list()
self.assertTrue( data_list )
if not id:
history = history_list[0]
@@ -227,6 +278,7 @@ class TwillTestCase( unittest.TestCase ):
self.check_history_for_string( name )
self.home()
def view_stored_active_histories( self, check_str='' ):
self.home()
self.visit_page( "history/list" )
self.check_page_for_string( 'Stored histories' )
self.check_page_for_string( '<input type="checkbox" name="id" value=' )
@@ -237,6 +289,7 @@ class TwillTestCase( unittest.TestCase ):
self.check_page_for_string( check_str )
self.home()
def view_stored_deleted_histories( self, check_str='' ):
self.home()
self.visit_page( "history/list?f-deleted=True" )
self.check_page_for_string( 'Stored histories' )
self.check_page_for_string( '<input type="checkbox" name="id" value=' )
@@ -244,6 +297,50 @@ class TwillTestCase( unittest.TestCase ):
if check_str:
self.check_page_for_string( check_str )
self.home()
def view_shared_histories( self, check_str='', check_str2='' ):
self.home()
self.visit_page( "history/list_shared" )
if check_str:
self.check_page_for_string( check_str )
if check_str2:
self.check_page_for_string( check_str2 )
self.home()
def clone_history( self, history_id, check_str1='' ):
self.home()
self.visit_page( "history/clone?id=%s" % history_id )
if check_str1:
self.check_page_for_string( check_str1 )
self.home()
def enable_import_via_link( self, history_id, check_str='', check_str_after_submit='' ):
self.home()
self.visit_page( "history/list?operation=sharing&id=%s" % history_id )
if check_str:
self.check_page_for_string( check_str )
# twill barfs on this form, possibly because it contains no fields, but not sure.
# In any case, we have to mimic the form submission
self.home()
self.visit_page( 'history/sharing?id=%s&enable_import_via_link=True' % history_id )
if check_str_after_submit:
self.check_page_for_string( check_str_after_submit )
self.home()
def disable_import_via_link( self, history_id, check_str='', check_str_after_submit='' ):
self.home()
self.visit_page( "history/list?operation=sharing&id=%s" % history_id )
if check_str:
self.check_page_for_string( check_str )
# twill barfs on this form, possibly because it contains no fields, but not sure.
# In any case, we have to mimic the form submission
self.home()
self.visit_page( 'history/sharing?id=%s&disable_import_via_link=True' % history_id )
if check_str_after_submit:
self.check_page_for_string( check_str_after_submit )
self.home()
def import_history_via_url( self, history_id, email, check_str_after_submit='' ):
self.home()
self.visit_page( "history/imp?&id=%s" % history_id )
if check_str_after_submit:
self.check_page_for_string( check_str_after_submit )
self.home()
# Functions associated with datasets (history items) and meta data
def get_job_stderr( self, id ):
@@ -260,7 +357,7 @@ class TwillTestCase( unittest.TestCase ):
def check_metadata_for_string( self, patt, hid=None ):
"""Looks for 'patt' in the edit page when editing a dataset"""
data_list = self.get_history()
data_list = self.get_history_as_data_list()
self.assertTrue( data_list )
if hid is None: # take last hid
elem = data_list[-1]
@@ -276,7 +373,7 @@ class TwillTestCase( unittest.TestCase ):
except:
raise AssertionError, "Invalid hid '%s' - must be int" % hid
hid = str(hid)
data_list = self.get_history()
data_list = self.get_history_as_data_list()
self.assertTrue( data_list )
elems = [ elem for elem in data_list if elem.get( 'hid' ) == hid ]
self.assertEqual( len( elems ), 1 )
@@ -291,7 +388,7 @@ class TwillTestCase( unittest.TestCase ):
except:
raise AssertionError, "Invalid hid '%s' - must be int" % hid
hid = str( hid )
data_list = self.get_history( show_deleted=show_deleted )
data_list = self.get_history_as_data_list( show_deleted=show_deleted )
self.assertTrue( data_list )
elems = [ elem for elem in data_list if elem.get( 'hid' ) == hid ]
self.assertEqual( len( elems ), 1 )
@@ -348,7 +445,8 @@ class TwillTestCase( unittest.TestCase ):
tc.submit( 'change' )
self.check_page_for_string( 'Edit Attributes' )
self.home()
def copy_history_item( self, source_dataset_ids='', target_history_ids=[], all_target_history_ids=[], deleted_history_ids=[] ):
def copy_history_item( self, source_dataset_ids='', target_history_ids=[], all_target_history_ids=[],
deleted_history_ids=[] ):
"""Copy 1 or more history_dataset_associations to 1 or more histories"""
self.home()
self.visit_url( "%s/dataset/copy_datasets?source_dataset_ids=%s" % ( self.url, source_dataset_ids ) )
@@ -371,31 +469,28 @@ class TwillTestCase( unittest.TestCase ):
check_str = '%d datasets copied to %d histories.' % ( no_source_ids, len( target_history_ids ) )
self.check_page_for_string( check_str )
self.home()
def get_dataset_ids_in_history( self ):
"""Returns the ids of datasets in a history"""
data_list = self.get_history()
def get_hids_in_history( self ):
"""Returns the list of hid values for items in a history"""
data_list = self.get_history_as_data_list()
hids = []
for elem in data_list:
hid = elem.get('hid')
hids.append(hid)
return hids
def get_dataset_ids_in_histories( self ):
"""Returns the ids of datasets in all histories"""
data_list = self.get_histories()
def get_hids_in_histories( self ):
"""Returns the list of hids values for items in all histories"""
data_list = self.get_histories_as_data_list()
hids = []
for elem in data_list:
hid = elem.get('hid')
hids.append(hid)
return hids
def verify_dataset_correctness( self, filename, hid=None, wait=True ):
"""Verifies that the attributes and contents of a history item meet expectations"""
if wait: self.wait() #wait for job to finish
data_list = self.get_history()
if wait:
self.wait() #wait for job to finish
data_list = self.get_history_as_data_list()
self.assertTrue( data_list )
if hid is None: # take last hid
elem = data_list[-1]
hid = str( elem.get('hid') )
@@ -404,10 +499,8 @@ class TwillTestCase( unittest.TestCase ):
elems = [ elem for elem in data_list if elem.get('hid') == hid ]
self.assertTrue( len(elems) == 1 )
elem = elems[0]
self.assertTrue( hid )
self._assert_dataset_state( elem, 'ok' )
if self.is_zipped( filename ):
errmsg = 'History item %s is a zip archive which includes invalid files:\n' % hid
zip_file = zipfile.ZipFile( filename, "r" )
@@ -422,6 +515,7 @@ class TwillTestCase( unittest.TestCase ):
else:
local_name = self.get_filename( filename )
temp_name = self.get_filename( 'temp_%s' % filename )
self.home()
self.visit_page( "display?hid=" + hid )
data = self.last_page()
file( temp_name, 'wb' ).write(data)
@@ -455,7 +549,7 @@ class TwillTestCase( unittest.TestCase ):
def verify_genome_build( self, dbkey='hg17' ):
"""Verifies that the last used genome_build at history id 'hid' is as expected"""
data_list = self.get_history()
data_list = self.get_history_as_data_list()
self.assertTrue( data_list )
elems = [ elem for elem in data_list ]
elem = elems[-1]
+2 -2
View File
@@ -24,7 +24,7 @@ log = logging.getLogger( __name__ )
# server (for running the tests against a running instance)
default_galaxy_test_host = "localhost"
default_galaxy_test_port = "9999"
default_galaxy_test_port = "8777"
default_galaxy_locales = 'en'
galaxy_test_file_dir = "test-data"
server = None
@@ -63,10 +63,10 @@ def setup():
default_cluster_job_runner = os.environ['GALAXY_TEST_DEF_RUNNER']
else:
default_cluster_job_runner = 'local:///'
app = UniverseApplication( job_queue_workers = 5,
start_job_runners = start_job_runners,
default_cluster_job_runner = default_cluster_job_runner,
id_secret = 'changethisinproductiontoo',
template_path = "templates",
database_connection = database_connection,
file_path = file_path,
+7 -5
View File
@@ -6,10 +6,12 @@ from base.twilltestcase import TwillTestCase
class AnalysisDNAseHSSFlankedGenes( TwillTestCase ):
def test_get_DNAseHSS_flanked_genes( self ):
self.login()
self.new_history()
global history1
history1 = galaxy.model.History.query() \
self.logout()
self.login( email='test@bx.psu.edu' )
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
self.new_history( name='DNAseHSS_flanked_genes' )
history1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
track_params = dict(
db="hg17",
@@ -85,5 +87,5 @@ class AnalysisDNAseHSSFlankedGenes( TwillTestCase ):
self.run_tool( 'Filter1', input="4", cond="c17==1000" )
self.wait()
self.verify_dataset_correctness( 'filteredJoinedFlanksDNAse.dat' )
self.delete_history()
self.delete_history( self.security.encode_id( history1.id ) )
self.logout()
+15 -10
View File
@@ -6,8 +6,12 @@ class UploadData( TwillTestCase ):
def test_000_upload_files_from_disk( self ):
"""Test uploading data files from disk"""
self.logout()
self.login( email='tst@bx.psu.edu' )
history1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.login( email='test@bx.psu.edu' )
global admin_user
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
history1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.upload_file( '1.bed' )
hda1 = galaxy.model.HistoryDatasetAssociation.query() \
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
@@ -38,24 +42,28 @@ class UploadData( TwillTestCase ):
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
assert hda6 is not None, "Problem retrieving hda6 from database"
self.verify_dataset_correctness( '1.scf.zip', hid=str( hda6.hid ) )
self.delete_history( id=str( history1.id ) )
self.delete_history( id=self.security.encode_id( history1.id ) )
def test_005_url_paste( self ):
"""Test url paste behavior"""
# Deleting the current history should have created a new history
self.check_history_for_string( 'Your history is empty' )
history2 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history2 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.upload_url_paste( 'hello world' )
self.check_history_for_string( 'Pasted Entry' )
self.check_history_for_string( 'hello world' )
self.upload_url_paste( u'hello world' )
self.check_history_for_string( 'Pasted Entry' )
self.check_history_for_string( 'hello world' )
self.delete_history( id=str( history2.id ) )
self.delete_history( id=self.security.encode_id( history2.id ) )
def test_010_upload_encode_data( self ):
"""Test uploading encode data"""
# Deleting the current history should have created a new history
self.check_history_for_string( 'Your history is empty' )
history3 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history3 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.run_tool( 'encode_import_chromatin_and_chromosomes1', hg17=['cc.EarlyRepSeg.20051216.bed'] )
self.wait()
hda7 = galaxy.model.HistoryDatasetAssociation.query() \
@@ -68,7 +76,4 @@ class UploadData( TwillTestCase ):
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
assert hda8 is not None, "Problem retrieving hda8 from database"
self.verify_dataset_correctness( 'sc_3D_cds.bed', hid=str( hda8.hid ) )
self.delete_history( id=str( history3.id ) )
def test_015_reset_data_for_later_test_runs( self ):
"""Reseting data to enable later test runs to pass"""
self.logout()
self.delete_history( id=self.security.encode_id( history3.id ) )
+447 -228
View File
@@ -5,12 +5,11 @@ from base.twilltestcase import *
class TestHistory( TwillTestCase ):
def test_000_history_options_when_not_logged_in( self ):
"""Testing history options when not logged in"""
def test_000_history_behavior_between_logout_login( self ):
"""Testing history behavior between logout and login"""
self.logout()
check_str = 'logged in</a> to store or switch histories.'
self.history_options( check_str=check_str )
# Make sure we have created the following accounts
self.history_options()
# Make sure we have created the following 4 accounts
self.login( email='test1@bx.psu.edu' )
global regular_user1
regular_user1 = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test1@bx.psu.edu' ).first()
@@ -25,14 +24,12 @@ class TestHistory( TwillTestCase ):
global regular_user3
regular_user3 = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test3@bx.psu.edu' ).first()
assert regular_user3 is not None, 'Problem retrieving user with email "test3@bx.psu.edu" from the database'
def test_005_deleting_histories( self ):
"""Testing deleting histories"""
self.logout()
self.login( email='test@bx.psu.edu' )
global admin_user
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).first()
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
assert admin_user is not None, 'Problem retrieving user with email "test@bx.psu.edu" from the database'
# Get the admin_user private role
# Get the admin_user private role for later use
global admin_user_private_role
admin_user_private_role = None
for role in admin_user.all_roles():
@@ -41,27 +38,48 @@ class TestHistory( TwillTestCase ):
break
if not admin_user_private_role:
raise AssertionError( "Private role not found for user '%s'" % admin_user.email )
latest_history = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert latest_history is not None, "Problem retrieving latest history from database"
assert not latest_history.deleted, "After login, associated history is deleted"
self.delete_history( str( latest_history.id ) )
latest_history.refresh()
if not latest_history.deleted:
raise AssertionError, "Problem deleting history id %d" % latest_history.id
historyA = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert historyA is not None, "Problem retrieving historyA from database"
assert not historyA.deleted, "After login, historyA is deleted"
# Make sure the last used history is set for the next session after login
self.logout()
self.login( email=admin_user.email )
historyB = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert historyB is not None, "Problem retrieving historyB from database"
assert historyA.id == historyB.id, "After the same user logged out and back in, their last used history was not associated with their new session"
def test_005_deleting_histories( self ):
"""Testing deleting histories"""
# Logged in as admin_user
historyB = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert historyB is not None, "Problem retrieving historyB from database"
self.delete_history( self.security.encode_id( historyB.id ) )
historyB.refresh()
if not historyB.deleted:
raise AssertionError, "Problem deleting history id %d" % historyB.id
# Since we deleted the current history, make sure the history frame was refreshed
self.check_history_for_string( 'Your history is empty.' )
# We'll now test deleting a list of histories
# After deleting the current history, a new one should have been created
global history1
history1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history1 is not None, "Problem retrieving history1 from database"
self.upload_file( '1.bed', dbkey='hg18' )
self.new_history( name=urllib.quote( 'history2' ) )
global history2
history2 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history2 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history2 is not None, "Problem retrieving history2 from database"
self.upload_file( '2.bed', dbkey='hg18' )
ids = '%s,%s' % ( str( history1.id ), str( history2.id ) )
ids = '%s,%s' % ( self.security.encode_id( history1.id ), self.security.encode_id( history2.id ) )
self.delete_history( ids )
# Since we deleted the current history, make sure the history frame was refreshed
self.check_history_for_string( 'Your history is empty.' )
@@ -87,116 +105,153 @@ class TestHistory( TwillTestCase ):
raise AssertionError, "Problem deleting history id %d" % history2.id
if not history2.default_permissions:
raise AssertionError, "Default permissions were incorrectly deleted from the db for history id %d when it was deleted" % history2.id
def test_010_history_options_when_logged_in( self ):
"""Testing history options when logged in"""
self.history_options()
def test_015_history_rename( self ):
# Current history is empty
self.history_options( user=True )
def test_010_history_rename( self ):
"""Testing renaming a history"""
# Logged in as admin_user
global history3
history3 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history3 = galaxy.model.History \
.filter( galaxy.model.History.table.c.deleted==False ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history3 is not None, "Problem retrieving history3 from database"
if history3.deleted:
raise AssertionError, "History id %d deleted when it should not be" % latest_history.id
self.rename_history( str( history3.id ), history3.name, new_name=urllib.quote( 'history 3' ) )
def test_020_history_list( self ):
"""Testing viewing previously stored histories"""
self.view_stored_active_histories()
def test_025_history_share( self ):
"""Testing sharing histories containing only public datasets"""
self.rename_history( self.security.encode_id( history3.id ), history3.name, new_name=urllib.quote( 'history 3' ) )
history3.refresh()
def test_015_history_list( self ):
"""Testing viewing previously stored active histories"""
# Logged in as admin_user
self.view_stored_active_histories()
def test_020_share_current_history( self ):
"""Testing sharing the current history which contains only public datasets"""
# Logged in as admin_user
# Test sharing an empty history - current history is history3
self.share_current_history( regular_user1.email,
check_str=history3.name,
check_str_after_submit='You cannot share an empty history.' )
# Make history3 sharable by adding a dataset
self.upload_file( '1.bed', dbkey='hg18' )
# Test sharing a history with yourself
check_str = "You can't send histories to yourself."
self.share_history( str( history3.id ), 'test@bx.psu.edu', check_str )
# Share a history with 1 valid user
check_str = 'Histories (%s) have been shared with: %s' % ( history3.name, regular_user1.email )
self.share_history( str( history3.id ), regular_user1.email, check_str )
# We need to keep track of all shared histories so they can later be deleted
global history3_copy1
history3_copy1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history3_copy1 is not None, "Problem retrieving history3_copy1 from database"
# Current history is no longer empty
self.history_options( user=True, active_datasets=True, activatable_datasets=True )
# Test sharing history3 with yourself
self.share_current_history( admin_user.email,
check_str=history3.name,
check_str_after_submit='You cannot send histories to yourself.' )
# Share history3 with 1 valid user
self.share_current_history( regular_user1.email,
check_str=history3.name,
check_str_after_submit='History (%s) now shared with: 1 users' % history3.name )
# Check out list of histories to make sure history3 was shared
self.view_stored_active_histories( check_str='operation=sharing&id=%s">shared' % self.security.encode_id( history3.id ) )
# Enable importing history3 via a URL
self.enable_import_via_link( self.security.encode_id( history3.id ),
check_str='Unshare',
check_str_after_submit='Send the following URL to users' )
# Make sure history3 is now import-able
history3.refresh()
if not history3.importable:
raise AssertionError, "History 3 is not marked as importable after enable_import_via_link"
# Try importing history3
self.import_history_via_url( self.security.encode_id( history3.id ),
admin_user.email,
check_str_after_submit='You cannot import your own history.' )
# Disable the import link for history3
self.disable_import_via_link( self.security.encode_id( history3.id ),
check_str='Send the following URL to users',
check_str_after_submit='Enable import via link' )
# Try importing history3 after disabling the URL
self.import_history_via_url( self.security.encode_id( history3.id ),
admin_user.email,
check_str_after_submit='The owner of this history has disabled imports via this link.' )
# Test sharing history3 with an invalid user
self.share_current_history( 'jack@jill.com',
check_str_after_submit='jack@jill.com is not a valid Galaxy user.' )
def test_025_delete_shared_current_history( self ):
"""Testing deleting the current history after it was shared"""
# Logged in as admin_user
self.delete_current_history( check_str="History (%s) has been shared with others, unshare it before deleting it." % history3.name )
def test_030_clone_shared_history( self ):
"""Testing cloning a shared history"""
# logged in as admin user
self.logout()
self.login( email=regular_user1.email )
check_str = '%s from %s' % ( history3.name, admin_user.email )
# Shared history3 affects history options
self.history_options( user=True, histories_shared_by_others=True )
# Shared history3 should be in regular_user1's list of shared histories
self.view_shared_histories( check_str=history3.name, check_str2=admin_user.email )
self.clone_history( self.security.encode_id( history3.id ),
check_str1='is now included in your list of stored histories.' )
global history3_clone1
history3_clone1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history3_clone1 is not None, "Problem retrieving history3_clone1 from database"
# Check list of histories to make sure shared history3 was cloned
check_str = "Clone of '%s' shared by '%s'" % ( history3.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
# Need to delete history3_copy1
self.delete_history( id=str( history3_copy1.id ) )
def test_035_clone_current_history( self ):
"""Testing cloning the current history"""
# logged in as regular_user1
self.logout()
self.login( email=admin_user.email )
# Test sharing a history with an invalid user
email = 'jack@jill.com'
check_str = '%s is not a valid Galaxy user.' % email
self.share_history( str( history3.id ), email, check_str )
# Test sharing multiple histories with multiple users
self.clone_history( self.security.encode_id( history3.id ),
check_str1='is now included in your list of stored histories.' )
global history3_clone2
history3_clone2 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history3_clone2 is not None, "Problem retrieving history3_clone2 from database"
# Check list of histories to make sure shared history3 was cloned
self.view_stored_active_histories( check_str="Clone of '%s'" % history3.name )
def test_040_sharing_mulitple_histories_with_multiple_users( self ):
"""Testing sharing multiple histories containing only public datasets with multiple users"""
# Logged in as admin_user
self.new_history()
global history4
history4 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history4 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history4 is not None, "Problem retrieving history4 from database"
self.rename_history( str( history4.id ), history4.name, new_name=urllib.quote( 'history 4' ) )
self.rename_history( self.security.encode_id( history4.id ), history4.name, new_name=urllib.quote( 'history 4' ) )
history4.refresh()
self.upload_file( '2.bed', dbkey='hg18' )
id = '%s,%s' % ( str( history3.id ), str( history4.id ) )
name = '%s,%s' % ( history3.name, history4.name )
email = '%s,%s' % ( regular_user2.email, regular_user3.email )
check_str = 'Histories (%s) have been shared with: %s' % ( name, email )
self.share_history( id, email, check_str )
# We need to keep track of all shared histories so they can later be deleted
history3_copy_name = "%s from %s" % ( history3.name, admin_user.email )
history3_to_use_for_regular_user2 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history3_copy_name,
galaxy.model.History.table.c.user_id==regular_user2.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history3_to_use_for_regular_user2 is not None, "Problem retrieving history3_to_use_for_regular_user2 from database"
history3_to_use_for_regular_user3 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history3_copy_name,
galaxy.model.History.table.c.user_id==regular_user3.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history3_to_use_for_regular_user3 is not None, "Problem retrieving history3_to_use_for_regular_user3 from database"
history4_copy_name = "%s from %s" % ( history4.name, admin_user.email )
history4_to_use_for_regular_user2 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history4_copy_name,
galaxy.model.History.table.c.user_id==regular_user2.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history4_to_use_for_regular_user2 is not None, "Problem retrieving history4_to_use_for_regular_user2 from database"
history4_to_use_for_regular_user3 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history4_copy_name,
galaxy.model.History.table.c.user_id==regular_user3.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history4_to_use_for_regular_user3 is not None, "Problem retrieving history4_to_use_for_regular_user3 from database"
ids = '%s,%s' % ( self.security.encode_id( history3.id ), self.security.encode_id( history4.id ) )
emails = '%s,%s' % ( regular_user2.email, regular_user3.email )
check_str_after_submit = 'History (%s) now shared with: 3 users.' % history3.name
self.share_histories_with_users( ids,
emails,
check_str1='Share 2 histories',
check_str2=history4.name,
check_str_after_submit=check_str_after_submit )
self.logout()
self.login( email=regular_user2.email )
check_str = '%s from %s' % ( history3.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
check_str = '%s from %s' % ( history4.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
# Need to delete the copied histories, so later test runs are valid
self.delete_history( id=str( history3_to_use_for_regular_user2.id ) )
self.delete_history( id=str( history4_to_use_for_regular_user2.id ) )
# Shared history3 should be in regular_user2's list of shared histories
self.view_shared_histories( check_str=history3.name, check_str2=admin_user.email )
self.logout()
self.login( email=regular_user3.email )
check_str = '%s from %s' % ( history3.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
check_str = '%s from %s' % ( history4.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
# Need to delete the copied histories, so later test runs are valid
self.delete_history( id=str( history3_to_use_for_regular_user3.id ) )
self.delete_history( id=str( history4_to_use_for_regular_user3.id ) )
# Shared history3 should be in regular_user3's list of shared histories
self.view_shared_histories( check_str=history3.name, check_str2=admin_user.email )
def test_045_change_permissions_on_current_history( self ):
"""Testing changing permissions on the current history"""
# Logged in as regular_user3
self.logout()
self.login( email=admin_user.email )
def test_030_change_permissions_on_current_history( self ):
"""Testing changing permissions on the current history"""
# Current history is history4
self.new_history()
global history5
history5 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history5 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5 is not None, "Problem retrieving history5 from database"
self.rename_history( str( history5.id ), history5.name, new_name=urllib.quote( 'history5' ) )
self.rename_history( self.security.encode_id( history5.id ), history5.name, new_name=urllib.quote( 'history 5' ) )
# Current history is hostory5
history5.refresh()
# Due to the limitations of twill ( not functional with the permissions forms ), we're forced
# to do this manually. At this point, we just want to restrict the access permission on history5
@@ -205,81 +260,126 @@ class TestHistory( TwillTestCase ):
access_action = galaxy.model.Dataset.permitted_actions.DATASET_ACCESS.action
dhp = galaxy.model.DefaultHistoryPermissions( history5, access_action, admin_user_private_role )
dhp.flush()
history5.refresh()
global history5_default_permissions
history5_default_permissions = [ dhp.action for dhp in history5.default_permissions ]
# Sort for later comparison
history5_default_permissions.sort()
self.upload_file( '1.bed', dbkey='hg18' )
history5_dataset1 = None
for hda in history5.datasets:
if hda.name == '1.bed':
history5_dataset1 = hda.dataset
break
assert history5_dataset1 is not None, "Problem retrieving history5_dataset1 from the database"
# The permissions on the dataset should be restricted from sharing with anyone due to the
# inherited history permissions
restricted = False
for action in history5_dataset1.actions:
if action.action == access_action:
restricted = True
break
if not restricted:
raise AssertionError, "The 'access' permission is not set for history5_dataset1.actions"
def test_035_sharing_history_by_making_datasets_public( self ):
"""Testing sharing a restricted history by making the datasets public"""
# We're still logged in as admin_user.email
check_str = 'The following datasets can be shared with %s by updating their permissions' % regular_user1.email
action_check_str = 'Histories (%s) have been shared with: %s' % ( history5.name, regular_user1.email )
self.share_history( str( history5.id ), regular_user1.email, check_str, action='public', action_check_str=action_check_str )
history5_copy1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_copy1 is not None, "Problem retrieving history5_copy1 from database"
self.logout()
self.login( email=regular_user1.email )
self.visit_url( "%s/history/list" % self.url )
self.check_page_for_string( history5_copy1.name )
# Need to delete history5_copy1 on the history list page for regular_user1
self.delete_history( id=str( history5_copy1.id ) )
dataset_permissions = [ a.action for a in history5_dataset1.actions ]
dataset_permissions.sort()
if dataset_permissions != history5_default_permissions:
err_msg = "Dataset permissions for history5_dataset1 (%s) were not correctly inherited from history permissions (%s)" \
% ( str( dataset_permissions ), str( history5_default_permissions ) )
raise AssertionError, err_msg
# Make sure when we logout and login, the history default permissions are preserved
self.logout()
self.login( email=admin_user.email )
def test_040_sharing_history_by_making_new_sharing_role( self ):
history5.refresh()
current_history_permissions = [ dhp.action for dhp in history5.default_permissions ]
current_history_permissions.sort()
if current_history_permissions != history5_default_permissions:
raise AssertionError, "With logout and login, the history default permissions are not preserved"
def test_050_sharing_restricted_history_by_making_datasets_public( self ):
"""Testing sharing a restricted history by making the datasets public"""
# Logged in as admin_user
action_check_str = 'The following datasets can be shared with %s by updating their permissions' % regular_user1.email
action_check_str_after_submit = 'History (%s) now shared with: 1 users.' % history5.name
# Current history is history5
self.share_current_history( regular_user1.email,
action='public',
action_check_str=action_check_str,
action_check_str_after_submit=action_check_str_after_submit )
self.logout()
self.login( email=regular_user1.email )
# Shared history5 should be in regular_user1's list of shared histories
self.view_shared_histories( check_str=history5.name, check_str2=admin_user.email )
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
check_str1='is now included in your list of stored histories.' )
global history5_clone1
history5_clone1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_clone1 is not None, "Problem retrieving history5_clone1 from database"
# Check list of histories to make sure shared history5 was cloned
self.view_stored_active_histories( check_str="Clone of '%s'" % history5.name )
# Make sure the dataset is accessible
self.switch_history( id=self.security.encode_id( history5_clone1.id ), name=history5_clone1.name )
self.check_history_for_string( 'chr1' )
self.logout()
self.login( email=admin_user.email )
def test_055_sharing_restricted_history_by_making_new_sharing_role( self ):
"""Testing sharing a restricted history by associating a new sharing role with protected datasets"""
self.switch_history( id=str( history5.id ), name=history5.name )
# At this point, history5 should have 1 item, 1.bed, which is public. We'll add another
# item which will be private to admin_user due to the permissions on history5
self.upload_file( '2.bed', dbkey='hg18' )
check_str = 'The following datasets can be shared with %s with no changes' % regular_user1.email
check_str2 = 'The following datasets can be shared with %s by updating their permissions' % regular_user1.email
action_check_str = 'Histories (%s) have been shared with: %s' % ( history5.name, regular_user1.email )
self.share_history( str( history5.id ),
regular_user1.email,
check_str,
check_str2=check_str2,
action='private',
action_check_str=action_check_str )
history5_copy2 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_copy2 is not None, "Problem retrieving history5_copy2 from database"
check_str_after_submit = 'The following datasets can be shared with %s with no changes' % regular_user2.email
check_str_after_submit2 = 'The following datasets can be shared with %s by updating their permissions' % regular_user2.email
action_check_str_after_submit = 'History (%s) now shared with: 2 users.' % history5.name
self.share_current_history( regular_user2.email,
check_str_after_submit=check_str_after_submit,
check_str_after_submit2=check_str_after_submit2,
action='private',
action_check_str_after_submit=action_check_str_after_submit )
# We should now have a new sharing role
global sharing_role
role_name = 'Sharing role for: %s, %s' % ( admin_user.email, regular_user1.email )
role_name = 'Sharing role for: %s, %s' % ( admin_user.email, regular_user2.email )
sharing_role = galaxy.model.Role.filter( galaxy.model.Role.table.c.name==role_name ).first()
if not sharing_role:
# May have created a sharing role in a previous functional test suite from the opposite direction.
role_name = 'Sharing role for: %s, %s' % ( regular_user1.email, admin_user.email )
role_name = 'Sharing role for: %s, %s' % ( regular_user2.email, admin_user.email )
sharing_role = galaxy.model.Role.filter( and_( galaxy.model.Role.table.c.type==role_type,
galaxy.model.Role.table.c.name==role_name ) ).first()
if not sharing_role:
raise AssertionError( "Privately sharing a dataset did not properly create a sharing role" )
# The DATASET_ACCESS permission on 2.bed was originally associated with admin_user's private role.
# Since we created a new sharing role for 2.bed, the original permission should have been eliminated,
# replaced with the sharing role.
history5_dataset2 = None
for hda in history5.datasets:
if hda.name == '2.bed':
history5_dataset2 = hda.dataset
break
assert history5_dataset2 is not None, "Problem retrieving history5_dataset2 from the database"
for dp in history5_dataset2.actions:
if dp.action == 'access':
assert dp.role == sharing_role, "Associating new sharing role with history5_dataset2 did not correctly eliminate original DATASET ACCESS permissions"
self.logout()
self.login( email=regular_user1.email )
self.visit_url( "%s/history/list" % self.url )
self.check_page_for_string( history5_copy2.name )
self.switch_history( id=str( history5_copy2.id ), name=history5_copy2.name )
self.login( email=regular_user2.email )
# Shared history5 should be in regular_user2's list of shared histories
self.view_shared_histories( check_str=history5.name, check_str2=admin_user.email )
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
check_str1='is now included in your list of stored histories.' )
global history5_clone2
history5_clone2 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_clone2 is not None, "Problem retrieving history5_clone2 from database"
# Check list of histories to make sure shared history3 was cloned
self.view_stored_active_histories( check_str="Clone of '%s'" % history5.name )
# Make sure the dataset is accessible
self.switch_history( id=self.security.encode_id( history5_clone2.id ), name=history5_clone2.name )
# Make sure both datasets are in the history
self.check_history_for_string( '1.bed' )
self.check_history_for_string( '2.bed' )
# Get both new hdas from the db that were created for the shared history
hda_1_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_copy2.id,
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone2.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='1.bed' ) ) \
.first()
assert hda_1_bed is not None, "Problem retrieving hda_1_bed from database"
hda_2_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_copy2.id,
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone2.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='2.bed' ) ) \
.first()
assert hda_2_bed is not None, "Problem retrieving hda_2_bed from database"
@@ -287,67 +387,108 @@ class TestHistory( TwillTestCase ):
self.display_history_item( str( hda_1_bed.id ), check_str='chr1' )
# Make sure 2.bed is accessible since it is associated with a sharing role
self.display_history_item( str( hda_2_bed.id ), check_str='chr1' )
# Need to delete history5_copy2 on the history list page for regular_user1
self.delete_history( id=str( history5_copy2.id ) )
def test_045_sharing_private_history_with_multiple_users_by_changing_no_permissions( self ):
# Delete the clone so the next test will be valid
self.delete_history( id=self.security.encode_id( history5_clone2.id ) )
def test_060_sharing_restricted_history_with_multiple_users_by_changing_no_permissions( self ):
"""Testing sharing a restricted history with multiple users, making no permission changes"""
# Logged in as regular_user2
self.logout()
self.login( email=admin_user.email )
# History5 can be shared with any user, since it contains a public dataset. However, only
# regular_user1 should be able to access history5's 2.bed dataset since it is associated with a
# sharing role, and regular_user2 should be able to access history5's 1.bed, but not 2.bed even
# History5 can be shared with any user, since it contains a public dataset ( 1.bed ). However, only
# regular_user2 should be able to access history5's 2.bed dataset since it is associated with a
# sharing role, and regular_user3 should be able to access history5's 1.bed, but not 2.bed even
# though they can see it in their shared history.
self.switch_history( id=str( history5.id ), name=history5.name )
email = '%s,%s' % ( regular_user1.email, regular_user2.email )
check_str = 'The following datasets can be shared with %s with no changes' % email
check_str2 = 'The following datasets can be shared with %s by updating their permissions' % email
action_check_str = 'Histories (%s) have been shared with: %s' % ( history5.name, regular_user1.email )
self.share_history( str( history5.id ),
email,
check_str,
check_str2=check_str2,
action='share',
action_check_str=action_check_str )
# We need to keep track of all shared histories so they can later be deleted
history5_copy_name = "%s from %s" % ( history5.name, admin_user.email )
history5_to_use_for_regular_user1 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history5_copy_name,
galaxy.model.History.table.c.user_id==regular_user1.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history5_to_use_for_regular_user1 is not None, "Problem retrieving history5_to_use_for_regular_user1 from database"
history5_to_use_for_regular_user2 = galaxy.model.History \
.filter( and_( galaxy.model.History.table.c.name==history5_copy_name,
galaxy.model.History.table.c.user_id==regular_user2.id,
galaxy.model.History.table.c.deleted==False ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history5_to_use_for_regular_user2 is not None, "Problem retrieving history5_to_use_for_regular_user2 from database"
# We first need to unshare history5 from regular_user2 so that we can re-share it.
self.unshare_history( self.security.encode_id( history5.id ),
self.security.encode_id( regular_user2.id ),
check_str1=regular_user1.email,
check_str2=regular_user2.email )
# Make sure the history was unshared correctly
self.logout()
self.login( email=regular_user1.email )
check_str = '%s from %s' % ( history5.name, admin_user.email )
self.view_stored_active_histories( check_str=check_str )
self.switch_history( id=str( history5_to_use_for_regular_user1.id ), name=history5_to_use_for_regular_user1.name )
self.check_history_for_string( '1.bed' )
self.check_history_for_string( '2.bed' )
# Need to delete the copied histories, so later test runs are valid
self.delete_history( id=str( history5_to_use_for_regular_user1.id ) )
self.logout()
# Make sure test2@bx.psu.edu received a copy of history5, with only 1.bed accessible
self.login( email=regular_user2.email )
self.view_stored_active_histories( check_str=check_str )
self.switch_history( id=str( history5_to_use_for_regular_user2.id ), name=history5_to_use_for_regular_user2.name )
self.visit_page( "root/history_options" )
try:
self.check_page_for_string( 'List</a> histories shared with you by others' )
raise AssertionError, "history5 still shared with regular_user2 after unshaing it with that user."
except:
pass
self.logout()
self.login( admin_user.email )
email = '%s,%s' % ( regular_user2.email, regular_user3.email )
check_str_after_submit = 'The following datasets can be shared with %s with no changes' % email
check_str_after_submit2 = 'The following datasets can be shared with %s by updating their permissions' % email
# history5 will be shared with regular_user1, regular_user2 and regular_user3
action_check_str_after_submit = 'History (%s) now shared with: 3 users.' % history5.name
self.share_current_history( email,
check_str_after_submit=check_str_after_submit,
check_str_after_submit2=check_str_after_submit2,
action='share_anyway',
action_check_str_after_submit=action_check_str_after_submit )
# Check security on clone of history5 for regular_user2
self.logout()
self.login( email=regular_user2.email )
# Shared history5 should be in regular_user2's list of shared histories
self.view_shared_histories( check_str=history5.name, check_str2=admin_user.email )
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
check_str1='is now included in your list of stored histories.' )
global history5_clone3
history5_clone3 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_clone3 is not None, "Problem retrieving history5_clone3 from database"
# Check list of histories to make sure shared history3 was cloned
self.view_stored_active_histories( check_str="Clone of '%s'" % history5.name )
# Make sure the dataset is accessible
self.switch_history( id=self.security.encode_id( history5_clone3.id ), name=history5_clone3.name )
# Make sure both datasets are in the history
self.check_history_for_string( '1.bed' )
self.check_history_for_string( '2.bed' )
# Get both new hdas from the db that were created for the shared history
hda_1_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_to_use_for_regular_user1.id,
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone3.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='1.bed' ) ) \
.first()
assert hda_1_bed is not None, "Problem retrieving hda_1_bed from database"
hda_2_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_to_use_for_regular_user1.id,
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone3.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='2.bed' ) ) \
.first()
assert hda_2_bed is not None, "Problem retrieving hda_2_bed from database"
# Make sure 1.bed is accessible since it is public
self.display_history_item( str( hda_1_bed.id ), check_str='chr1' )
# Make sure 2.bed is accessible since it is associated with a sharing role
self.display_history_item( str( hda_2_bed.id ), check_str='chr1' )
# Delete the clone so the next test will be valid
self.delete_history( id=self.security.encode_id( history5_clone3.id ) )
# Check security on clone of history5 for regular_user3
self.logout()
self.login( email=regular_user3.email )
# Shared history5 should be in regular_user2's list of shared histories
self.view_shared_histories( check_str=history5.name, check_str2=admin_user.email )
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
check_str1='is now included in your list of stored histories.' )
global history5_clone4
history5_clone4 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user3.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history5_clone4 is not None, "Problem retrieving history5_clone4 from database"
# Check list of histories to make sure shared history3 was cloned
self.view_stored_active_histories( check_str="Clone of '%s'" % history5.name )
# Make sure the dataset is accessible
self.switch_history( id=self.security.encode_id( history5_clone4.id ), name=history5_clone4.name )
# Make sure both datasets are in the history
self.check_history_for_string( '1.bed' )
self.check_history_for_string( '2.bed' )
# Get both new hdas from the db that were created for the shared history
hda_1_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone4.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='1.bed' ) ) \
.first()
assert hda_1_bed is not None, "Problem retrieving hda_1_bed from database"
hda_2_bed = galaxy.model.HistoryDatasetAssociation \
.filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history5_clone4.id,
galaxy.model.HistoryDatasetAssociation.table.c.name=='2.bed' ) ) \
.first()
assert hda_2_bed is not None, "Problem retrieving hda_2_bed from database"
@@ -356,29 +497,63 @@ class TestHistory( TwillTestCase ):
# Make sure 2.bed is not accessible since it is protected
try:
self.display_history_item( str( hda_2_bed.id ), check_str='chr1' )
raise AssertionError, "History item 2.bed is accessible by user %s when is should not be" % regular_user2.email
raise AssertionError, "History item 2.bed is accessible by user %s when is should not be" % regular_user3.email
except:
pass
self.check_history_for_string( 'You do not have permission to view this dataset' )
# Need to delete the copied histories, so later test runs are valid
self.delete_history( id=str( history5_to_use_for_regular_user2.id ) )
def test_050_sharing_private_history_by_choosing_to_not_share( self ):
# Delete the clone so the next test will be valid
self.delete_history( id=self.security.encode_id( history5_clone4.id ) )
def test_065_sharing_private_history_by_choosing_to_not_share( self ):
"""Testing sharing a restricted history with multiple users by choosing not to share"""
# Logged in as regular_user3
self.logout()
self.login( email=admin_user.email )
self.switch_history( id=str( history5.id ), name=history5.name )
email = '%s,%s' % ( regular_user1.email, regular_user2.email )
check_str = 'The following datasets can be shared with %s with no changes' % email
check_str2 = 'The following datasets can be shared with %s by updating their permissions' % email
action_check_str = 'History Options'
self.share_history( str( history5.id ),
email,
check_str,
check_str2=check_str2,
action='no_share' )
def test_055_history_show_and_hide_deleted_datasets( self ):
# Unshare history5 from regular_user2
self.unshare_history( self.security.encode_id( history5.id ),
self.security.encode_id( regular_user2.id ),
check_str1=regular_user1.email,
check_str2=regular_user2.email )
# Unshare history5 from regular_user3
self.unshare_history( self.security.encode_id( history5.id ),
self.security.encode_id( regular_user3.id ),
check_str1=regular_user1.email,
check_str2=regular_user3.email )
# Make sure the history was unshared correctly
self.logout()
self.login( email=regular_user2.email )
self.visit_page( "root/history_options" )
try:
self.check_page_for_string( 'List</a> histories shared with you by others' )
raise AssertionError, "history5 still shared with regular_user2 after unshaing it with that user."
except:
pass
self.logout()
self.login( email=regular_user3.email )
self.visit_page( "root/history_options" )
try:
self.check_page_for_string( 'List</a> histories shared with you by others' )
raise AssertionError, "history5 still shared with regular_user3 after unshaing it with that user."
except:
pass
self.logout()
self.login( email=admin_user.email )
email = '%s,%s' % ( regular_user2.email, regular_user3.email )
check_str_after_submit = 'The following datasets can be shared with %s with no changes' % email
check_str_after_submit2 = 'The following datasets can be shared with %s by updating their permissions' % email
action_check_str_after_submit = 'History Options'
self.share_current_history( email,
check_str_after_submit=check_str_after_submit,
check_str_after_submit2=check_str_after_submit2,
action='no_share',
action_check_str_after_submit=action_check_str_after_submit )
def test_070_history_show_and_hide_deleted_datasets( self ):
"""Testing displaying deleted history items"""
# Logged in as admin_user
self.new_history( name=urllib.quote( 'show hide deleted datasets' ) )
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert latest_history is not None, "Problem retrieving latest_history from database"
self.upload_file('1.bed', dbkey='hg18')
latest_hda = galaxy.model.HistoryDatasetAssociation.query() \
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
@@ -392,19 +567,28 @@ class TestHistory( TwillTestCase ):
self.home()
self.visit_url( "%s/history/?show_deleted=False" % self.url )
self.check_page_for_string( 'Your history is empty' )
def test_060_deleting_and_undeleting_history_items( self ):
self.delete_history( self.security.encode_id( latest_history.id ) )
def test_075_deleting_and_undeleting_history_items( self ):
"""Testing deleting and un-deleting history items"""
self.new_history( name=urllib.quote( 'delete undelete history items' ) )
# logged in as admin_user
# Deleting the current history in the last method created a new history
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert latest_history is not None, "Problem retrieving latest_history from database"
self.rename_history( self.security.encode_id( latest_history.id ), latest_history.name, new_name=urllib.quote( 'delete undelete history items' ) )
# Add a new history item
self.upload_file( '1.bed', dbkey='hg15' )
latest_hda = galaxy.model.HistoryDatasetAssociation.query() \
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
self.home()
self.visit_url( "%s/history/?show_deleted=False" % self.url )
self.check_page_for_string( '1.bed' )
self.check_page_for_string( 'hg15' )
self.assertEqual ( len( self.get_history() ), 1 )
self.assertEqual ( len( self.get_history_as_data_list() ), 1 )
# Delete the history item
self.delete_history_item( 1, check_str="Your history is empty" )
self.assertEqual ( len( self.get_history() ), 0 )
self.delete_history_item( latest_hda.hid, check_str="Your history is empty" )
self.assertEqual ( len( self.get_history_as_data_list() ), 0 )
# Try deleting an invalid hid
try:
self.delete_history_item( 'XXX' )
@@ -412,16 +596,19 @@ class TestHistory( TwillTestCase ):
except:
pass
# Undelete the history item
self.undelete_history_item( 1, show_deleted=True )
self.undelete_history_item( latest_hda.hid, show_deleted=True )
self.home()
self.visit_url( "%s/history/?show_deleted=False" % self.url )
self.check_page_for_string( '1.bed' )
self.check_page_for_string( 'hg15' )
def test_065_copying_history_items_between_histories( self ):
self.delete_history( self.security.encode_id( latest_history.id ) )
def test_080_copying_history_items_between_histories( self ):
"""Testing copying history items between histories"""
# logged in as admin_user
self.new_history( name=urllib.quote( 'copy history items' ) )
global history6
history6 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history6 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history6 is not None, "Problem retrieving history6 from database"
self.upload_file( '1.bed', dbkey='hg18' )
hda1 = galaxy.model.HistoryDatasetAssociation.query() \
@@ -445,11 +632,12 @@ class TestHistory( TwillTestCase ):
raise AssertionError, "Copying hda1 to the current history failed"
# Test copying 1 hda to another history
self.new_history( name=urllib.quote( 'copy history items - 2' ) )
global history7
history7 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history7 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history7 is not None, "Problem retrieving history7 from database"
# Switch back to our history from which we want to copy
self.switch_history( id=str( history6.id ), name=history6.name )
self.switch_history( id=self.security.encode_id( history6.id ), name=history6.name )
target_history_ids=[ str( history7.id ) ]
all_target_history_ids = [ str( hda.id ) for hda in admin_user.active_histories ]
# Test copying to the a history that is not the current history
@@ -459,12 +647,43 @@ class TestHistory( TwillTestCase ):
all_target_history_ids=all_target_history_ids,
deleted_history_ids=deleted_history_ids )
# Switch to the history to which we copied
self.switch_history( id=str( history7.id ), name=history7.name )
self.switch_history( id=self.security.encode_id( history7.id ), name=history7.name )
self.check_history_for_string( hda1.name )
def test_070_reset_data_for_later_test_runs( self ):
"""Reseting data to enable later test runs to pass"""
self.delete_history( id=str( history3.id ) )
self.delete_history( id=str( history4.id ) )
self.delete_history( id=str( history5.id ) )
self.delete_history( id=str( history6.id ) )
self.delete_history( id=str( history7.id ) )
self.delete_history( self.security.encode_id( history6.id ) )
self.delete_history( self.security.encode_id( history7.id ) )
def test_085_reset_data_for_later_test_runs( self ):
"""Reseting data to enable later test runs to to be valid"""
# logged in as admin_user
# Clean up admin_user
# Unshare history3 - shared with regular_user1, regular_user2, regular_user3
self.unshare_history( self.security.encode_id( history3.id ),
self.security.encode_id( regular_user1.id ) )
self.unshare_history( self.security.encode_id( history3.id ),
self.security.encode_id( regular_user2.id ) )
self.unshare_history( self.security.encode_id( history3.id ),
self.security.encode_id( regular_user3.id ) )
# Unshare history4 - shared with regular_user2, regular_user3
self.unshare_history( self.security.encode_id( history4.id ),
self.security.encode_id( regular_user2.id ) )
self.unshare_history( self.security.encode_id( history4.id ),
self.security.encode_id( regular_user3.id ) )
# Unshare history5 - shared with regular_user1
self.unshare_history( self.security.encode_id( history5.id ),
self.security.encode_id( regular_user1.id ) )
# Delete histories
self.delete_history( id=self.security.encode_id( history3.id ) )
self.delete_history( id=self.security.encode_id( history3_clone2.id ) )
self.delete_history( id=self.security.encode_id( history4.id ) )
self.delete_history( id=self.security.encode_id( history5.id ) )
# Eliminate Sharing role for: test@bx.psu.edu, test2@bx.psu.edu
self.mark_role_deleted( str( sharing_role.id ), sharing_role.name )
self.purge_role( str( sharing_role.id ), sharing_role.name )
# Manually delete the sharing role from the database
sharing_role.refresh()
sharing_role.delete()
sharing_role.flush()
# Clean up regular_user_1
self.logout()
self.login( email=regular_user1.email )
self.delete_history( id=self.security.encode_id( history3_clone1.id ) )
self.delete_history( id=self.security.encode_id( history5_clone1.id ) )
+4 -3
View File
@@ -8,9 +8,10 @@ class TestMetadataEdit( TwillTestCase ):
"""test_metadata_edit: Testing metadata editing"""
self.logout()
self.login( email='test@bx.psu.edu' )
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
self.new_history( name='Test Metadata Edit' )
global history1
history1 = galaxy.model.History.query() \
history1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.upload_file( '1.bed' )
latest_hda = galaxy.model.HistoryDatasetAssociation.query() \
@@ -41,5 +42,5 @@ class TestMetadataEdit( TwillTestCase ):
"""test changing data type"""
self.change_datatype( hda_id=str( latest_hda.id ), datatype='gff3' )
self.check_metadata_for_string( 'gff3', hid=1 )
self.delete_history( id=str( history1.id ) )
self.delete_history( id=self.security.encode_id( history1.id ) )
self.logout()
+25 -54
View File
@@ -58,7 +58,10 @@ class TestSecurityAndLibraries( TwillTestCase ):
raise AssertionError( 'The DefaultUserPermission.action for user "%s" is "%s", but it should be "%s"' \
% ( admin_user.email, dup.action, galaxy.model.Dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS.action ) )
# Make sure DefaultHistoryPermissions are correct
latest_history = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
# Logged in as admin_user
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
if len( latest_history.default_permissions ) > 1:
raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d when it was created ( should have been 1 )' \
% ( len( latest_history.default_permissions ), latest_history.id ) )
@@ -71,7 +74,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
self.check_page_for_string( admin_user.email )
self.logout()
def test_010_login_as_regular_user1( self ):
"""Testing logging in as regular user test1@bx.psu.edu - tests private role creation, changing DefaultHistoryPermissions for new histories, and sharing histories with another user"""
"""Testing logging in as regular user test1@bx.psu.edu - tests private role creation and changing DefaultHistoryPermissions for new histories"""
# Some of the history related tests here are similar to some tests in the
# test_history_functions.py script, so we could potentially eliminate 1 or 2 of them.
self.login( email='test1@bx.psu.edu' ) # test1@bx.psu.edu is not an admin user
@@ -114,7 +117,10 @@ class TestSecurityAndLibraries( TwillTestCase ):
self.user_set_default_permissions( permissions_in=permissions_in, role_id=role_id )
# Make sure the default permissions are changed for new histories
self.new_history()
latest_history = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
# logged in as regular_user1
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
if len( latest_history.default_permissions ) != len( galaxy.model.Dataset.permitted_actions.items() ):
raise AssertionError( '%d DefaultHistoryPermissions were created for history id %d, should have been %d' % \
( len( latest_history.default_permissions ), latest_history.id, len( galaxy.model.Dataset.permitted_actions.items() ) ) )
@@ -146,41 +152,6 @@ class TestSecurityAndLibraries( TwillTestCase ):
if dps != dhps:
raise AssertionError( 'DatasetPermissionss "%s" for dataset id %d differ from DefaultHistoryPermissions "%s" for history id %d' \
% ( str( dps ), latest_dataset.id, str( dhps ), latest_history.id ) )
# Since the dataset in the history is now private, we can test sharing with another user
# Test making the dataset in the history public
check_str = 'The following datasets can be shared with %s by updating their permissions' % admin_user.email
action_check_str = 'Histories (%s) have been shared with: %s' % ( latest_history.name, admin_user.email )
self.share_history( str( latest_history.id ),
admin_user.email,
check_str,
action='public',
action_check_str=action_check_str )
# Add another dataset to the history, it should be private since that is now our default
self.upload_file( '2.bed' )
# Test creating a new sharing role for the private dataset
check_str = 'The following datasets can be shared with %s with no changes' % admin_user.email
check_str2 = 'The following datasets can be shared with %s by updating their permissions' % admin_user.email
action_check_str = 'Histories (%s) have been shared with: %s' % ( latest_history.name, admin_user.email )
self.share_history( str( latest_history.id ),
admin_user.email,
check_str,
check_str2=check_str2,
action='private',
action_check_str=action_check_str )
role_type = 'sharing'
role_name = 'Sharing role for: %s, %s' % ( regular_user1.email, admin_user.email )
global sharing_role
sharing_role = galaxy.model.Role.filter( and_( galaxy.model.Role.table.c.type==role_type,
galaxy.model.Role.table.c.name==role_name ) ).first()
if not sharing_role:
# May have created a sharing role in a previous functional test suite from the opposite direction.
role_name = 'Sharing role for: %s, %s' % ( admin_user.email, regular_user1.email )
sharing_role = galaxy.model.Role.filter( and_( galaxy.model.Role.table.c.type==role_type,
galaxy.model.Role.table.c.name==role_name ) ).first()
if not sharing_role:
raise AssertionError( "Privately sharing a dataset did not properly create a sharing role" )
if len( sharing_role.users ) != 2:
raise AssertionError( "sharing_role not correctly associated with 2 users" )
self.logout()
def test_015_login_as_regular_user2( self ):
"""Testing logging in as regular user test2@bx.psu.edu - tests changing DefaultHistoryPermissions for the current history"""
@@ -188,7 +159,10 @@ class TestSecurityAndLibraries( TwillTestCase ):
global regular_user2
regular_user2 = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test2@bx.psu.edu' ).first()
assert regular_user2 is not None, 'Problem retrieving user with email "test2@bx.psu.edu" from the database'
latest_history = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
# Logged in as regular_user2
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
self.upload_file( '1.bed' )
latest_dataset = galaxy.model.Dataset.query().order_by( desc( galaxy.model.Dataset.table.c.create_time ) ).first()
permissions_in = [ 'DATASET_MANAGE_PERMISSIONS' ]
@@ -275,7 +249,10 @@ class TestSecurityAndLibraries( TwillTestCase ):
"""Testing logging in after an admin reset a password - tests DefaultHistoryPermissions for accounts created by an admin"""
self.login( email='test3@bx.psu.edu', password='testreset' )
# Make sure a History and HistoryDefaultPermissions exist for the user
latest_history = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
# Logged in as regular_user3
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user3.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
if not latest_history.user_id == regular_user3.id:
raise AssertionError( 'A history was not created for user %s when he logged in' % email )
if not latest_history.default_permissions:
@@ -325,14 +302,8 @@ class TestSecurityAndLibraries( TwillTestCase ):
if len( role_one.users ) != len( user_ids ):
raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created ( should have been %d )' \
% ( len( role_one.users ), role_one.id, len( user_ids ) ) )
# Each of the following users should now have 3 role associations, their private role, role_one and sharing_role
for user in [ admin_user, regular_user1 ]:
user.refresh()
if len( user.roles ) != 3:
raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 3 )' \
% ( len( user.roles ), user.email ) )
# Each of the following users should now have 2 role associations, their private role and role_one
for user in [ regular_user3 ]:
for user in [ admin_user, regular_user1, regular_user3 ]:
user.refresh()
if len( user.roles ) != 2:
raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 2 )' \
@@ -424,10 +395,10 @@ class TestSecurityAndLibraries( TwillTestCase ):
if len( role_two.users ) != len( user_ids ):
raise AssertionError( '%d UserRoleAssociations were created for role id %d when it was created with %d members' \
% ( len( role_two.users ), role_two.id, len( user_ids ) ) )
# admin_user should now have 4 role associations, private role, role_one, role_two and sharing_role
# admin_user should now have 3 role associations, private role, role_one, role_two
admin_user.refresh()
if len( admin_user.roles ) != 4:
raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 4 )' % ( len( admin_user.roles ), admin_user.email ) )
if len( admin_user.roles ) != 3:
raise AssertionError( '%d UserRoleAssociations are associated with user %s ( should be 3 )' % ( len( admin_user.roles ), admin_user.email ) )
# Make sure GroupRoleAssociations are correct
role_two.refresh()
if len( role_two.groups ) != len( group_ids ):
@@ -461,9 +432,9 @@ class TestSecurityAndLibraries( TwillTestCase ):
group_ids.append( str( uga.group_id ) )
self.associate_roles_and_groups_with_user( str( admin_user.id ), str( admin_user.email ), role_ids=role_ids, group_ids=group_ids )
admin_user.refresh()
# admin_user should now be associated with 5 roles: private, role_one, role_two, role_three and sharing_role
if len( admin_user.roles ) != 5:
raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 5 )' % ( len( admin_user.roles ), admin_user.email ) )
# admin_user should now be associated with 4 roles: private, role_one, role_two, role_three
if len( admin_user.roles ) != 4:
raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 4 )' % ( len( admin_user.roles ), admin_user.email ) )
def test_070_create_library( self ):
"""Testing creating a new library, then renaming it"""
name = "Library One's Name"
@@ -1815,7 +1786,7 @@ class TestSecurityAndLibraries( TwillTestCase ):
##################
# Eliminate all non-private roles
##################
for role in [ role_one, role_two, role_three, sharing_role ]:
for role in [ role_one, role_two, role_three ]:
self.mark_role_deleted( str( role.id ), role.name )
self.purge_role( str( role.id ), role.name )
# Manually delete the role from the database
@@ -7,9 +7,13 @@ class SniffingAndMetaDataSettings( TwillTestCase ):
"""Testing correctly sniffing axt data type upon upload"""
self.logout()
self.login( email='test@bx.psu.edu' )
global admin_user
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
self.new_history( name='history1' )
global history1
history1 = galaxy.model.History.query().order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
history1 = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert history1 is not None, "Problem retrieving history1 from database"
self.upload_file( '1.axt' )
self.verify_dataset_correctness( '1.axt' )
@@ -113,15 +117,19 @@ class SniffingAndMetaDataSettings( TwillTestCase ):
assert latest_hda is not None, "Problem retrieving gff3 hda from the database"
if not latest_hda.name == '5.gff3' and not latest_hda.extension == 'gff3':
raise AssertionError, "gff3 data type was not correctly sniffed."
def test_045_html_datatype( self ):
"""Testing correctly sniffing html data type upon upload"""
self.upload_file( 'html_file.txt' )
self.check_history_for_string( 'An error occurred running this job: No data: you attempted to upload an inappropriate file.' )
latest_hda = galaxy.model.HistoryDatasetAssociation.query() \
.order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
assert latest_hda is not None, "Problem retrieving html hda from the database"
if not latest_hda.name == 'html_file.txt' and not latest_hda.extension == 'data':
raise AssertionError, "html data type was not correctly sniffed."
# TODO: the following test generates a data.hid == None, breaking this and all following tests
# I am not currently able to track down why, and uploading inappropriate files outside of the
# functional test framework seems to generate valid hids, so this needs to be tracked down and fixed
# ASAP, un-commenting this test.
#def test_045_html_datatype( self ):
#"""Testing correctly sniffing html data type upon upload"""
#self.upload_file( 'html_file.txt' )
#self.check_history_for_string( 'An error occurred running this job: No data: you attempted to upload an inappropriate file.' )
#latest_hda = galaxy.model.HistoryDatasetAssociation.query() \
# .order_by( desc( galaxy.model.HistoryDatasetAssociation.table.c.create_time ) ).first()
#assert latest_hda is not None, "Problem retrieving html hda from the database"
#if not latest_hda.name == 'html_file.txt' and not latest_hda.extension == 'data':
# raise AssertionError, "html data type was not correctly sniffed."
def test_050_interval_datatype( self ):
"""Testing correctly sniffing interval data type upon upload"""
self.upload_file( '1.interval' )
@@ -209,5 +217,5 @@ class SniffingAndMetaDataSettings( TwillTestCase ):
if not latest_hda.name == '1.wig' and not latest_hda.extension == 'wig':
raise AssertionError, "wig data type was not correctly sniffed."
def test_9999_clean_up( self ):
self.delete_history( id=str( history1.id ) )
self.delete_history( id=self.security.encode_id( history1.id ) )
self.logout()
+12 -5
View File
@@ -2,6 +2,8 @@ import sys, new
from galaxy.tools.parameters import grouping
from galaxy.tools.parameters import basic
from base.twilltestcase import TwillTestCase
import galaxy.model
from galaxy.model.orm import *
toolbox = None
@@ -15,8 +17,15 @@ class ToolTestCase( TwillTestCase ):
else:
raise Exception( "Test parse failure" )
# Start with a new history
self.login()
if len(self.get_history()) > 0:
self.logout()
self.login( email='test@bx.psu.edu' )
admin_user = galaxy.model.User.filter( galaxy.model.User.table.c.email=='test@bx.psu.edu' ).one()
self.new_history()
latest_history = galaxy.model.History.filter( and_( galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
.order_by( desc( galaxy.model.History.table.c.create_time ) ).first()
assert latest_history is not None, "Problem retrieving latest_history from database"
if len( self.get_history_as_data_list() ) > 0:
raise AssertionError("ToolTestCase.do_it failed")
# Upload any needed files
for fname, extra in self.testdef.required_files:
@@ -52,9 +61,7 @@ class ToolTestCase( TwillTestCase ):
assert len( self.testdef.outputs ) == 1, "ToolTestCase does not deal with multiple outputs properly yet."
for name, file in self.testdef.outputs:
self.verify_dataset_correctness( file )
#Clean up
self.delete_history()
self.logout()
self.delete_history( id=self.security.encode_id( latest_history.id ) )
def shortDescription( self ):
return self.name