root/galaxy-central/lib/galaxy/webapps/community/security/__init__.py @ 2

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

import galaxy-central

行番号 
1"""
2Galaxy Tool Shed Security
3"""
4import logging, socket, operator
5from datetime import datetime, timedelta
6from galaxy.util.bunch import Bunch
7from galaxy.util import listify
8from galaxy.model.orm import *
9from galaxy.webapps.community.controllers.common import get_versions
10
11log = logging.getLogger(__name__)
12
13class Action( object ):
14    def __init__( self, action, description, model ):
15        self.action = action
16        self.description = description
17        self.model = model
18
19class RBACAgent:
20    """Class that handles galaxy community space security"""
21    permitted_actions = Bunch()
22    def associate_components( self, **kwd ):
23        raise 'No valid method of associating provided components: %s' % kwd
24    def associate_user_role( self, user, role ):
25        raise 'No valid method of associating a user with a role'
26    def convert_permitted_action_strings( self, permitted_action_strings ):
27        """
28        When getting permitted actions from an untrusted source like a
29        form, ensure that they match our actual permitted actions.
30        """
31        return filter( lambda x: x is not None, [ self.permitted_actions.get( action_string ) for action_string in permitted_action_strings ] )
32    def create_private_user_role( self, user ):
33        raise "Unimplemented Method"
34    def get_action( self, name, default=None ):
35        """Get a permitted action by its dict key or action name"""
36        for k, v in self.permitted_actions.items():
37            if k == name or v.action == name:
38                return v
39        return default
40    def get_actions( self ):
41        """Get all permitted actions as a list of Action objects"""
42        return self.permitted_actions.__dict__.values()
43    def get_item_actions( self, action, item ):
44        raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
45    def get_private_user_role( self, user ):
46        raise "Unimplemented Method"
47
48class CommunityRBACAgent( RBACAgent ):
49    def __init__( self, model, permitted_actions=None ):
50        self.model = model
51        if permitted_actions:
52            self.permitted_actions = permitted_actions
53    @property
54    def sa_session( self ):
55        """Returns a SQLAlchemy session"""
56        return self.model.context
57    def allow_action( self, roles, action, item ):
58        """
59        Method for checking a permission for the current user ( based on roles ) to perform a
60        specific action on an item
61        """
62        item_actions = self.get_item_actions( action, item )
63        if not item_actions:
64            return action.model == 'restrict'
65        ret_val = False
66        for item_action in item_actions:
67            if item_action.role in roles:
68                ret_val = True
69                break
70        return ret_val
71    def associate_components( self, **kwd ):
72        if 'user' in kwd:
73            if 'group' in kwd:
74                return self.associate_user_group( kwd['user'], kwd['group'] )
75            elif 'role' in kwd:
76                return self.associate_user_role( kwd['user'], kwd['role'] )
77        elif 'role' in kwd:
78            if 'group' in kwd:
79                return self.associate_group_role( kwd['group'], kwd['role'] )
80        elif 'tool' in kwd:
81            return self.associate_tool_category( kwd['tool'], kwd['category'] )
82        raise 'No valid method of associating provided components: %s' % kwd
83    def associate_group_role( self, group, role ):
84        assoc = self.model.GroupRoleAssociation( group, role )
85        self.sa_session.add( assoc )
86        self.sa_session.flush()
87        return assoc
88    def associate_user_group( self, user, group ):
89        assoc = self.model.UserGroupAssociation( user, group )
90        self.sa_session.add( assoc )
91        self.sa_session.flush()
92        return assoc
93    def associate_user_role( self, user, role ):
94        assoc = self.model.UserRoleAssociation( user, role )
95        self.sa_session.add( assoc )
96        self.sa_session.flush()
97        return assoc
98    def associate_tool_category( self, tool, category ):
99        assoc = self.model.ToolCategoryAssociation( tool, category )
100        self.sa_session.add( assoc )
101        self.sa_session.flush()
102        return assoc
103    def create_private_user_role( self, user ):
104        # Create private role
105        role = self.model.Role( name=user.email, description='Private Role for ' + user.email, type=self.model.Role.types.PRIVATE )
106        self.sa_session.add( role )
107        self.sa_session.flush()
108        # Add user to role
109        self.associate_components( role=role, user=user )
110        return role
111    def get_item_actions( self, action, item ):
112        # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
113        return [ permission for permission in item.actions if permission.action == action.action ]
114    def get_private_user_role( self, user, auto_create=False ):
115        role = self.sa_session.query( self.model.Role ) \
116                              .filter( and_( self.model.Role.table.c.name == user.email,
117                                             self.model.Role.table.c.type == self.model.Role.types.PRIVATE ) ) \
118                              .first()
119        if not role:
120            if auto_create:
121                return self.create_private_user_role( user )
122            else:
123                return None
124        return role
125    def set_entity_group_associations( self, groups=[], users=[], roles=[], delete_existing_assocs=True ):
126        for group in groups:
127            if delete_existing_assocs:
128                for a in group.roles + group.users:
129                    self.sa_session.delete( a )
130                    self.sa_session.flush()
131            for role in roles:
132                self.associate_components( group=group, role=role )
133            for user in users:
134                self.associate_components( group=group, user=user )
135    def set_entity_role_associations( self, roles=[], users=[], groups=[], delete_existing_assocs=True ):
136        for role in roles:
137            if delete_existing_assocs:
138                for a in role.users + role.groups:
139                    self.sa_session.delete( a )
140                    self.sa_session.flush()
141            for user in users:
142                self.associate_components( user=user, role=role )
143            for group in groups:
144                self.associate_components( group=group, role=role )
145    def set_entity_user_associations( self, users=[], roles=[], groups=[], delete_existing_assocs=True ):
146        for user in users:
147            if delete_existing_assocs:
148                for a in user.non_private_roles + user.groups:
149                    self.sa_session.delete( a )
150                    self.sa_session.flush()
151            self.sa_session.refresh( user )
152            for role in roles:
153                # Make sure we are not creating an additional association with a PRIVATE role
154                if role not in user.roles:
155                    self.associate_components( user=user, role=role )
156            for group in groups:
157                self.associate_components( user=user, group=group )
158    def set_entity_category_associations( self, tools=[], categories=[], delete_existing_assocs=True ):
159        for tool in tools:
160            if delete_existing_assocs:
161                for a in tool.categories:
162                    self.sa_session.delete( a )
163                    self.sa_session.flush()
164            self.sa_session.refresh( tool )
165            for category in categories:
166                self.associate_components( tool=tool, category=category )
167    def can_rate( self, user, user_is_admin, cntrller, item ):
168        # The current user can rate and review the item if they are an admin or if
169        # they did not upload the item and the item is approved or archived.
170        if user and user_is_admin and cntrller == 'admin':
171            return True
172        if cntrller in [ 'tool' ] and ( item.is_approved or item.is_archived ) and user != item.user:
173            return True
174        return False
175    def can_approve_or_reject( self, user, user_is_admin, cntrller, item ):
176        # The current user can approve or reject the item if the user
177        # is an admin, and the item's state is WAITING.
178        return user and user_is_admin and cntrller=='admin' and item.is_waiting
179    def can_delete( self, user, user_is_admin, cntrller, item ):
180        # The current user can delete the item if they are an admin or if they uploaded the
181        # item and in either case the item's state is not DELETED.
182        if user and user_is_admin and cntrller == 'admin':
183            can_delete = not item.is_deleted
184        elif cntrller in [ 'tool' ]:
185            can_delete = user==item.user and not item.is_deleted
186        else:
187            can_delete = False
188        return can_delete
189    def can_download( self, user, user_is_admin, cntrller, item ):
190        # The current user can download the item if they are an admin or if the
191        # item's state is not one of: NEW, WAITING.
192        if user and user_is_admin and cntrller == 'admin':
193            return True
194        elif cntrller in [ 'tool' ]:
195            can_download = not( item.is_new or item.is_waiting )
196        else:
197            can_download = False
198        return can_download
199    def can_edit( self, user, user_is_admin, cntrller, item ):
200        # The current user can edit the item if they are an admin or if they uploaded the item
201        # and the item's state is one of: NEW, REJECTED.
202        if user and user_is_admin and cntrller == 'admin':
203            return True
204        if cntrller in [ 'tool' ]:
205            return user and user==item.user and ( item.is_new or item.is_rejected )
206        return False
207    def can_purge( self, user, user_is_admin, cntrller ):
208        # The current user can purge the item if they are an admin.
209        return user and user_is_admin and cntrller == 'admin'
210    def can_upload_new_version( self, user, item ):
211        # The current user can upload a new version as long as the item's state is not NEW or WAITING.
212        if not user:
213            return False
214        versions = get_versions( item )
215        state_ok = True
216        for version in versions:
217            if version.is_new or version.is_waiting:
218                state_ok = False
219                break
220        return state_ok
221    def can_view( self, user, user_is_admin, cntrller, item ):
222        # The current user can view the item if they are an admin or if they uploaded the item
223        # or if the item's state is APPROVED.
224        if user and user_is_admin and cntrller == 'admin':
225            return True
226        if cntrller in [ 'tool' ] and item.is_approved:
227            return True
228        return user and user==item.user
229    def get_all_action_permissions( self, user, user_is_admin, cntrller, item ):
230        """Get all permitted actions on item for the current user"""
231        can_edit = self.can_edit( cntrller, user, user_is_admin, item )
232        can_view = self.can_view( cntrller, user, user_is_admin, item )
233        can_upload_new_version = self.can_upload_new_version( user, item )
234        visible_versions = self.get_visible_versions( user, user_is_admin, cntrller, item )
235        can_approve_or_reject = self.can_approve_or_reject( user, user_is_admin, cntrller, item )
236        can_delete = self.can_delete( user, user_is_admin, cntrller, item )
237        return can_edit, can_view, can_upload_new_version, can_delete, visible_versions, can_approve_or_reject
238    def get_visible_versions( self, user, user_is_admin, cntrller, item ):
239        # All previous versions of item can be displayed if the current user is an admin
240        # or they uploaded item.  Otherwise, only versions whose state is APPROVED or
241        # ARCHIVED will be displayed.
242        if user and user_is_admin and cntrller == 'admin':
243            visible_versions = get_versions( item )
244        elif cntrller in [ 'tool' ]:
245            visible_versions = []
246            for version in get_versions( item ):
247                if version.is_approved or version.is_archived or version.user == user:
248                    visible_versions.append( version )
249        else:
250           visible_versions = []
251        return visible_versions
252
253def get_permitted_actions( filter=None ):
254    '''Utility method to return a subset of RBACAgent's permitted actions'''
255    if filter is None:
256        return RBACAgent.permitted_actions
257    tmp_bunch = Bunch()
258    [ tmp_bunch.__dict__.__setitem__(k, v) for k, v in RBACAgent.permitted_actions.items() if k.startswith( filter ) ]
259    return tmp_bunch
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。