root/galaxy-central/lib/galaxy/web/api/contents.py @ 2

リビジョン 2, 7.9 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
1"""
2API operations on the contents of a library.
3"""
4import logging, os, string, shutil, urllib, re, socket
5from cgi import escape, FieldStorage
6from galaxy import util, datatypes, jobs, web, util
7from galaxy.web.base.controller import *
8from galaxy.util.sanitize_html import sanitize_html
9from galaxy.model.orm import *
10
11log = logging.getLogger( __name__ )
12
13class ContentsController( BaseController ):
14   
15    @web.expose_api
16    def index( self, trans, library_id, **kwd ):
17        """
18        GET /api/libraries/{encoded_library_id}/contents
19        Displays a collection (list) of library contents (files and folders).
20        """
21        rval = []
22        current_user_roles = trans.get_current_user_roles()
23        def traverse( folder ):
24            admin = trans.user_is_admin()
25            rval = []
26            for subfolder in folder.active_folders:
27                if not admin:
28                    can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder )
29                if (admin or can_access) and not subfolder.deleted:
30                    subfolder.api_path = folder.api_path + '/' + subfolder.name
31                    subfolder.api_type = 'folder'
32                    rval.append( subfolder )
33                    rval.extend( traverse( subfolder ) )
34            for ld in folder.datasets:
35                if not admin:
36                    can_access = trans.app.security_agent.can_access_dataset( current_user_roles, ld.library_dataset_dataset_association.dataset )
37                if (admin or can_access) and not ld.deleted:
38                    ld.api_path = folder.api_path + '/' + ld.name
39                    ld.api_type = 'file'
40                    rval.append( ld )
41            return rval
42        try:
43            decoded_library_id = trans.security.decode_id( library_id )
44        except TypeError:
45            trans.response.status = 400
46            return "Malformed library id ( %s ) specified, unable to decode." % str( library_id )
47        try:
48            library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
49        except:
50            library = None
51        if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( current_user_roles, library ) ):
52            trans.response.status = 400
53            return "Invalid library id ( %s ) specified." % str( library_id )
54        encoded_id = trans.security.encode_id( 'folder.%s' % library.root_folder.id )
55        rval.append( dict( id = encoded_id,
56                           type = 'folder',
57                           name = '/',
58                           url = url_for( 'content', library_id=library_id, id=encoded_id ) ) )
59        library.root_folder.api_path = ''
60        for content in traverse( library.root_folder ):
61            encoded_id = trans.security.encode_id( '%s.%s' % ( content.api_type, content.id ) )
62            rval.append( dict( id = encoded_id,
63                               type = content.api_type,
64                               name = content.api_path,
65                               url = url_for( 'content', library_id=library_id, id=encoded_id, ) ) )
66        return rval
67
68    @web.expose_api
69    def show( self, trans, id, library_id, **kwd ):
70        """
71        GET /api/libraries/{encoded_library_id}/contents/{encoded_content_type_and_id}
72        Displays information about a library content (file or folder).
73        """
74        content_id = id
75        try:
76            decoded_type_and_id = trans.security.decode_string_id( content_id )
77            content_type, decoded_content_id = decoded_type_and_id.split( '.' )
78        except:
79            trans.response.status = 400
80            return "Malformed content id ( %s ) specified, unable to decode." % str( content_id )
81        if content_type == 'folder':
82            model_class = trans.app.model.LibraryFolder
83        elif content_type == 'file':
84            model_class = trans.app.model.LibraryDataset
85        else:
86            trans.response.status = 400
87            return "Invalid type ( %s ) specified." % str( content_type )
88        try:
89            content = trans.sa_session.query( model_class ).get( decoded_content_id )
90        except:
91            content = None
92        if not content or ( not trans.user_is_admin() and not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), content, trans.user ) ):
93            trans.response.status = 400
94            return "Invalid %s id ( %s ) specified." % ( content_type, str( content_id ) )
95        return content.get_api_value( view='element' )
96
97    @web.expose_api
98    def create( self, trans, library_id, payload, **kwd ):
99        """
100        POST /api/libraries/{encoded_library_id}/contents
101        Creates a new library content item (file or folder).
102        """
103        create_type = None
104        if 'create_type' not in payload:
105            trans.response.status = 400
106            return "Missing required 'create_type' parameter.  Please consult the API documentation for help."
107        else:
108            create_type = payload.pop( 'create_type' )
109        if create_type not in ( 'file', 'folder' ):
110            trans.response.status = 400
111            return "Invalid value for 'create_type' parameter ( %s ) specified.  Please consult the API documentation for help." % create_type
112        try:
113            content_id = str( payload.pop( 'folder_id' ) )
114            decoded_type_and_id = trans.security.decode_string_id( content_id )
115            parent_type, decoded_parent_id = decoded_type_and_id.split( '.' )
116            assert parent_type in ( 'folder', 'file' )
117        except:
118            trans.response.status = 400
119            return "Malformed parent id ( %s ) specified, unable to decode." % content_id
120        # "content" can be either a folder or a file, but the parent of new contents can only be folders.
121        if parent_type == 'file':
122            trans.response.status = 400
123            try:
124                # With admins or people who can access the dataset provided as the parent, be descriptive.
125                dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( decoded_parent_id ).library_dataset_dataset_association.dataset
126                assert trans.user_is_admin() or trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), dataset )
127                return "The parent id ( %s ) points to a file, not a folder." % content_id
128            except:
129                # If you can't access the parent we don't want to reveal its existence.
130                return "Invalid parent folder id ( %s ) specified." % content_id
131        # The rest of the security happens in the library_common controller.
132        folder_id = trans.security.encode_id( decoded_parent_id )
133        # Now create the desired content object, either file or folder.
134        if create_type == 'file':
135            status, output = trans.webapp.controllers['library_common'].upload_library_dataset( trans, 'api', library_id, folder_id, **payload )
136        elif create_type == 'folder':
137            status, output = trans.webapp.controllers['library_common'].create_folder( trans, 'api', folder_id, library_id, **payload )
138        if status != 200:
139            trans.response.status = status
140            # We don't want to reveal the encoded folder_id since it's invalid
141            # in the API context.  Instead, return the content_id originally
142            # supplied by the client.
143            output = output.replace( folder_id, content_id )
144            return output
145        else:
146            rval = []
147            for k, v in output.items():
148                if type( v ) == trans.app.model.LibraryDatasetDatasetAssociation:
149                    v = v.library_dataset
150                encoded_id = trans.security.encode_id( create_type + '.' + str( v.id ) )
151                rval.append( dict( id = encoded_id,
152                                   name = v.name,
153                                   url = url_for( 'content', library_id=library_id, id=encoded_id ) ) )
154            return rval
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。