Commits

James Taylor committed a37d828 Merge

Comments (0)

Files changed (111)

lib/galaxy/util/backports/__init__.py

+"""
+Modules for providing backward compatibility with future versions of Python
+""" 

lib/galaxy/util/backports/importlib/__init__.py

+"""Backport of importlib.import_module from 3.x."""
+# While not critical (and in no way guaranteed!), it would be nice to keep this
+# code compatible with Python 2.3.
+import sys
+
+def _resolve_name(name, package, level):
+    """Return the absolute name of the module to be imported."""
+    if not hasattr(package, 'rindex'):
+        raise ValueError("'package' not set to a string")
+    dot = len(package)
+    for x in xrange(level, 1, -1):
+        try:
+            dot = package.rindex('.', 0, dot)
+        except ValueError:
+            raise ValueError("attempted relative import beyond top-level "
+                              "package")
+    return "%s.%s" % (package[:dot], name)
+
+
+def import_module(name, package=None):
+    """Import a module.
+
+    The 'package' argument is required when performing a relative import. It
+    specifies the package to use as the anchor point from which to resolve the
+    relative import to an absolute import.
+
+    """
+    if name.startswith('.'):
+        if not package:
+            raise TypeError("relative imports require the 'package' argument")
+        level = 0
+        for character in name:
+            if character != '.':
+                break
+            level += 1
+        name = _resolve_name(name[level:], package, level)
+    __import__(name)
+    return sys.modules[name]
+
+    ## Note: this was copied from 
+    ## http://svn.python.org/projects/python/trunk/Lib/importlib/__init__.py
+    ## on 24 September 2012

lib/galaxy/web/__init__.py

 """
-The Galaxy web application.
+The Galaxy web application framework
 """
 
 from framework import expose, json, json_pretty, require_login, require_admin, url_for, error, form, FormBuilder, expose_api

lib/galaxy/web/api/__init__.py

Empty file removed.

lib/galaxy/web/api/datasets.py

-"""
-API operations on the contents of a dataset.
-"""
-import logging, os, string, shutil, urllib, re, socket
-from cgi import escape, FieldStorage
-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.visualization.data_providers.genome import *
-from galaxy.visualization.data_providers.basic import ColumnDataProvider
-from galaxy.datatypes.tabular import Vcf
-from galaxy.model import NoConverterException, ConverterDependencyException
-
-log = logging.getLogger( __name__ )
-
-class DatasetsController( BaseAPIController, UsesVisualizationMixin ):
-
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/datasets
-        Lists datasets.
-        """
-        pass
-        
-    @web.expose_api
-    def show( self, trans, id, hda_ldda='hda', data_type=None, **kwd ):
-        """
-        GET /api/datasets/{encoded_dataset_id}
-        Displays information about and/or content of a dataset.
-        """
-        
-        # Get dataset.
-        try:
-            dataset = self.get_hda_or_ldda( trans, hda_ldda=hda_ldda, dataset_id=id )
-        except Exception, e:
-            return str( e )
-
-        # Use data type to return particular type of data.
-        try:
-            if data_type == 'state':
-                rval = self._dataset_state( trans, dataset )
-            elif data_type == 'converted_datasets_state':
-                rval = self._converted_datasets_state( trans, dataset, kwd.get( 'chrom', None ) )
-            elif data_type == 'data':
-                rval = self._data( trans, dataset, **kwd )
-            elif data_type == 'features':
-                rval = self._search_features( trans, dataset, kwd.get( 'query ' ) )
-            elif data_type == 'raw_data':
-                rval = self._raw_data( trans, dataset, **kwd )
-            elif data_type == 'track_config':
-                rval = self.get_new_track_config( trans, dataset )
-            else:
-                # Default: return dataset as API value.
-                rval = dataset.get_api_value()
-                
-        except Exception, e:
-            rval = "Error in dataset API at listing contents"
-            log.error( rval + ": %s" % str(e), exc_info=True )
-            trans.response.status = 500
-        return rval
-
-    def _dataset_state( self, trans, dataset, **kwargs ):
-        """ Returns state of dataset. """
-            
-        msg = self.check_dataset_state( trans, dataset )
-        if not msg:
-            msg = messages.DATA
-
-        return msg
-        
-    def _converted_datasets_state( self, trans, dataset, chrom=None ):
-        """
-        Init-like method that returns state of dataset's converted datasets. Returns valid chroms
-        for that dataset as well.
-        """
-
-        msg = self.check_dataset_state( trans, dataset )
-        if msg:
-            return msg
-            
-        # Get datasources and check for messages.
-        data_sources = dataset.get_datasources( trans )
-        messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
-        msg = get_highest_priority_msg( messages_list )
-        if msg:
-            return msg
-            
-        # Check for data in the genome window.
-        data_provider_registry = trans.app.data_provider_registry
-        data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset= dataset, source='index' )
-        if not data_provider.has_data( chrom ):
-            return messages.NO_DATA
-            
-        # Have data if we get here
-        return { "status": messages.DATA, "valid_chroms": None }
-
-    def _search_features( self, trans, dataset, query ):
-        """
-        Returns features, locations in dataset that match query. Format is a 
-        list of features; each feature is a list itself: [name, location]
-        """
-        if dataset.can_convert_to( "fli" ):
-            converted_dataset = dataset.get_converted_dataset( trans, "fli" )
-            if converted_dataset:
-                data_provider = FeatureLocationIndexDataProvider( converted_dataset=converted_dataset )
-                if data_provider:
-                    return data_provider.get_data( query )
-        
-        return []
-        
-    
-    def _data( self, trans, dataset, chrom, low, high, start_val=0, max_vals=None, **kwargs ):
-        """
-        Provides a block of data from a dataset.
-        """
-    
-        # Parameter check.
-        if not chrom:
-            return messages.NO_DATA
-        
-        # Dataset check.
-        msg = self.check_dataset_state( trans, dataset )
-        if msg:
-            return msg
-            
-        # Get datasources and check for messages.
-        data_sources = dataset.get_datasources( trans )
-        messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
-        return_message = get_highest_priority_msg( messages_list )
-        if return_message:
-            return return_message
-            
-        extra_info = None
-        mode = kwargs.get( "mode", "Auto" )
-        # Handle histogram mode uniquely for now:
-        data_provider_registry = trans.app.data_provider_registry
-        if mode == "Coverage":
-            # Get summary using minimal cutoffs.
-            indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
-            summary = indexer.get_data( chrom, low, high, detail_cutoff=0, draw_cutoff=0, **kwargs )
-            if summary == "detail":
-                # Use maximum level of detail--2--to get summary data no matter the resolution.
-                summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ], level=2, detail_cutoff=0, draw_cutoff=0 )
-            return summary
-
-        if 'index' in data_sources and data_sources['index']['name'] == "summary_tree" and mode == "Auto":
-            # Only check for summary_tree if it's Auto mode (which is the default)
-            # 
-            # Have to choose between indexer and data provider
-            indexer = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
-            summary = indexer.get_data( chrom, low, high, resolution=kwargs[ 'resolution' ] )
-            if summary is None:
-                return { 'dataset_type': indexer.dataset_type, 'data': None }
-                
-            if summary == "draw":
-                kwargs["no_detail"] = True # meh
-                extra_info = "no_detail"
-            elif summary != "detail":
-                return summary
-        
-        # Get data provider.
-        data_provider = data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='data' )
-        
-        # Allow max_vals top be data provider set if not passed
-        if max_vals is None:
-            max_vals = data_provider.get_default_max_vals()
-
-        # Get and return data from data_provider.
-        result = data_provider.get_data( chrom, int( low ), int( high ), int( start_val ), int( max_vals ), **kwargs )
-        result.update( { 'dataset_type': data_provider.dataset_type, 'extra_info': extra_info } )
-        return result
-
-    def _raw_data( self, trans, dataset, **kwargs ):
-        """
-        Uses original (raw) dataset to return data. This method is useful 
-        when the dataset is not yet indexed and hence using data would
-        be slow because indexes need to be created.
-        """
-        
-        # Dataset check.
-        msg = self.check_dataset_state( trans, dataset )
-        if msg:
-            return msg
-    
-        # Return data.
-        data = None
-        data_provider = trans.app.data_provider_registry.get_data_provider( trans, raw=True, original_dataset=dataset )
-        print 'data_provider:', data_provider
-        
-        if isinstance( data_provider, ColumnDataProvider ):
-            data = data_provider.get_data( **kwargs )
-            
-        else:
-            # Default to genomic data.
-            # FIXME: need better way to set dataset_type.
-            low, high = int( kwargs.get( 'low' ) ), int( kwargs.get( 'high' ) )
-            data = data_provider.get_data( start=low, end=high, **kwargs )
-            data[ 'dataset_type' ] = 'interval_index'
-            data[ 'extra_info' ] = None
-            if isinstance( dataset.datatype, Vcf ):
-                data[ 'dataset_type' ] = 'tabix'
-        return data

lib/galaxy/web/api/forms.py

-"""
-API operations on FormDefinition objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-from galaxy.forms.forms import form_factory
-from elementtree.ElementTree import XML
-
-log = logging.getLogger( __name__ )
-
-class FormDefinitionAPIController( BaseAPIController ):
-    
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/forms
-        Displays a collection (list) of forms.
-        """
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to view the list of forms."
-        query = trans.sa_session.query( trans.app.model.FormDefinition )#.filter( trans.app.model.FormDefinition.table.c.deleted == False )
-        rval = []
-        for form_definition in query:
-            item = form_definition.get_api_value( value_mapper={ 'id': trans.security.encode_id, 'form_definition_current_id': trans.security.encode_id } )
-            item['url'] = url_for( 'form', id=trans.security.encode_id( form_definition.id ) )
-            rval.append( item )
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, **kwd ):
-        """
-        GET /api/forms/{encoded_form_id}
-        Displays information about a form.
-        """
-        form_definition_id = id
-        try:
-            decoded_form_definition_id = trans.security.decode_id( form_definition_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed form definition id ( %s ) specified, unable to decode." % str( form_definition_id )
-        try:
-            form_definition = trans.sa_session.query( trans.app.model.FormDefinition ).get( decoded_form_definition_id )
-        except:
-            form_definition = None
-        if not form_definition or not trans.user_is_admin():
-            trans.response.status = 400
-            return "Invalid form definition id ( %s ) specified." % str( form_definition_id )
-        item = form_definition.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id, 'form_definition_current_id': trans.security.encode_id } )
-        item['url'] = url_for( 'form', id=form_definition_id )
-        return item
-
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/forms
-        Creates a new form.
-        """
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to create a new form."
-        xml_text = payload.get( 'xml_text', None )
-        if xml_text is None:
-            trans.response.status = 400
-            return "Missing required parameter 'xml_text'."
-            #enhance to allow creating from more than just xml
-        form_definition = form_factory.from_elem( XML( xml_text ) )
-        trans.sa_session.add( form_definition )
-        trans.sa_session.flush()
-        encoded_id = trans.security.encode_id( form_definition.id )
-        item = form_definition.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id, 'form_definition_current_id': trans.security.encode_id } )
-        item['url'] = url_for( 'form', id=encoded_id )
-        return [ item ]

