Exemplo n.º 1
0
         dictify_dataset_collection_instance(
             dataset_collection_instance,
             security=trans.security,
             parent=parent)
     ]
 if status != 200:
     trans.response.status = status
     return output
 else:
     rval = []
     for k, v in output.items():
         if ex_meta_payload is not None:
             """
             If there is extended metadata, store it, attach it to the dataset, and index it
             """
             ex_meta = ExtendedMetadata(ex_meta_payload)
             trans.sa_session.add(ex_meta)
             v.extended_metadata = ex_meta
             trans.sa_session.add(v)
             trans.sa_session.flush()
             for path, value in self._scan_json_block(ex_meta_payload):
                 meta_i = ExtendedMetadataIndex(ex_meta, path, value)
                 trans.sa_session.add(meta_i)
             trans.sa_session.flush()
         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,
Exemplo n.º 2
0
    def create(self, trans, library_id, payload, **kwd):
        """
        create( self, trans, library_id, payload, **kwd )
        * POST /api/libraries/{library_id}/contents:
            create a new library file or folder

        To copy an HDA into a library send ``create_type`` of 'file' and
        the HDA's encoded id in ``from_hda_id`` (and optionally ``ldda_message``).

        To copy an HDCA into a library send ``create_type`` of 'file' and
        the HDCA's encoded id in ``from_hdca_id`` (and optionally ``ldda_message``).

        :type   library_id: str
        :param  library_id: the encoded id of the library where to create the new item
        :type   payload:    dict
        :param  payload:    dictionary structure containing:

            * folder_id:    the encoded id of the parent folder of the new item
            * create_type:  the type of item to create ('file', 'folder' or 'collection')
            * from_hda_id:  (optional, only if create_type is 'file') the
                encoded id of an accessible HDA to copy into the library
            * ldda_message: (optional) the new message attribute of the LDDA created
            * extended_metadata: (optional) sub-dictionary containing any extended
                metadata to associate with the item
            * upload_option: (optional) one of 'upload_file' (default), 'upload_directory' or 'upload_paths'
            * server_dir: (optional, only if upload_option is
                'upload_directory') relative path of the subdirectory of Galaxy
                ``library_import_dir`` to upload. All and only the files (i.e.
                no subdirectories) contained in the specified directory will be
                uploaded.
            * filesystem_paths: (optional, only if upload_option is
                'upload_paths' and the user is an admin) file paths on the
                Galaxy server to upload to the library, one file per line
            * link_data_only: (optional, only when upload_option is
                'upload_directory' or 'upload_paths') either 'copy_files'
                (default) or 'link_to_files'. Setting to 'link_to_files'
                symlinks instead of copying the files
            * name: (optional, only if create_type is 'folder') name of the
                folder to create
            * description: (optional, only if create_type is 'folder')
                description of the folder to create
            * tag_using_filename: (optional)
                create tags on datasets using the file's original name

        :returns:   a dictionary describing the new item unless ``from_hdca_id`` is supplied,
                    in that case a list of such dictionaries is returned.
        :rtype:     object
        """
        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', 'collection'):
            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 required 'folder_id' parameter."
        else:
            folder_id = payload.pop('folder_id')
            class_name, folder_id = self.__decode_library_content_id(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 as e:
            return str(e)
        # The rest of the security happens in the library_common controller.
        real_folder_id = trans.security.encode_id(parent.id)

        # are we copying an HDA to the library folder?
        #   we'll need the id and any message to attach, then branch to that private function
        from_hda_id, from_hdca_id, ldda_message = (payload.pop(
            'from_hda_id',
            None), payload.pop('from_hdca_id',
                               None), payload.pop('ldda_message', ''))
        if create_type == 'file':
            if from_hda_id:
                return self._copy_hda_to_library_folder(
                    trans, self.hda_manager, self.decode_id(from_hda_id),
                    real_folder_id, ldda_message)
            if from_hdca_id:
                return self._copy_hdca_to_library_folder(
                    trans, self.hda_manager, self.decode_id(from_hdca_id),
                    real_folder_id, ldda_message)

        # check for extended metadata, store it and pop it out of the param
        # otherwise sanitize_param will have a fit
        ex_meta_payload = payload.pop('extended_metadata', None)

        # 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)
        elif create_type == 'collection':
            # Not delegating to library_common, so need to check access to parent
            # folder here.
            self.check_user_can_add_to_library_item(trans,
                                                    parent,
                                                    check_accessible=True)
            create_params = api_payload_to_create_params(payload)
            create_params['parent'] = parent
            service = trans.app.dataset_collections_service
            dataset_collection_instance = service.create(**create_params)
            return [
                dictify_dataset_collection_instance(
                    dataset_collection_instance,
                    security=trans.security,
                    parent=parent)
            ]
        if status != 200:
            trans.response.status = status
            return output
        else:
            rval = []
            for v in output.values():
                if ex_meta_payload is not None:
                    # If there is extended metadata, store it, attach it to the dataset, and index it
                    ex_meta = ExtendedMetadata(ex_meta_payload)
                    trans.sa_session.add(ex_meta)
                    v.extended_metadata = ex_meta
                    trans.sa_session.add(v)
                    trans.sa_session.flush()
                    for path, value in self._scan_json_block(ex_meta_payload):
                        meta_i = ExtendedMetadataIndex(ex_meta, path, value)
                        trans.sa_session.add(meta_i)
                    trans.sa_session.flush()
                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
Exemplo n.º 3
0
class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):

    @web.expose_api
    # TODO: Add parameter to only get top level of datasets/subfolders.
    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:
                    log.debug( "type(folder): %s" % type( folder ) )
                    log.debug( "type(api_path): %s; folder.api_path: %s" % ( type(folder.api_path), folder.api_path ) )
                    #log.debug( "attributes of folder: %s" % str(dir(folder)) )
                    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 )
        log.debug( "Root folder type: %s" % type( library.root_folder ) )
        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 ) ) )
        log.debug( "Root folder attributes: %s" % str(dir(library.root_folder)) )
        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 )

        #check for extended metadata, store it and pop it out of the param 
        #otherwise sanitize_param will have a fit
        ex_meta_payload = None
        if 'extended_metadata' in payload:
            ex_meta_payload = payload.pop('extended_metadata')

        # 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 ex_meta_payload is not None:
                    """
                    If there is extended metadata, store it, attach it to the dataset, and index it
                    """
                    ex_meta = ExtendedMetadata(ex_meta_payload)
                    trans.sa_session.add( ex_meta )
                    v.extended_metadata = ex_meta
                    trans.sa_session.add(v)
                    trans.sa_session.flush()
                    for path, value in self._scan_json_block(ex_meta_payload):
                        meta_i = ExtendedMetadataIndex(ex_meta, path, value)
                        trans.sa_session.add(meta_i)
                    trans.sa_session.flush()
                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