mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-08-31 01:02:04 +08:00
These are the changes we've been discussing to incorporate
galaxy sessions (using cookies) for all histories, events and jobs.
This commit is contained in:
@@ -80,7 +80,7 @@ class UCSCProxy(common.Root):
|
||||
else:
|
||||
try:
|
||||
text = page.read()
|
||||
|
||||
|
||||
# Serialize store into a form element
|
||||
store_text = "<INPUT TYPE=\"HIDDEN\" NAME=\"__GALAXY__\" ID=\"__GALAXY__\" VALUE=\"" \
|
||||
+ util.object_to_string(store) + "\" \>"
|
||||
|
||||
@@ -27,6 +27,8 @@ class Universe(common.Root):
|
||||
trans.set_cookie(name=self.pref_cookie_name, value=mode)
|
||||
else:
|
||||
mode = trans.get_cookie(name=self.pref_cookie_name)
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
result = trans.fill_template('index_frames.tmpl', mode=mode)
|
||||
return [ result ]
|
||||
|
||||
@@ -319,6 +321,13 @@ class Universe(common.Root):
|
||||
new_history = self.copy_history(history)
|
||||
new_history.name = history.name+" from "+user.email
|
||||
new_history.user_id = send_to_user.id
|
||||
"""
|
||||
gvk TODO: how should we handle galaxy_session_to_history association here?
|
||||
I'll do the following for now, but not sure if this is what we want...
|
||||
"""
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session())
|
||||
trans.log_event( "History share: %s to %s" % (str(history.id),str(new_history.id)) )
|
||||
self.app.model.flush()
|
||||
return trans.show_message( "History (%s) has been shared with: %s" % (",".join(history_names),email) )
|
||||
@@ -333,6 +342,8 @@ class Universe(common.Root):
|
||||
|
||||
@web.expose
|
||||
def history_import( self, trans, id=None, confirm=False, **kwd ):
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
msg = ""
|
||||
user = trans.get_user()
|
||||
user_history = trans.get_history()
|
||||
@@ -347,6 +358,7 @@ class Universe(common.Root):
|
||||
new_history = self.copy_history(import_history)
|
||||
new_history.name = "imported: "+new_history.name
|
||||
new_history.user_id = user.id
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session())
|
||||
new_history.flush()
|
||||
if not user_history.datasets:
|
||||
trans.set_history( new_history )
|
||||
@@ -356,6 +368,7 @@ class Universe(common.Root):
|
||||
new_history = self.copy_history(import_history)
|
||||
new_history.name = "imported: "+new_history.name
|
||||
new_history.user_id = None
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session())
|
||||
new_history.flush()
|
||||
trans.set_history( new_history )
|
||||
trans.log_event( "History import: %s" % str(new_history.id) )
|
||||
@@ -367,8 +380,11 @@ class Universe(common.Root):
|
||||
if not id:
|
||||
return trans.fill_template( "history_switch.tmpl" )
|
||||
else:
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
new_history = trans.app.model.History.get( id )
|
||||
if new_history:
|
||||
new_history.add_galaxy_session(trans.get_galaxy_session())
|
||||
trans.set_history( new_history )
|
||||
trans.log_event( "History switch" )
|
||||
return trans.show_message( "History switched to: %s" % new_history.name,
|
||||
@@ -379,7 +395,7 @@ class Universe(common.Root):
|
||||
@web.expose
|
||||
def history_new( self, trans ):
|
||||
trans.new_history()
|
||||
trans.log_event( "History new" )
|
||||
trans.log_event( "Created new History." )
|
||||
return self.history( trans )
|
||||
|
||||
@web.expose
|
||||
|
||||
@@ -37,6 +37,8 @@ class ToolRunner(common.Root):
|
||||
return "Tool '%s' does not exist, kwd=%s " % (tool_id, kwd)
|
||||
params = util.Params(kwd)
|
||||
history = trans.get_history()
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
template, vars = tool.handle_input( trans, params.__dict__ )
|
||||
trans.log_event( "Tool View: %s; %s" % (str(tool),str(params)) )
|
||||
trans.log_event( "Tool View: %s; %s" % (str(tool),str(params)), tool_id=tool_id )
|
||||
return trans.fill_template( template, history=history, toolbox=toolbox, tool=tool, util=util, **vars )
|
||||
@@ -88,6 +88,13 @@ class User( common.Root ):
|
||||
password_error = "Invalid password"
|
||||
else:
|
||||
trans.set_user( user )
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
else:
|
||||
"""
|
||||
Associate user with galaxy_session and history
|
||||
"""
|
||||
trans.make_associations()
|
||||
trans.log_event( "User logged in" )
|
||||
return trans.show_ok_message( "Now logged in as " + user.email, \
|
||||
refresh_frames=['masthead', 'history'] )
|
||||
@@ -98,12 +105,12 @@ class User( common.Root ):
|
||||
|
||||
@web.expose
|
||||
def logout( self, trans ):
|
||||
# If the current history is saved for the current user it should be
|
||||
# disconnected.
|
||||
trans.log_event( "User logged out" )
|
||||
# If the current history is saved for the current user it should be disconnected.
|
||||
if trans.history.user == trans.user:
|
||||
trans.set_history( None )
|
||||
trans.log_event( "User logged out" )
|
||||
trans.set_user( None )
|
||||
trans.end_galaxy_session()
|
||||
return trans.show_ok_message( "You are no longer logged in", \
|
||||
refresh_frames=['masthead', 'history'] )
|
||||
|
||||
@@ -126,7 +133,14 @@ class User( common.Root ):
|
||||
user.set_password_cleartext( password )
|
||||
user.flush()
|
||||
trans.set_user( user )
|
||||
trans.log_event( "User new" )
|
||||
if not trans.galaxy_session_is_valid():
|
||||
trans.new_galaxy_session()
|
||||
else:
|
||||
"""
|
||||
Associate user with galaxy_session and history
|
||||
"""
|
||||
trans.make_associations()
|
||||
trans.log_event( "User created a new account" )
|
||||
trans.log_event( "User logged in" )
|
||||
#subscribe user to email list
|
||||
if subscribe:
|
||||
|
||||
@@ -209,6 +209,10 @@ class JobWrapper( object ):
|
||||
def get_command_line( self ):
|
||||
job = model.Job.get( self.job_id )
|
||||
return job.command_line
|
||||
|
||||
def get_session_id( self ):
|
||||
job = model.Job.get( self.job_id )
|
||||
return job.session_id
|
||||
|
||||
def get_input_fnames( self ):
|
||||
job = model.Job.get( self.job_id )
|
||||
|
||||
@@ -37,6 +37,7 @@ class Job( object ):
|
||||
OK = 'ok',
|
||||
ERROR = 'error' )
|
||||
def __init__( self ):
|
||||
self.session_id = None
|
||||
self.tool_id = None
|
||||
self.command_line = None
|
||||
self.param_filename = None
|
||||
@@ -79,6 +80,7 @@ class History( object ):
|
||||
# Relationships
|
||||
self.user = user
|
||||
self.datasets = []
|
||||
self.galaxy_sessions = []
|
||||
|
||||
def _next_hid( self ):
|
||||
# TODO: override this with something in the database that ensures
|
||||
@@ -91,6 +93,9 @@ class History( object ):
|
||||
if dataset.hid > last_hid:
|
||||
last_hid = dataset.hid
|
||||
return last_hid + 1
|
||||
|
||||
def add_galaxy_session( self, galaxy_session ):
|
||||
self.galaxy_sessions.append( GalaxySessionToHistoryAssociation( galaxy_session, self ) )
|
||||
|
||||
def add_dataset( self, dataset, parent_id=None ):
|
||||
if parent_id:
|
||||
@@ -98,6 +103,7 @@ class History( object ):
|
||||
if data.id == parent_id:
|
||||
dataset.hid = data.hid
|
||||
break
|
||||
# TODO gvk: ask if this needs to be fixed, I don't want to break it if it isn't broken...
|
||||
else:
|
||||
dataset.hid = self._next_hid()
|
||||
else:
|
||||
@@ -250,7 +256,27 @@ class Dataset( object ):
|
||||
log.critical('%s delete error %s' % (self.__class__.__name__, e))
|
||||
|
||||
class Event( object ):
|
||||
def __init__( self, message=None, history=None, user=None ):
|
||||
self.message = message
|
||||
def __init__( self, message=None, history=None, user=None, galaxy_session=None ):
|
||||
self.history = history
|
||||
self.galaxy_session = galaxy_session
|
||||
self.user = user
|
||||
self.tool_id = None
|
||||
self.message = message
|
||||
|
||||
class GalaxySession( object ):
|
||||
def __init__( self, id=None, user=None, remote_host=None, remote_addr=None ):
|
||||
self.id = id
|
||||
self.user = user
|
||||
self.remote_host = remote_host
|
||||
self.remote_addr = remote_addr
|
||||
self.histories = []
|
||||
|
||||
def add_history( self, history ):
|
||||
self.histories.append( GalaxySessionToHistoryAssociation( self, history ) )
|
||||
|
||||
class GalaxySessionToHistoryAssociation( object ):
|
||||
def __init__( self, galaxy_session, history ):
|
||||
self.galaxy_session = galaxy_session
|
||||
self.history = history
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ Job.table = Table( "job", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, PassiveDefault( func.current_timestamp() ) ),
|
||||
Column( "update_time", DateTime, PassiveDefault( func.current_timestamp() ), onupdate=func.current_timestamp() ),
|
||||
Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), nullable=True ),
|
||||
Column( "history_id", Integer, ForeignKey( "history.id" ) ),
|
||||
Column( "tool_id", String( 255 ) ),
|
||||
Column( "state", String( 64 ) ),
|
||||
@@ -104,10 +105,26 @@ Event.table = Table( "event", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, PassiveDefault( func.current_timestamp() ) ),
|
||||
Column( "update_time", DateTime, PassiveDefault( func.current_timestamp() ), onupdate=func.current_timestamp() ),
|
||||
Column( "history_id", Integer, nullable=True ),
|
||||
Column( "history_id", Integer, ForeignKey( "history.id" ), nullable=True ),
|
||||
Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), nullable=True ),
|
||||
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True ),
|
||||
Column( "tool_id", String( 255 ) ),
|
||||
Column( "message", TrimmedString( 1024 ) ) )
|
||||
|
||||
GalaxySession.table = Table( "galaxy_session", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, PassiveDefault( func.current_timestamp() ) ),
|
||||
Column( "update_time", DateTime, PassiveDefault( func.current_timestamp() ), onupdate=func.current_timestamp() ),
|
||||
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), nullable=True ),
|
||||
Column( "remote_host", String( 255 ) ),
|
||||
Column( "remote_addr", String( 255 ) ) )
|
||||
|
||||
GalaxySessionToHistoryAssociation.table = Table( "galaxy_session_to_history", metadata,
|
||||
Column( "id", Integer, primary_key=True ),
|
||||
Column( "create_time", DateTime, PassiveDefault( func.current_timestamp() ) ),
|
||||
Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ) ),
|
||||
Column( "history_id", Integer, ForeignKey( "history.id" ) ) )
|
||||
|
||||
# With the tables defined we can define the mappers and setup the
|
||||
# relationships between the model objects.
|
||||
|
||||
@@ -119,7 +136,8 @@ assign_mapper( context, Dataset, Dataset.table,
|
||||
# properties=dict( datasets=relation( model.Dataset.mapper, backref="query") ) )
|
||||
|
||||
assign_mapper( context, History, History.table,
|
||||
properties=dict( datasets=relation( Dataset, backref="history", order_by=asc(Dataset.table.c.hid) ),
|
||||
properties=dict( galaxy_sessions=relation( GalaxySessionToHistoryAssociation ),
|
||||
datasets=relation( Dataset, backref="history", order_by=asc(Dataset.table.c.hid) ),
|
||||
active_datasets=relation( Dataset, primaryjoin=( ( Dataset.c.history_id == History.table.c.id ) & ( Dataset.c.deleted == False ) ), order_by=asc( Dataset.table.c.hid ), lazy=False, viewonly=True ) ) )
|
||||
|
||||
assign_mapper( context, User, User.table,
|
||||
@@ -135,13 +153,24 @@ assign_mapper( context, JobToOutputDatasetAssociation, JobToOutputDatasetAssocia
|
||||
assign_mapper( context, JobParameter, JobParameter.table )
|
||||
|
||||
assign_mapper( context, Job, Job.table,
|
||||
properties=dict( history=relation( History ),
|
||||
properties=dict( galaxy_session=relation( GalaxySession ),
|
||||
history=relation( History ),
|
||||
parameters=relation( JobParameter ),
|
||||
input_datasets=relation( JobToInputDatasetAssociation ),
|
||||
output_datasets=relation( JobToOutputDatasetAssociation ) ) )
|
||||
|
||||
assign_mapper( context, Event, Event.table,
|
||||
properties=dict( user=relation( User.mapper ) ) )
|
||||
properties=dict( history=relation( History ),
|
||||
galaxy_session=relation( GalaxySession ),
|
||||
user=relation( User.mapper ) ) )
|
||||
|
||||
assign_mapper( context, GalaxySession, GalaxySession.table,
|
||||
properties=dict( histories=relation( GalaxySessionToHistoryAssociation ),
|
||||
user=relation( User.mapper ) ) )
|
||||
|
||||
assign_mapper( context, GalaxySessionToHistoryAssociation, GalaxySessionToHistoryAssociation.table,
|
||||
properties=dict( galaxy_session=relation( GalaxySession ),
|
||||
history=relation( History ) ) )
|
||||
|
||||
def db_next_hid( self ):
|
||||
"""
|
||||
|
||||
@@ -8,6 +8,7 @@ class MappingTests( unittest.TestCase ):
|
||||
assert model.engine is not None
|
||||
# Make some changes and commit them
|
||||
u = model.User( email="james@foo.bar.baz", password="password" )
|
||||
# gs = model.GalaxySession()
|
||||
h1 = model.History( name="History 1", user=u)
|
||||
#h1.queries.append( model.Query( "h1->q1" ) )
|
||||
#h1.queries.append( model.Query( "h1->q2" ) )
|
||||
@@ -39,6 +40,7 @@ class MappingTests( unittest.TestCase ):
|
||||
hists = model.History.select()
|
||||
assert hists[0].name == "History 1"
|
||||
assert hists[1].name == "History 2b"
|
||||
# gvk TODO need to ad test for GalaxySessions, but not yet sure what they should look like.
|
||||
|
||||
def get_suite():
|
||||
suite = unittest.TestSuite()
|
||||
|
||||
@@ -588,6 +588,14 @@ class DefaultToolAction( object ):
|
||||
|
||||
# Create the job object
|
||||
job = trans.app.model.Job()
|
||||
if trans.galaxy_session_is_valid():
|
||||
a_galaxy_session = trans.get_galaxy_session()
|
||||
else:
|
||||
a_galaxy_session = trans.new_galaxy_session()
|
||||
job.session_id = a_galaxy_session.id
|
||||
a_history = trans.get_history()
|
||||
if a_history is not None:
|
||||
job.history_id = a_history.id
|
||||
job.tool_id = tool.id
|
||||
job.command_line = command_line
|
||||
job.param_filename = param_filename
|
||||
|
||||
@@ -7,7 +7,6 @@ class UploadToolAction( object ):
|
||||
Action for uploading files
|
||||
"""
|
||||
def execute( self, tool, trans, incoming={} ):
|
||||
|
||||
data_file = incoming['file_data']
|
||||
file_type = incoming['file_type']
|
||||
dbkey = incoming['dbkey']
|
||||
|
||||
@@ -24,21 +24,24 @@ NOT_SET = object()
|
||||
class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
"""
|
||||
Encapsulates web transaction specific state for the Universe application
|
||||
(specifically the user's history)
|
||||
(specifically the user's "cookie" session and history)
|
||||
"""
|
||||
def __init__( self, environ, app ):
|
||||
self.app = app
|
||||
self.__user = NOT_SET
|
||||
self.__history = NOT_SET
|
||||
self.__galaxy_session = NOT_SET
|
||||
framework.DefaultWebTransaction.__init__( self, environ )
|
||||
self.app.model.context.current.clear()
|
||||
self.debug = asbool( self.app.config.get( 'debug', False ) )
|
||||
def log_event( self, message, **kwargs ):
|
||||
|
||||
def log_event( self, message, tool_id=None, **kwargs ):
|
||||
"""
|
||||
Application level logging. Still needs fleshing out (log levels and
|
||||
such)
|
||||
"""
|
||||
event = self.app.model.Event()
|
||||
event.tool_id = tool_id
|
||||
try:
|
||||
event.message = message % kwargs
|
||||
except:
|
||||
@@ -49,7 +52,10 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
except:
|
||||
event.history_id = None
|
||||
event.user = self.user
|
||||
if self.galaxy_session_is_valid():
|
||||
event.session_id = self.galaxy_session.id
|
||||
event.flush()
|
||||
|
||||
def get_cookie( self, name='universe' ):
|
||||
"""
|
||||
Convienience method for getting the universe cookie
|
||||
@@ -63,6 +69,7 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
return self.request.cookies[name].value
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def set_cookie( self, value, name='universe', path='/', age=90, version='1' ):
|
||||
"""
|
||||
Convienience method for setting the universe cookie
|
||||
@@ -73,6 +80,7 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
tstamp = time.localtime ( time.time() + 3600 * 24 * age )
|
||||
self.response.cookies[name]['expires'] = time.strftime('%a, %d-%b-%Y %H:%M:%S GMT', tstamp)
|
||||
self.response.cookies[name]['version'] = version
|
||||
|
||||
def get_history( self ):
|
||||
"""
|
||||
Load the current history
|
||||
@@ -84,14 +92,20 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
history = self.app.model.History.get( id )
|
||||
if history is None:
|
||||
history = self.new_history()
|
||||
self.__history = history
|
||||
return self.__history
|
||||
self.__history = history
|
||||
return self.__history
|
||||
|
||||
def new_history( self ):
|
||||
history = self.app.model.History()
|
||||
if history.user_id is None and self.user is not None:
|
||||
history.user_id = self.user.id
|
||||
if self.galaxy_session_is_valid():
|
||||
history.add_galaxy_session(self.get_galaxy_session())
|
||||
history.flush()
|
||||
self.set_cookie( name='universe', value=history.id )
|
||||
self.__history = history
|
||||
return history
|
||||
|
||||
def set_history( self, history ):
|
||||
if history is None:
|
||||
self.set_cookie( name='universe', value='' )
|
||||
@@ -99,6 +113,7 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
self.set_cookie( name='universe', value=history.id )
|
||||
self.__history = history
|
||||
history = property( get_history, set_history )
|
||||
|
||||
def get_user( self ):
|
||||
"""
|
||||
Return the current user if logged in (based on cookie) or `None`.
|
||||
@@ -110,6 +125,7 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
else:
|
||||
self.__user = self.app.model.User.get( int( id ) )
|
||||
return self.__user
|
||||
|
||||
def set_user( self, user ):
|
||||
"""
|
||||
Set the current user to `user` (by setting a cookie).
|
||||
@@ -119,7 +135,75 @@ class UniverseWebTransaction( framework.DefaultWebTransaction ):
|
||||
else:
|
||||
self.set_cookie( name='universe_user', value=user.id )
|
||||
self.__user = user
|
||||
user = property( get_user, set_user )
|
||||
user = property( get_user, set_user )
|
||||
|
||||
def get_galaxy_session( self ):
|
||||
"""
|
||||
Return the current user's galaxy_session.
|
||||
"""
|
||||
if self.__galaxy_session is NOT_SET:
|
||||
id = self.get_cookie( name='universe_session' )
|
||||
if not id:
|
||||
self.__galaxy_session = None
|
||||
else:
|
||||
self.__galaxy_session = self.app.model.GalaxySession.get( int( id ) )
|
||||
return self.__galaxy_session
|
||||
|
||||
def new_galaxy_session( self ):
|
||||
galaxy_session = self.app.model.GalaxySession()
|
||||
if self.user is not None:
|
||||
galaxy_session.user_id = self.user.id
|
||||
galaxy_session.remote_host = self.request.remote_host
|
||||
galaxy_session.remote_addr = self.request.remote_addr
|
||||
if self.history is not None:
|
||||
galaxy_session.add_history(self.history)
|
||||
galaxy_session.flush()
|
||||
self.set_cookie( name='universe_session', value=galaxy_session.id )
|
||||
self.__galaxy_session = galaxy_session
|
||||
return self.__galaxy_session
|
||||
|
||||
def set_galaxy_session( self, galaxy_session ):
|
||||
"""
|
||||
Set the current galaxy_session by setting the universe_session cookie.
|
||||
"""
|
||||
if galaxy_session is None:
|
||||
#TODO we may want to raise an exception here instead of creating a new galaxy_session
|
||||
galaxy_session = self.new_galaxy_session()
|
||||
else:
|
||||
if galaxy_session.user_id is None and self.user is not None:
|
||||
galaxy_session.user_id = self.user.id
|
||||
galaxy_session.flush()
|
||||
self.set_cookie( name='universe_session', value=galaxy_session.id )
|
||||
self.__galaxy_session = galaxy_session
|
||||
|
||||
def galaxy_session_is_valid( self ):
|
||||
# TODO do we want better validation here?
|
||||
valid = False
|
||||
a_galaxy_session = self.get_galaxy_session()
|
||||
if a_galaxy_session is not None and a_galaxy_session.id is not None:
|
||||
valid = True
|
||||
return valid
|
||||
|
||||
def end_galaxy_session( self ):
|
||||
"""
|
||||
End the current galaxy_session by expiring the universe_session cookie.
|
||||
"""
|
||||
if self.galaxy_session_is_valid():
|
||||
self.set_cookie( name='universe_session', value=self.galaxy_session.id, age=0 )
|
||||
self.__galaxy_session = None
|
||||
galaxy_session = property( get_galaxy_session, set_galaxy_session )
|
||||
|
||||
def make_associations( self ):
|
||||
if self.galaxy_session_is_valid():
|
||||
if self.galaxy_session.user_id is None and self.user is not None:
|
||||
self.galaxy_session.user_id = self.user.id
|
||||
self.galaxy_session.flush()
|
||||
self.__galaxy_session = self.galaxy_session
|
||||
if self.history is not None and self.user is not None:
|
||||
self.history.user_id = self.user.id
|
||||
self.history.flush()
|
||||
self.__history = self.history
|
||||
|
||||
def get_toolbox(self):
|
||||
"""Returns the application toolbox"""
|
||||
return self.app.toolbox
|
||||
|
||||
Reference in New Issue
Block a user