APIs to add histories, add items to histories, and list the status

of datasets within a history
This commit is contained in:
John Duddy
2011-08-22 12:29:49 -07:00
parent 83163908e8
commit a083ceef9a
2 changed files with 126 additions and 54 deletions
+100 -18
View File
@@ -7,6 +7,9 @@ from galaxy import util, datatypes, jobs, web, util
from galaxy.web.base.controller import *
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.orm import *
from galaxy.model import Dataset
import galaxy.datatypes
from galaxy.util.bunch import Bunch
log = logging.getLogger( __name__ )
@@ -17,20 +20,19 @@ class HistoriesController( BaseController ):
"""
GET /api/histories
Displays a collection (list) of histories.
"""
try:
query = trans.sa_session.query( trans.app.model.History ).filter( trans.app.model.History.table.c.deleted == False )
current_user_role_ids = [ role.id for role in trans.get_current_user_roles() ]
user = trans.get_user()
query = query.filter_by( user=user, deleted=False )
"""
try:
query = trans.sa_session.query( trans.app.model.History ).filter_by( user=trans.user, deleted=False ).order_by(
desc(trans.app.model.History.table.c.update_time)).all()
except Exception, e:
log.debug("Error in history API: %s" % str(e))
rval = []
try:
for history in query:
item = history.get_api_value()
item = history.get_api_value(value_mapper={'id':trans.security.encode_id})
item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
item['id'] = trans.security.encode_id( item['id'] )
# item['id'] = trans.security.encode_id( item['id'] )
rval.append( item )
except Exception, e:
log.debug("Error in history API at constructing return list: %s" % str(e))
@@ -39,26 +41,63 @@ class HistoriesController( BaseController ):
@web.expose_api
def show( self, trans, id, **kwd ):
"""
GET /api/histories/{encoded_library_id}
GET /api/histories/{encoded_history_id}
Displays information about a history.
"""
history_id = id
params = util.Params( kwd )
def traverse( datasets ):
rval = {}
states = Dataset.states
for key, state in states.items():
rval[state] = 0
#log.debug("History API: Init rval %s" % rval)
for dataset in datasets:
item = dataset.get_api_value( view='element' )
#log.debug("History API: Set rval %s" % item['state'])
if not item['deleted']:
rval[item['state']] = rval[item['state']] + 1
return rval
try:
decoded_history_id = trans.security.decode_id( history_id )
except TypeError:
trans.response.status = 400
return "Malformed history id ( %s ) specified, unable to decode." % str( library_id )
return "Malformed history id ( %s ) specified, unable to decode." % str( history_id )
try:
history = trans.sa_session.query( trans.app.model.History ).get( decoded_history_id )
history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
if history.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
trans.response.status = 400
return("History is not owned by or shared with current user")
except:
history = None
trans.response.status = 400
return "That history does not exist."
try:
if not history or not ( trans.user_is_admin() or trans.app.security_agent.can_access_history( trans.get_current_user_roles(), history ) ):
trans.response.status = 400
return "Invalid history id ( %s ) specified." % str( history_id )
item = history.get_api_value( view='element' )
item = history.get_api_value(view='element', value_mapper={'id':trans.security.encode_id})
num_sets = len( [hda.id for hda in history.datasets if not hda.deleted] )
states = Dataset.states
state = states.ERROR
if num_sets == 0:
state = states.NEW
else:
summary = traverse(history.datasets)
#log.debug("History API: Status summary %s" % summary)
if summary[states.ERROR] > 0 or summary[states.FAILED_METADATA] > 0:
state = states.ERROR
elif summary[states.RUNNING] > 0 or summary[states.SETTING_METADATA] > 0:
state = states.RUNNING
elif summary[states.QUEUED] > 0:
state = states.QUEUED
elif summary[states.OK] == num_sets:
state = states.OK
#item['user'] = item['user'].username
item['contents_url'] = url_for( 'history_contents', history_id=history_id )
#item['datasets'] = len( item['datasets'] )
item['state'] = state
#log.debug("History API: State %s for %d datasets" % (state, num_sets))
except Exception, e:
log.debug("Error in history API at showing history detail: %s" % str(e))
return item
@@ -69,5 +108,48 @@ class HistoriesController( BaseController ):
POST /api/histories
Creates a new history.
"""
trans.response.status = 403
return "Not implemented."
params = util.Params( payload )
hist_name = util.restore_text( params.get( 'name', None ) )
new_history = trans.app.model.History( user=trans.user, name=hist_name )
trans.sa_session.add( new_history )
trans.sa_session.flush()
item = new_history.get_api_value(view='element', value_mapper={'id':trans.security.encode_id})
return item
@web.expose_api
def delete( self, trans, id, **kwd ):
"""
DELETE /api/histories/{encoded_history_id}
Deletes a history
"""
history_id = id
params = util.Params( kwd )
try:
decoded_history_id = trans.security.decode_id( history_id )
except TypeError:
trans.response.status = 400
return "Malformed history id ( %s ) specified, unable to decode." % str( history_id )
try:
history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
if history.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
trans.response.status = 400
return("History is not owned by or shared with current user")
except:
trans.response.status = 400
return "That history does not exist."
history.deleted = True
# If deleting the current history, make a new current.
if history == trans.get_history():
trans.new_history()
if trans.app.config.allow_user_dataset_purge:
for hda in history.datasets:
hda.purged = True
trans.sa_session.add( hda )
if hda.dataset.user_can_purge:
try:
hda.dataset.full_delete()
trans.sa_session.add( hda.dataset )
except:
trans.sa_session.flush()
+26 -36
View File
@@ -21,42 +21,23 @@ class HistoryContentsController( BaseController ):
"""
GET /api/histories/{encoded_history_id}/contents
Displays a collection (list) of history contents
"""
rval = []
current_user_roles = trans.get_current_user_roles()
def traverse( folder ):
admin = trans.user_is_admin()
rval = []
for subfolder in folder.active_folders:
if not admin:
can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder )
if (admin or can_access) and not subfolder.deleted:
subfolder.api_path = folder.api_path + '/' + subfolder.name
subfolder.api_type = 'folder'
rval.append( subfolder )
rval.extend( traverse( subfolder ) )
for ld in folder.datasets:
if not admin:
can_access = trans.app.security_agent.can_access_dataset( current_user_roles, ld.library_dataset_dataset_association.dataset )
if (admin or can_access) and not ld.deleted:
ld.api_path = folder.api_path + '/' + ld.name
ld.api_type = 'file'
rval.append( ld )
return rval
#log.debug("Entering Content API for history with %s" % str(history_id))
"""
try:
decoded_history_id = trans.security.decode_id( history_id )
except TypeError:
trans.response.status = 400
return "Malformed history id ( %s ) specified, unable to decode." % str( history_id )
try:
history = trans.sa_session.query( trans.app.model.History ).get( decoded_history_id )
history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
if history.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
trans.response.status = 400
return("History is not owned by or shared with current user")
except:
history = None
if not history or not ( trans.user_is_admin() or trans.app.security_agent.can_access_history( current_user_roles, history ) ):
trans.response.status = 400
return "Invalid history id ( %s ) specified." % str( history_id )
#log.debug("History item %s" % str(history))
return "That history does not exist."
rval = []
try:
for dataset in history.datasets:
api_type = "file"
@@ -93,10 +74,12 @@ class HistoryContentsController( BaseController ):
try:
content = trans.sa_session.query( model_class ).get( decoded_content_id )
except:
content = None
if not content or ( not trans.user_is_admin() and not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), content, trans.user ) ):
trans.response.status = 400
return "Invalid %s id ( %s ) specified." % ( content_type, str( content_id ) )
if content.history.user != trans.user and not trans.user_is_admin():
if trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=history).count() == 0:
trans.response.status = 400
return("History is not owned by or shared with current user")
item = content.get_api_value( view='element' )
if not item['deleted']:
# Problem: Method url_for cannot use the dataset controller
@@ -106,14 +89,21 @@ class HistoryContentsController( BaseController ):
# url_for is being phased out, so new applications should use url
item['download_url'] = url(controller='dataset', action='display', dataset_id=trans.security.encode_id(decoded_content_id), to_ext=content.ext)
except Exception, e:
log.debug("Error in history API at listing dataset: %s" % str(e))
log.debug("Error in history API at listing dataset: %s" % str(e))
return item
@web.expose_api
def create( self, trans, history_id, payload, **kwd ):
"""
POST /api/libraries/{encoded_library_id}/contents
Creates a new history content item (file or folder).
"""
trans.response.status = 403
return "Not implemented."
POST /api/libraries/{encoded_history_id}/contents
Creates a new history content item. """
params = util.Params( payload )
history_id = util.restore_text( params.get( 'history_id', None ) )
ldda_id = util.restore_text( params.get( 'ldda_id', None ) )
add_to_history = True
decoded_history_id = trans.security.decode_id( history_id )
ld_t, ld_id = trans.security.decode_string_id(ldda_id).split('.')
history = trans.sa_session.query(trans.app.model.History).get(decoded_history_id)
ldda = trans.sa_session.query(self.app.model.LibraryDatasetDatasetAssociation).get(ld_id)
hda = ldda.to_history_dataset_association(history, add_to_history=add_to_history)
history.add_dataset(hda)