lib/galaxy/web/api/genomes.py

-from galaxy import config, tools, web, util
-from galaxy.web.base.controller import BaseController, BaseAPIController
-from galaxy.util.bunch import Bunch
-
-def is_true ( a_str ):
-    return is_true == True or a_str in [ 'True', 'true', 'T', 't' ]
-
-class GenomesController( BaseAPIController ):
-    """
-    RESTful controller for interactions with genome data.
-    """
-    
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/genomes: returns a list of installed genomes
-        """        
-        
-        return []
-
-    @web.json
-    def show( self, trans, id, num=None, chrom=None, low=None, high=None, **kwd ):
-        """
-        GET /api/genomes/{id}
-        
-        Returns information about build <id>
-        """
-
-        # Process kwds.
-        reference = is_true( kwd.get( 'reference', False ) )
-
-        # Return info.
-        rval = None
-        if reference:
-            rval = self.app.genomes.reference( trans, dbkey=id, chrom=chrom, low=low, high=high, **kwd )
-        else:
-            rval = self.app.genomes.chroms( trans, dbkey=id, num=num, chrom=chrom, low=low )
-        return rval
-    
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/genomes
-        Download and/or index a genome.
-        
-        Parameters:
-        
-        dbkey           DB key of the build to download, ignored unless 'UCSC' is specified as the source
-        ncbi_name       NCBI's genome identifier, ignored unless NCBI is specified as the source
-        ensembl_dbkey   Ensembl's genome identifier, ignored unless Ensembl is specified as the source
-        url_dbkey       DB key to use for this build, ignored unless URL is specified as the source
-        source          Data source for this build. Can be: UCSC, Ensembl, NCBI, URL
-        indexers        POST array of indexers to run after downloading (indexers[] = first, indexers[] = second, ...)
-        func            Allowed values:
-                        'download'  Download and index
-                        'index'     Index only
-                        
-        Returns:
-        
-        If no error:
-        dict( status: 'ok', job: <job ID> )
-        
-        If error:
-        dict( status: 'error', error: <error message> )
-        
-        """
-        params = util.Params( payload )
-        from galaxy.web.controllers.data_admin import build_param_dict as massage
-        paramdict = massage( params, trans )
-        func = params.get( 'func', 'download' )
-        if func == 'download':
-            url = paramdict[ 'url' ]
-            liftover = paramdict[ 'liftover' ]
-            dbkey = paramdict[ 'dbkey' ]
-            indexers = paramdict[ 'indexers' ]
-            longname = paramdict[ 'longname' ]
-            jobid = trans.app.job_manager.deferred_job_queue.plugins['GenomeTransferPlugin'].create_job( trans, url, dbkey, longname, indexers )
-            chainjob = []
-            if liftover is not None:
-                for chain in liftover:
-                    liftover_url = u'ftp://hgdownload.cse.ucsc.edu%s' % chain[0]
-                    from_genome = chain[1]
-                    to_genome = chain[2]
-                    destfile = liftover_url.split('/')[-1].replace('.gz', '')
-                    lochain = trans.app.job_manager.deferred_job_queue.plugins['LiftOverTransferPlugin'].create_job( trans, liftover_url, dbkey, from_genome, to_genome, destfile, jobid )
-                    chainjob.append( lochain )
-                job = trans.app.job_manager.deferred_job_queue.plugins['GenomeTransferPlugin'].get_job_status( jobid )
-                job.params['liftover'] = chainjob
-                trans.app.model.context.current.flush()
-            return dict( status='ok', job=jobid )
-        elif func == 'index':
-            dbkey = paramdict[ 'dbkey' ]
-            indexer = [ params.get( 'indexer', None ) ]
-            longname = None
-            path = None
-            for build in trans.app.tool_data_tables.data_tables[ 'all_fasta' ].data:
-                if build[0] == dbkey:
-                    longname = build[2]
-                    path = build[3]
-                    break
-            if longname is not None and indexer is not None and path is not None:
-                jobid = trans.app.job_manager.deferred_job_queue.plugins['GenomeIndexPlugin'].create_job( trans, path, indexer, dbkey, longname )
-                return dict( status='ok', job=jobid )
-            else:
-                return dict( status='error', error='Build not %s found in tool data table.' % dbkey )
-        else:
-            return dict( status='error', error='Unkown function selected.' )

lib/galaxy/web/api/group_roles.py

-"""
-API operations on Group objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-
-log = logging.getLogger( __name__ )
-
-class GroupRolesAPIController( BaseAPIController ):
-
-    @web.expose_api
-    @web.require_admin
-    def index( self, trans, group_id, **kwd ):
-        """
-        GET /api/groups/{encoded_group_id}/roles
-        Displays a collection (list) of groups.
-        """
-        decoded_group_id = trans.security.decode_id( group_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-        except:
-            group = None
-        if not group:
-            trans.response.status = 400
-            return "Invalid group id ( %s ) specified." % str( group_id )
-        rval = []
-        try:
-            for gra in group.roles:
-                role = gra.role
-                encoded_id = trans.security.encode_id( role.id )
-                rval.append( dict( id = encoded_id,
-                                   name = role.name,
-                                   url = url_for( 'group_role', group_id=group_id, id=encoded_id, ) ) )
-        except Exception, e:
-            rval = "Error in group API at listing roles"
-            log.error( rval + ": %s" % str(e) )
-            trans.response.status = 500
-        return rval
-
-    @web.expose_api
-    @web.require_admin
-    def show( self, trans, id, group_id, **kwd ):
-        """
-        GET /api/groups/{encoded_group_id}/roles/{encoded_role_id}
-        Displays information about a group role.
-        """
-        role_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_role_id =  trans.security.decode_id( role_id )
-        item = None
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            role = trans.sa_session.query( trans.app.model.Role ).get( decoded_role_id )
-            for gra in group.roles:
-                if gra.role == role:
-                    item = dict( id = role_id,
-                                   name = role.name,
-                                   url = url_for( 'group_role', group_id=group_id, id=role_id) ) # TODO Fix This
-            if not item:
-                item = "role %s not in group %s" % (role.name,group.name)
-        except Exception, e:
-            item = "Error in group_role API group %s role %s" % (group.name, role.name)
-            log.error(item + ": %s" % str(e))
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def update( self, trans, id, group_id, **kwd ):
-        """
-        PUT /api/groups/{encoded_group_id}/roles/{encoded_role_id}
-        Adds a role to a group
-        """
-        role_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_role_id =  trans.security.decode_id( role_id )
-        item = None
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            role = trans.sa_session.query( trans.app.model.Role ).get( decoded_role_id )
-            for gra in group.roles:
-                if gra.role == role:
-                    item = dict( id = role_id,
-                                   name = role.name,
-                                   url = url_for( 'group_role', group_id=group_id, id=role_id) ) 
-            if not item:
-                gra = trans.app.model.GroupRoleAssociation( group, role )
-                # Add GroupRoleAssociation
-                trans.sa_session.add( gra )
-                trans.sa_session.flush()
-                item = dict( id = role_id,
-                             name = role.name,
-                             url = url_for( 'group_role', group_id=group_id, id=role_id) ) 
-        except Exception, e:
-            item = "Error in group_role API Adding role %s to group %s" % (role.name,group.name)
-            log.error(item + ": %s" % str(e))
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def delete( self, trans, id, group_id, **kwd ):
-        """
-        DELETE /api/groups/{encoded_group_id}/roles/{encoded_role_id}
-        Removes a role from a group
-        """
-        role_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_role_id =  trans.security.decode_id( role_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            role = trans.sa_session.query( trans.app.model.Role ).get( decoded_role_id )
-            for gra in group.roles:
-                if gra.role == role:
-                    trans.sa_session.delete( gra )
-                    trans.sa_session.flush()
-                    item = dict( id = role_id,
-                                 name = role.name,
-                                 url = url_for( 'group_role', group_id=group_id, id=role_id) ) 
-            if not item:
-                item = "role %s not in group %s" % (role.name,group.name)
-        except Exception, e:
-            item = "Error in group_role API Removing role %s from group %s" % (role.name,group.name)
-            log.error(item + ": %s" % str(e))
-        return item

lib/galaxy/web/api/group_users.py

-"""
-API operations on Group objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-
-log = logging.getLogger( __name__ )
-
-class GroupUsersAPIController( BaseAPIController ):
-
-    @web.expose_api
-    @web.require_admin
-    def index( self, trans, group_id, **kwd ):
-        """
-        GET /api/groups/{encoded_group_id}/users
-        Displays a collection (list) of groups.
-        """
-        decoded_group_id = trans.security.decode_id( group_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-        except:
-            group = None
-        if not group:
-            trans.response.status = 400
-            return "Invalid group id ( %s ) specified." % str( group_id )
-        rval = []
-        try:
-            for uga in group.users:
-                user = uga.user
-                encoded_id = trans.security.encode_id( user.id )
-                rval.append( dict( id = encoded_id,
-                                   email = user.email,
-                                   url = url_for( 'group_user', group_id=group_id, id=encoded_id, ) ) )
-        except Exception, e:
-            rval = "Error in group API at listing users"
-            log.error( rval + ": %s" % str(e) )
-            trans.response.status = 500
-        return rval
-
-    @web.expose_api
-    @web.require_admin
-    def show( self, trans, id, group_id, **kwd ):
-        """
-        GET /api/groups/{encoded_group_id}/users/{encoded_user_id}
-        Displays information about a group user.
-        """
-        user_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_user_id =  trans.security.decode_id( user_id )
-        item = None
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            user = trans.sa_session.query( trans.app.model.User ).get( decoded_user_id )
-            for uga in group.users:
-                if uga.user == user:
-                    item = dict( id = user_id,
-                                   email = user.email,
-                                   url = url_for( 'group_user', group_id=group_id, id=user_id) ) # TODO Fix This
-            if not item:
-                item = "user %s not in group %s" % (user.email,group.name)
-        except Exception, e:
-            item = "Error in group_user API group %s user %s" % (group.name, user.email)
-            log.error(item + ": %s" % str(e))
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def update( self, trans, id, group_id, **kwd ):
-        """
-        PUT /api/groups/{encoded_group_id}/users/{encoded_user_id}
-        Adds a user to a group
-        """
-        user_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_user_id =  trans.security.decode_id( user_id )
-        item = None
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            user = trans.sa_session.query( trans.app.model.User ).get( decoded_user_id )
-            for uga in group.users:
-                if uga.user == user:
-                    item = dict( id = user_id,
-                                   email = user.email,
-                                   url = url_for( 'group_user', group_id=group_id, id=user_id) ) 
-            if not item:
-                uga = trans.app.model.UserGroupAssociation( user, group )
-                # Add UserGroupAssociations
-                trans.sa_session.add( uga )
-                trans.sa_session.flush()
-                item = dict( id = user_id,
-                             email = user.email,
-                             url = url_for( 'group_user', group_id=group_id, id=user_id) ) 
-        except Exception, e:
-            item = "Error in group_user API Adding user %s to group %s" % (user.email,group.name)
-            log.error(item + ": %s" % str(e))
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def delete( self, trans, id, group_id, **kwd ):
-        """
-        DELETE /api/groups/{encoded_group_id}/users/{encoded_user_id}
-        Removes a user from a group
-        """
-        user_id = id
-        decoded_group_id = trans.security.decode_id( group_id )
-        decoded_user_id =  trans.security.decode_id( user_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-            user = trans.sa_session.query( trans.app.model.User ).get( decoded_user_id )
-            for uga in group.users:
-                if uga.user == user:
-                    trans.sa_session.delete( uga )
-                    trans.sa_session.flush()
-                    item = dict( id = user_id,
-                                 email = user.email,
-                                 url = url_for( 'group_user', group_id=group_id, id=user_id) ) 
-            if not item:
-                item = "user %s not in group %s" % (user.email,group.name)
-        except Exception, e:
-            item = "Error in group_user API Removing user %s from group %s" % (user.email,group.name)
-            log.error(item + ": %s" % str(e))
-        return item

lib/galaxy/web/api/groups.py

-"""
-API operations on Group objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-
-
-log = logging.getLogger( __name__ )
-
-
-class GroupAPIController( BaseAPIController ):
-
-    @web.expose_api
-    @web.require_admin
-    def index( self, trans, **kwd ):
-        """
-        GET /api/groups
-        Displays a collection (list) of groups.
-        """
-        rval = []
-        for group in trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.deleted == False ):
-            if trans.user_is_admin():
-                item = group.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
-                encoded_id = trans.security.encode_id( group.id )
-                item['url'] = url_for( 'group', id=encoded_id )
-                rval.append( item )
-        return rval
-
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/groups
-        Creates a new group.
-        """
-        log.info("groups payload%s\n" % (payload)) 
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to create a new group."
-        name = payload.get( 'name', None )
-        if not name:
-            trans.response.status = 400
-            return "Enter a valid name"
-        if trans.sa_session.query( trans.app.model.Group ).filter( trans.app.model.Group.table.c.name==name ).first():
-            trans.response.status = 400
-            return "A group with that name already exists"
-
-        group = trans.app.model.Group( name=name )
-        trans.sa_session.add( group )
-        user_ids = payload.get( 'user_ids', [] )
-        for i in user_ids:
-          log.info("user_id: %s\n" % (i )) 
-          log.info("%s %s\n" % (i, trans.security.decode_id( i ) )) 
-        users = [ trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( i ) ) for i in user_ids ]
-        role_ids = payload.get( 'role_ids', [] )
-        roles = [ trans.sa_session.query( trans.model.Role ).get( trans.security.decode_id( i ) ) for i in role_ids ]
-        trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=roles, users=users )
-        """
-        # Create the UserGroupAssociations
-        for user in users:
-            trans.app.security_agent.associate_user_group( user, group )
-        # Create the GroupRoleAssociations
-        for role in roles:
-            trans.app.security_agent.associate_group_role( group, role )
-        """
-        trans.sa_session.flush()
-        encoded_id = trans.security.encode_id( group.id )
-        item = group.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
-        item['url'] = url_for( 'group', id=encoded_id )
-        return [ item ]
-
-    @web.expose_api
-    @web.require_admin
-    def show( self, trans, id, **kwd ):
-        """
-        GET /api/groups/{encoded_group_id}
-        Displays information about a group.
-        """
-        group_id = id
-        try:
-            decoded_group_id = trans.security.decode_id( group_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed group id ( %s ) specified, unable to decode." % str( group_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-        except:
-            group = None
-        if not group:
-            trans.response.status = 400
-            return "Invalid group id ( %s ) specified." % str( group_id )
-        item = group.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
-        item['url'] = url_for( 'group', id=group_id )
-        item['users_url'] = url_for( 'group_users', group_id=group_id )
-        item['roles_url'] = url_for( 'group_roles', group_id=group_id )
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def update( self, trans, id, payload, **kwd ):
-        """
-        PUT /api/groups/{encoded_group_id}
-        Modifies a group.
-        """
-        group_id = id
-        try:
-            decoded_group_id = trans.security.decode_id( group_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed group id ( %s ) specified, unable to decode." % str( group_id )
-        try:
-            group = trans.sa_session.query( trans.app.model.Group ).get( decoded_group_id )
-        except:
-            group = None
-        if not group:
-            trans.response.status = 400
-            return "Invalid group id ( %s ) specified." % str( group_id )
-        name = payload.get( 'name', None )
-        if name:
-          group.name = name
-          trans.sa_session.add(group)
-        user_ids = payload.get( 'user_ids', [] )
-        users = [ trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( i ) ) for i in user_ids ]
-        role_ids = payload.get( 'role_ids', [] )
-        roles = [ trans.sa_session.query( trans.model.Role ).get( trans.security.decode_id( i ) ) for i in role_ids ]
-        trans.app.security_agent.set_entity_group_associations( groups=[ group ], roles=roles, users=users,delete_existing_assocs=False )
-        trans.sa_session.flush()
-

lib/galaxy/web/api/histories.py

-"""
-API operations on a history.
-"""
-import logging, os, string, shutil, urllib, re, socket
-from cgi import escape, FieldStorage
-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 *
-import galaxy.datatypes
-from galaxy.util.bunch import Bunch
-
-log = logging.getLogger( __name__ )
-
-class HistoriesController( BaseAPIController, UsesHistoryMixin ):
-
-    @web.expose_api
-    def index( self, trans, deleted='False', **kwd ):
-        """
-        GET /api/histories
-        GET /api/histories/deleted
-        Displays a collection (list) of histories.
-        """
-        rval = []
-        deleted = util.string_as_bool( deleted )
-        try:
-            if trans.user:
-                query = trans.sa_session.query(trans.app.model.History ).filter_by( user=trans.user, deleted=deleted ).order_by(
-                    desc(trans.app.model.History.table.c.update_time)).all()
-                for history in query:
-                    item = history.get_api_value(value_mapper={'id':trans.security.encode_id})
-                    item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
-                    rval.append( item )
-            elif trans.galaxy_session.current_history:
-                #No user, this must be session authentication with an anonymous user.
-                history = trans.galaxy_session.current_history
-                item = history.get_api_value(value_mapper={'id':trans.security.encode_id})
-                item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
-                rval.append(item)
-        except Exception, e:
-            rval = "Error in history API"
-            log.error( rval + ": %s" % str(e) )
-            trans.response.status = 500
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, deleted='False', **kwd ):
-        """
-        GET /api/histories/{encoded_history_id}
-        GET /api/histories/deleted/{encoded_history_id}
-        Displays information about a history.
-        """
-        history_id = id
-        params = util.Params( kwd )
-        deleted = util.string_as_bool( deleted )
-
-        def traverse( datasets ):
-            rval = {}
-            states = trans.app.model.Dataset.states
-            for key, state in states.items():
-                rval[state] = 0
-            for dataset in datasets:
-                item = dataset.get_api_value( view='element' )
-                if not item['deleted']:
-                    rval[item['state']] = rval[item['state']] + 1
-            return rval
-        try:
-            history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=deleted )
-        except Exception, e:
-            return str( e )
-        try:
-            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 = trans.app.model.Dataset.states
-            state = states.ERROR
-            if num_sets == 0:
-                state = states.NEW
-            else:
-                summary = traverse(history.datasets)
-                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['contents_url'] = url_for( 'history_contents', history_id=history_id )
-                item['state_details'] = summary
-            item['state'] = state
-        except Exception, e:
-            item = "Error in history API at showing history detail"
-            log.error(item + ": %s" % str(e))
-            trans.response.status = 500
-        return item
-
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/histories
-        Creates a new history.
-        """
-        params = util.Params( payload )
-        hist_name = None
-        if payload.get( 'name', None ):
-            hist_name = util.restore_text( payload['name'] )
-        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})
-        item['url'] = url_for( 'history', id=item['id'] )
-        return item
-
-    @web.expose_api
-    def delete( self, trans, id, **kwd ):
-        """
-        DELETE /api/histories/{encoded_history_id}
-        Deletes a history
-        """
-        history_id = id
-        # a request body is optional here
-        purge = False
-        if kwd.get( 'payload', None ):
-            purge = util.string_as_bool( kwd['payload'].get( 'purge', False ) )
-
-        try:
-            history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False, deleted=True )
-        except Exception, e:
-            return str( e )
-
-        history.deleted = True
-        if purge and trans.app.config.allow_user_dataset_purge:
-            # First purge all the datasets
-            for hda in history.datasets:
-                if hda.purged:
-                    continue
-                hda.purged = True
-                trans.sa_session.add( hda )
-                trans.sa_session.flush()
-                if hda.dataset.user_can_purge:
-                    try:
-                        hda.dataset.full_delete()
-                        trans.sa_session.add( hda.dataset )
-                    except:
-                        pass
-                    trans.sa_session.flush()
-            # Now mark the history as purged
-            history.purged = True
-            self.sa_session.add( history )
-
-        trans.sa_session.flush()
-        return 'OK'
-
-    @web.expose_api
-    def undelete( self, trans, id, **kwd ):
-        """
-        POST /api/histories/deleted/{encoded_history_id}/undelete
-        Undeletes a history
-        """
-        history_id = id
-        history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False, deleted=True )
-        history.deleted = False
-        trans.sa_session.add( history )
-        trans.sa_session.flush()
-        return 'OK'

lib/galaxy/web/api/history_contents.py

-"""
-API operations on the contents of a history.
-"""
-import logging
-from galaxy import web
-from galaxy.web.base.controller import BaseAPIController, url_for, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesLibraryMixin, UsesLibraryMixinItems
-
-import pkg_resources
-pkg_resources.require( "Routes" )
-import routes
-
-log = logging.getLogger( __name__ )
-
-class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesLibraryMixin, UsesLibraryMixinItems ):
-
-    @web.expose_api
-    def index( self, trans, history_id, **kwd ):
-        """
-        GET /api/histories/{encoded_history_id}/contents
-        Displays a collection (list) of history contents
-        """
-        try:
-            history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True )
-        except Exception, e:
-            return str( e )
-        rval = []
-        try:
-            for dataset in history.datasets:
-                api_type = "file"
-                encoded_id = trans.security.encode_id( dataset.id )
-                rval.append( dict( id = encoded_id,
-                                   type = api_type,
-                                   name = dataset.name,
-                                   url = url_for( 'history_content', history_id=history_id, id=encoded_id, ) ) )
-        except Exception, e:
-            rval = "Error in history API at listing contents"
-            log.error( rval + ": %s" % str(e) )
-            trans.response.status = 500
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, history_id, **kwd ):
-        """
-        GET /api/histories/{encoded_history_id}/contents/{encoded_content_id}
-        Displays information about a history content (dataset).
-        """
-        content_id = id
-        try:
-            # get the history just for the access checks
-            history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=False )
-            content = self.get_history_dataset_association( trans, history, content_id, check_ownership=True, check_accessible=True )
-        except Exception, e:
-            return str( e )
-        try:
-            item = content.get_api_value( view='element' )
-            if trans.user_is_admin() or trans.app.config.expose_dataset_path:
-                 item['file_name'] = content.file_name
-            if not item['deleted']:
-                # Problem: Method url_for cannot use the dataset controller
-                # Get the environment from DefaultWebTransaction and use default webapp mapper instead of webapp API mapper
-                url = routes.URLGenerator(trans.webapp.mapper, trans.environ)
-                # http://routes.groovie.org/generating.html
-                # 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(content.id), to_ext=content.ext)
-                item = self.encode_all_ids( trans, item )
-        except Exception, e:
-            item = "Error in history API at listing dataset"
-            log.error( item + ": %s" % str(e) )
-            trans.response.status = 500
-        return item
-
-    @web.expose_api
-    def create( self, trans, history_id, payload, **kwd ):
-        """
-        POST /api/histories/{encoded_history_id}/contents
-        Creates a new history content item (file, aka HistoryDatasetAssociation).
-        """
-        from_ld_id = payload.get( 'from_ld_id', None )
-
-        try:
-            history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False )
-        except Exception, e:
-            return str( e )
-
-        if from_ld_id:
-            try:
-                ld = self.get_library_dataset( trans, from_ld_id, check_ownership=False, check_accessible=False )
-                assert type( ld ) is trans.app.model.LibraryDataset, "Library content id ( %s ) is not a dataset" % from_ld_id
-            except AssertionError, e:
-                trans.response.status = 400
-                return str( e )
-            except Exception, e:
-                return str( e )
-            hda = ld.library_dataset_dataset_association.to_history_dataset_association( history, add_to_history=True )
-            trans.sa_session.flush()
-            return hda.get_api_value()
-        else:
-            # TODO: implement other "upload" methods here.
-            trans.response.status = 403
-            return "Not implemented."
-

lib/galaxy/web/api/libraries.py

-"""
-API operations on a library.
-"""
-import logging, os, string, shutil, urllib, re, socket
-from cgi import escape, FieldStorage
-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 paste.httpexceptions import *
-
-log = logging.getLogger( __name__ )
-
-class LibrariesController( BaseAPIController ):
-    
-    @web.expose_api
-    def index( self, trans, deleted='False', **kwd ):
-        """
-        GET /api/libraries
-        GET /api/libraries/deleted
-        Displays a collection (list) of libraries.
-        """
-        query = trans.sa_session.query( trans.app.model.Library )
-        deleted = util.string_as_bool( deleted )
-        if deleted:
-            route = 'deleted_library'
-            query = query.filter( trans.app.model.Library.table.c.deleted == True )
-        else:
-            route = 'library'
-            query = query.filter( trans.app.model.Library.table.c.deleted == False )
-        current_user_role_ids = [ role.id for role in trans.get_current_user_roles() ]
-        library_access_action = trans.app.security_agent.permitted_actions.LIBRARY_ACCESS.action
-        restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
-                                                                           .filter( trans.model.LibraryPermissions.table.c.action == library_access_action ) \
-                                                                           .distinct() ]
-        accessible_restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
-                                                                                      .filter( and_( trans.model.LibraryPermissions.table.c.action == library_access_action,
-                                                                                                     trans.model.LibraryPermissions.table.c.role_id.in_( current_user_role_ids ) ) ) ]
-        query = query.filter( or_( not_( trans.model.Library.table.c.id.in_( restricted_library_ids ) ),
-                           trans.model.Library.table.c.id.in_( accessible_restricted_library_ids ) ) )
-        rval = []
-        for library in query:
-            item = library.get_api_value()
-            item['url'] = url_for( route, id=trans.security.encode_id( library.id ) )
-            item['id'] = trans.security.encode_id( item['id'] )
-            rval.append( item )
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, deleted='False', **kwd ):
-        """
-        GET /api/libraries/{encoded_library_id}
-        GET /api/libraries/deleted/{encoded_library_id}
-        Displays information about a library.
-        """
-        library_id = id
-        deleted = util.string_as_bool( deleted )
-        params = util.Params( kwd )
-        try:
-            decoded_library_id = trans.security.decode_id( library_id )
-        except TypeError:
-            raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
-        try:
-            library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
-            assert library.deleted == deleted
-        except:
-            library = None
-        if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
-            raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
-        item = library.get_api_value( view='element' )
-        #item['contents_url'] = url_for( 'contents', library_id=library_id )
-        item['contents_url'] = url_for( 'library_contents', library_id=library_id )
-        return item
-
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/libraries
-        Creates a new library.
-        """
-        if not trans.user_is_admin():
-            raise HTTPForbidden( detail='You are not authorized to create a new library.' )
-        params = util.Params( payload )
-        name = util.restore_text( params.get( 'name', None ) )
-        if not name:
-            raise HTTPBadRequest( detail="Missing required parameter 'name'." )
-        description = util.restore_text( params.get( 'description', '' ) )
-        synopsis = util.restore_text( params.get( 'synopsis', '' ) )
-        if synopsis in [ 'None', None ]:
-            synopsis = ''
-        library = trans.app.model.Library( name=name, description=description, synopsis=synopsis )
-        root_folder = trans.app.model.LibraryFolder( name=name, description='' )
-        library.root_folder = root_folder
-        trans.sa_session.add_all( ( library, root_folder ) )
-        trans.sa_session.flush()
-        encoded_id = trans.security.encode_id( library.id )
-        rval = {}
-        rval['url'] = url_for( 'library', id=encoded_id )
-        rval['name'] = name
-        rval['id'] = encoded_id
-        return rval
-
-    @web.expose_api
-    def delete( self, trans, id, **kwd ):
-        if not trans.user_is_admin():
-            raise HTTPForbidden( detail='You are not authorized to delete libraries.' )
-        try:
-            decoded_id = trans.security.decode_id( id )
-        except TypeError:
-            raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
-        try:
-            library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
-        except:
-            library = None
-        if not library:
-            raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
-        library.deleted = True
-        trans.sa_session.add( library )
-        trans.sa_session.flush()
-        return library.get_api_value( view='element', value_mapper={ 'id' : trans.security.encode_id } )

lib/galaxy/web/api/library_contents.py

-"""
-API operations on the contents of a library.
-"""
-import logging, os, string, shutil, urllib, re, socket
-from cgi import escape, FieldStorage
-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 *
-
-log = logging.getLogger( __name__ )
-
-class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):
-
-    @web.expose_api
-    def index( self, trans, library_id, **kwd ):
-        """
-        GET /api/libraries/{encoded_library_id}/contents
-        Displays a collection (list) of library contents (files and folders).
-        """
-        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
-        try:
-            decoded_library_id = trans.security.decode_id( library_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed library id ( %s ) specified, unable to decode." % str( library_id )
-        try:
-            library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
-        except:
-            library = None
-        if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( current_user_roles, library ) ):
-            trans.response.status = 400
-            return "Invalid library id ( %s ) specified." % str( library_id )
-        encoded_id = 'F' + trans.security.encode_id( library.root_folder.id )
-        rval.append( dict( id = encoded_id,
-                           type = 'folder',
-                           name = '/',
-                           url = url_for( 'library_content', library_id=library_id, id=encoded_id ) ) )
-        library.root_folder.api_path = ''
-        for content in traverse( library.root_folder ):
-            encoded_id = trans.security.encode_id( content.id )
-            if content.api_type == 'folder':
-                encoded_id = 'F' + encoded_id
-            rval.append( dict( id = encoded_id,
-                               type = content.api_type,
-                               name = content.api_path,
-                               url = url_for( 'library_content', library_id=library_id, id=encoded_id, ) ) )
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, library_id, **kwd ):
-        """
-        GET /api/libraries/{encoded_library_id}/contents/{encoded_content_id}
-        Displays information about a library content (file or folder).
-        """
-        class_name, content_id = self.__decode_library_content_id( trans, id )
-        if class_name == 'LibraryFolder':
-            content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True )
-        else:
-            content = self.get_library_dataset( trans, content_id, check_ownership=False, check_accessible=True )
-        return self.encode_all_ids( trans, content.get_api_value( view='element' ) )
-
-    @web.expose_api
-    def create( self, trans, library_id, payload, **kwd ):
-        """
-        POST /api/libraries/{encoded_library_id}/contents
-        Creates a new library content item (file or folder).
-        """
-        create_type = None
-        if 'create_type' not in payload:
-            trans.response.status = 400
-            return "Missing required 'create_type' parameter."
-        else:
-            create_type = payload.pop( 'create_type' )
-        if create_type not in ( 'file', 'folder' ):
-            trans.response.status = 400
-            return "Invalid value for 'create_type' parameter ( %s ) specified." % create_type
-        if 'folder_id' not in payload:
-            trans.response.status = 400
-            return "Missing requred 'folder_id' parameter."
-        else:
-            folder_id = payload.pop( 'folder_id' )
-            class_name, folder_id = self.__decode_library_content_id( trans, folder_id )
-        try:
-            # security is checked in the downstream controller
-            parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessible=False )
-        except Exception, e:
-            return str( e )
-        # The rest of the security happens in the library_common controller.
-        real_folder_id = trans.security.encode_id( parent.id )
-        # Now create the desired content object, either file or folder.
-        if create_type == 'file':
-            status, output = trans.webapp.controllers['library_common'].upload_library_dataset( trans, 'api', library_id, real_folder_id, **payload )
-        elif create_type == 'folder':
-            status, output = trans.webapp.controllers['library_common'].create_folder( trans, 'api', real_folder_id, library_id, **payload )
-        if status != 200:
-            trans.response.status = status
-            return output
-        else:
-            rval = []
-            for k, v in output.items():
-                if type( v ) == trans.app.model.LibraryDatasetDatasetAssociation:
-                    v = v.library_dataset
-                encoded_id = trans.security.encode_id( v.id )
-                if create_type == 'folder':
-                    encoded_id = 'F' + encoded_id
-                rval.append( dict( id = encoded_id,
-                                   name = v.name,
-                                   url = url_for( 'library_content', library_id=library_id, id=encoded_id ) ) )
-            return rval
-
-    @web.expose_api
-    def update( self, trans, id,  library_id, payload, **kwd ):
-        """
-        PUT /api/libraries/{encoded_library_id}/contents/{encoded_content_type_and_id}
-        Sets relationships among items
-        """
-        if 'converted_dataset_id' in payload:
-            converted_id = payload.pop( 'converted_dataset_id' )
-            content = self.get_library_dataset( trans, id, check_ownership=False, check_accessible=False )
-            content_conv = self.get_library_dataset( trans, converted_id, check_ownership=False, check_accessible=False )
-            assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = content.library_dataset_dataset_association,
-                dataset = content_conv.library_dataset_dataset_association,
-                file_type = content_conv.library_dataset_dataset_association.extension,
-                metadata_safe = True )
-            trans.sa_session.add( assoc )
-            trans.sa_session.flush()
-
-    def __decode_library_content_id( self, trans, content_id ):
-        if ( len( content_id ) % 16 == 0 ):
-            return 'LibraryDataset', content_id
-        elif ( content_id.startswith( 'F' ) ):
-            return 'LibraryFolder', content_id[1:]
-        else:
-            raise HTTPBadRequest( 'Malformed library content id ( %s ) specified, unable to decode.' % str( content_id ) )

lib/galaxy/web/api/permissions.py

-"""
-API operations on the permissions of a library.
-"""
-import logging, os, string, shutil, urllib, re, socket
-from cgi import escape, FieldStorage
-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 *
-
-log = logging.getLogger( __name__ )
-
-class PermissionsController( BaseAPIController ):
-    
-    # Method not ideally named
-    @web.expose_api
-    def create( self, trans, library_id, payload, **kwd ): 
-        """
-        POST /api/libraries/{encoded_library_id}/permissions
-        Updates the library permissions.
-        """
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to update library permissions."
-
-        params = util.Params( payload )
-        try:
-            decoded_library_id = trans.security.decode_id( library_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed library id ( %s ) specified, unable to decode." % str( library_id )
-
-        try:
-            library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
-        except:
-            library = None
-
-        permissions = {}
-        for k, v in trans.app.model.Library.permitted_actions.items():
-            role_params = params.get( k + '_in', [] )
-            in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
-            permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
-        trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
-        trans.sa_session.refresh( library )
-        # Copy the permissions to the root folder
-        trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
-        message = "Permissions updated for library '%s'." % library.name
-
-        item = library.get_api_value( view='element' )
-        return item
-

lib/galaxy/web/api/quotas.py

-"""
-API operations on Quota objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, Admin, UsesQuotaMixin, url_for
-from galaxy import web, util
-from elementtree.ElementTree import XML
-
-from galaxy.web.params import QuotaParamParser
-from galaxy.actions.admin import AdminActions
-
-from paste.httpexceptions import HTTPBadRequest
-from galaxy.exceptions import *
-
-log = logging.getLogger( __name__ )
-
-class QuotaAPIController( BaseAPIController, Admin, AdminActions, UsesQuotaMixin, QuotaParamParser ):
-    @web.expose_api
-    @web.require_admin
-    def index( self, trans, deleted='False', **kwd ):
-        """
-        GET /api/quotas
-        GET /api/quotas/deleted
-        Displays a collection (list) of quotas.
-        """
-        rval = []
-        deleted = util.string_as_bool( deleted )
-        query = trans.sa_session.query( trans.app.model.Quota )
-        if deleted:
-            route = 'deleted_quota'
-            query = query.filter( trans.app.model.Quota.table.c.deleted == True )
-        else:
-            route = 'quota'
-            query = query.filter( trans.app.model.Quota.table.c.deleted == False )
-        for quota in query:
-            item = quota.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
-            encoded_id = trans.security.encode_id( quota.id )
-            item['url'] = url_for( route, id=encoded_id )
-            rval.append( item )
-        return rval
-
-    @web.expose_api
-    @web.require_admin
-    def show( self, trans, id, deleted='False', **kwd ):
-        """
-        GET /api/quotas/{encoded_quota_id}
-        GET /api/quotas/deleted/{encoded_quota_id}
-        Displays information about a quota.
-        """
-        quota = self.get_quota( trans, id, deleted=util.string_as_bool( deleted ) )
-        return quota.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
-    
-    @web.expose_api
-    @web.require_admin
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/quotas
-        Creates a new quota.
-        """
-        try:
-            self.validate_in_users_and_groups( trans, payload )
-        except Exception, e:
-            raise HTTPBadRequest( detail=str( e ) )
-        params = self.get_quota_params( payload )
-        try:
-            quota, message = self._create_quota( params )
-        except ActionInputError, e:
-            raise HTTPBadRequest( detail=str( e ) )
-        item = quota.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
-        item['url'] = url_for( 'quota', id=trans.security.encode_id( quota.id ) )
-        item['message'] = message
-        return item
-
-    @web.expose_api
-    @web.require_admin
-    def update( self, trans, id, payload, **kwd ):
-        """
-        PUT /api/quotas/{encoded_quota_id}
-        Modifies a quota.
-        """
-        try:
-            self.validate_in_users_and_groups( trans, payload )
-        except Exception, e:
-            raise HTTPBadRequest( detail=str( e ) )
-
-        quota = self.get_quota( trans, id, deleted=False )
-
-        # FIXME: Doing it this way makes the update non-atomic if a method fails after an earlier one has succeeded.
-        payload['id'] = id
-        params = self.get_quota_params( payload )
-        methods = []
-        if payload.get( 'name', None ) or payload.get( 'description', None ):
-            methods.append( self._rename_quota )
-        if payload.get( 'amount', None ):
-            methods.append( self._edit_quota )
-        if payload.get( 'default', None ) == 'no':
-            methods.append( self._unset_quota_default )
-        elif payload.get( 'default', None ):
-            methods.append( self._set_quota_default )
-        if payload.get( 'in_users', None ) or payload.get( 'in_groups', None ):
-            methods.append( self._manage_users_and_groups_for_quota )
-
-        messages = []
-        for method in methods:
-            try:
-                message = method( quota, params )
-            except ActionInputError, e:
-                raise HTTPBadRequest( detail=str( e ) )
-            messages.append( message )
-        return '; '.join( messages )
-
-    @web.expose_api
-    @web.require_admin
-    def delete( self, trans, id, **kwd ):
-        """
-        DELETE /api/quotas/{encoded_quota_id}
-        Deletes a quota
-        """
-        quota = self.get_quota( trans, id, deleted=False ) # deleted quotas are not technically members of this collection
-
-        # a request body is optional here
-        payload = kwd.get( 'payload', {} )
-        payload['id'] = id
-        params = self.get_quota_params( payload )
-
-        try:
-            message = self._mark_quota_deleted( quota, params )
-            if util.string_as_bool( payload.get( 'purge', False ) ):
-                message += self._purge_quota( quota, params )
-        except ActionInputError, e:
-            raise HTTPBadRequest( detail=str( e ) )
-        return message
-
-    @web.expose_api
-    @web.require_admin
-    def undelete( self, trans, id, **kwd ):
-        """
-        POST /api/quotas/deleted/{encoded_quota_id}/undelete
-        Undeletes a quota
-        """
-        quota = self.get_quota( trans, id, deleted=True )
-        params = self.get_quota_params( payload )
-        try:
-            return self._undelete_quota( quota, params )
-        except ActionInputError, e:
-            raise HTTPBadRequest( detail=str( e ) )

lib/galaxy/web/api/request_types.py

-"""
-API operations on RequestType objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-from galaxy.sample_tracking.request_types import request_type_factory
-from elementtree.ElementTree import XML
-
-log = logging.getLogger( __name__ )
-
-
-class RequestTypeAPIController( BaseAPIController ):
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/request_types
-        Displays a collection (list) of request_types.
-        """
-        rval = []
-        for request_type in trans.app.security_agent.get_accessible_request_types( trans, trans.user ):
-            item = request_type.get_api_value( value_mapper={ 'id': trans.security.encode_id, 'request_form_id': trans.security.encode_id, 'sample_form_id': trans.security.encode_id } )
-            encoded_id = trans.security.encode_id( request_type.id )
-            item['url'] = url_for( 'request_type', id=encoded_id )
-            rval.append( item )
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, **kwd ):
-        """
-        GET /api/request_types/{encoded_request_type_id}
-        Displays information about a request_type.
-        """
-        request_type_id = id
-        try:
-            decoded_request_type_id = trans.security.decode_id( request_type_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed request type id ( %s ) specified, unable to decode." % str( request_type_id )
-        try:
-            request_type = trans.sa_session.query( trans.app.model.RequestType ).get( decoded_request_type_id )
-        except:
-            request_type = None
-        if not request_type:# or not trans.user_is_admin():
-            trans.response.status = 400
-            return "Invalid request_type id ( %s ) specified." % str( request_type_id )
-        if not trans.app.security_agent.can_access_request_type( trans.user.all_roles(), request_type ):
-            trans.response.status = 400
-            return "No permission to access request_type ( %s )." % str( request_type_id )
-        item = request_type.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id, 'request_form_id': trans.security.encode_id, 'sample_form_id': trans.security.encode_id } )
-        item['url'] = url_for( 'request_type', id=request_type_id )
-        return item
-
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/request_types
-        Creates a new request type (external_service configuration).
-        """
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to create a new request type (external_service configuration)."
-        xml_text = payload.get( 'xml_text', None )
-        if xml_text is None:
-            trans.response.status = 400
-            return "Missing required parameter 'xml_text'."
-        elem = XML( xml_text )
-        request_form_id = payload.get( 'request_form_id', None )
-        if request_form_id is None:
-            trans.response.status = 400
-            return "Missing required parameter 'request_form_id'."
-        request_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( request_form_id ) )
-        sample_form_id = payload.get( 'sample_form_id', None )
-        if sample_form_id is None:
-            trans.response.status = 400
-            return "Missing required parameter 'sample_form_id'."
-        sample_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( sample_form_id ) )
-        external_service_id = payload.get( 'external_service_id', None )
-        if external_service_id is None:
-            trans.response.status = 400
-            return "Missing required parameter 'external_service_id'."
-        external_service = trans.sa_session.query( trans.app.model.ExternalService ).get( trans.security.decode_id( external_service_id ) )
-        request_type = request_type_factory.from_elem( elem, request_form, sample_form, external_service )
-        #FIXME: move permission building/setting to separate abstract method call and
-        #allow setting individual permissions by role (currently only one action, so not strictly needed)
-        role_ids = payload.get( 'role_ids', [] )
-        roles = [ trans.sa_session.query( trans.model.Role ).get( trans.security.decode_id( i ) ) for i in role_ids ]# if trans.app.security_agent.ok_to_display( trans.user, i ) ]
-        permissions = {}
-        if roles:
-            #yikes, there has to be a better way?
-            for k, v in trans.model.RequestType.permitted_actions.items():
-                permissions[ trans.app.security_agent.get_action( v.action ) ] = roles
-        if permissions:
-            trans.app.security_agent.set_request_type_permissions( request_type, permissions )
-        
-        #flush objects
-        trans.sa_session.add( request_type )
-        trans.sa_session.flush()
-        encoded_id = trans.security.encode_id( request_type.id )
-        item = request_type.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id, 'request_form_id': trans.security.encode_id, 'sample_form_id': trans.security.encode_id } )
-        item['url'] = url_for( 'request_type', id=encoded_id )
-        return [ item ]

lib/galaxy/web/api/requests.py

-"""
-API operations on a sample tracking system.
-"""
-import logging
-from galaxy import util, web
-from galaxy.web.base.controller import *
-from galaxy.model.orm import *
-from galaxy.util.bunch import Bunch
-
-log = logging.getLogger( __name__ )
-
-class RequestsAPIController( BaseAPIController ):
-    _update_types = Bunch( REQUEST = 'request_state' )
-    _update_type_values = [v[1] for v in _update_types.items()]
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/requests
-        Displays a collection (list) of sequencing requests.
-        """
-        # if admin user then return all requests
-        if trans.user_is_admin():
-            query = trans.sa_session.query( trans.app.model.Request )\
-                                    .filter(  trans.app.model.Request.table.c.deleted == False )\
-                                    .all()
-        else:
-            query = trans.sa_session.query( trans.app.model.Request )\
-                                    .filter( and_( trans.app.model.Request.table.c.user_id == trans.user.id \
-                                                   and trans.app.model.Request.table.c.deleted == False ) ) \
-                                    .all()
-        rval = []
-        for request in query:
-            item = request.get_api_value()
-            item['url'] = url_for( 'requests', id=trans.security.encode_id( request.id ) )
-            item['id'] = trans.security.encode_id( item['id'] )
-            if trans.user_is_admin():
-                item['user'] = request.user.email
-            rval.append( item )
-        return rval
-    @web.expose_api
-    def show( self, trans, id, **kwd ):
-        """
-        GET /api/requests/{encoded_request_id}
-        Displays details of a sequencing request.
-        """
-        try:
-            request_id = trans.security.decode_id( id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed  %s id ( %s ) specified, unable to decode." % ( update_type, str( id ) )
-        try:
-            request = trans.sa_session.query( trans.app.model.Request ).get( request_id )
-        except:
-            request = None
-        if not request or not ( trans.user_is_admin() or request.user.id == trans.user.id ):
-            trans.response.status = 400
-            return "Invalid request id ( %s ) specified." % str( request_id )
-        item = request.get_api_value()
-        item['url'] = url_for( 'requests', id=trans.security.encode_id( request.id ) )
-        item['id'] = trans.security.encode_id( item['id'] )
-        item['user'] = request.user.email
-        item['num_of_samples'] = len(request.samples)
-        return item
-    @web.expose_api
-    def update( self, trans, id, key, payload, **kwd ):
-        """
-        PUT /api/requests/{encoded_request_id}
-        Updates a request state, sample state or sample dataset transfer status
-        depending on the update_type
-        """
-        params = util.Params( kwd )
-        update_type = None
-        if 'update_type' not in payload:
-            trans.response.status = 400
-            return "Missing required 'update_type' parameter.  Please consult the API documentation for help."
-        else:
-            update_type = payload.pop( 'update_type' )
-        if update_type not in self._update_type_values:
-            trans.response.status = 400
-            return "Invalid value for 'update_type' parameter ( %s ) specified.  Please consult the API documentation for help." % update_type
-        try:
-            request_id = trans.security.decode_id( id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed  request id ( %s ) specified, unable to decode." % str( id )
-        try:
-            request = trans.sa_session.query( trans.app.model.Request ).get( request_id )
-        except:
-            request = None
-        if not request or not ( trans.user_is_admin() or request.user.id == trans.user.id ):
-            trans.response.status = 400
-            return "Invalid request id ( %s ) specified." % str( request_id )
-        # check update type
-        if update_type == 'request_state': 
-            return self.__update_request_state( trans, encoded_request_id=id )
-
-    def __update_request_state( self, trans, encoded_request_id ):
-        requests_common_cntrller = trans.webapp.controllers['requests_common']
-        status, output = requests_common_cntrller.update_request_state( trans, 
-                                                                        cntrller='api', 
-                                                                        request_id=encoded_request_id )
-        return status, output

lib/galaxy/web/api/roles.py

-"""
-API operations on Role objects.
-"""
-import logging
-from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy import web
-from elementtree.ElementTree import XML
-
-log = logging.getLogger( __name__ )
-
-class RoleAPIController( BaseAPIController ):
-    @web.expose_api
-    def index( self, trans, **kwd ):
-        """
-        GET /api/roles
-        Displays a collection (list) of roles.
-        """
-        rval = []
-        for role in trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.deleted == False ):
-            if trans.user_is_admin() or trans.app.security_agent.ok_to_display( trans.user, role ):
-                item = role.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
-                encoded_id = trans.security.encode_id( role.id )
-                item['url'] = url_for( 'role', id=encoded_id )
-                rval.append( item )
-        return rval
-
-    @web.expose_api
-    def show( self, trans, id, **kwd ):
-        """
-        GET /api/roles/{encoded_role_id}
-        Displays information about a role.
-        """
-        role_id = id
-        try:
-            decoded_role_id = trans.security.decode_id( role_id )
-        except TypeError:
-            trans.response.status = 400
-            return "Malformed role id ( %s ) specified, unable to decode." % str( role_id )
-        try:
-            role = trans.sa_session.query( trans.app.model.Role ).get( decoded_role_id )
-        except:
-            role = None
-        if not role or not (trans.user_is_admin() or trans.app.security_agent.ok_to_display( trans.user, role )):
-            trans.response.status = 400
-            return "Invalid role id ( %s ) specified." % str( role_id )
-        item = role.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
-        item['url'] = url_for( 'role', id=role_id )
-        return item
-    
-    @web.expose_api
-    def create( self, trans, payload, **kwd ):
-        """
-        POST /api/roles
-        Creates a new role.
-        """
-        if not trans.user_is_admin():
-            trans.response.status = 403
-            return "You are not authorized to create a new role."
-        name = payload.get( 'name', None )
-        description = payload.get( 'description', None )
-        if not name or not description:
-            trans.response.status = 400
-            return "Enter a valid name and a description"
-        if trans.sa_session.query( trans.app.model.Role ).filter( trans.app.model.Role.table.c.name==name ).first():
-            trans.response.status = 400
-            return "A role with that name already exists"
-        
-        role_type = trans.app.model.Role.types.ADMIN #TODO: allow non-admins to create roles
-        
-        role = trans.app.model.Role( name=name, description=description, type=role_type )
-        trans.sa_session.add( role )
-        user_ids = payload.get( 'user_ids', [] )
-        users = [ trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( i ) ) for i in user_ids ]
-        group_ids = payload.get( 'group_ids', [] )
-        groups = [ trans.sa_session.query( trans.model.Group ).get( trans.security.decode_id( i ) ) for i in group_ids ]            
-        # Create the UserRoleAssociations
-        for user in users:
-            trans.app.security_agent.associate_user_role( user, role ) 
-        # Create the GroupRoleAssociations
-        for group in groups: