diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 7785144f860..69292cc8f92 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -1388,6 +1388,12 @@ class Tool( object, Dictifiable ): return section_id, section_name return None, None + def allow_user_access( self, user ): + """ + :returns: bool -- Whether the user is allowed to access the tool. + """ + return True + def parse( self, root, guid=None ): """ Read tool configuration from the element `root` and fill in `self`. @@ -3392,6 +3398,7 @@ class DataManagerTool( OutputParameterJSONTool ): self.data_manager_id = self.id def exec_after_process( self, app, inp_data, out_data, param_dict, job=None, **kwds ): + assert self.allow_user_access( job.user ), "You must be an admin to access this tool." #run original exec_after_process super( DataManagerTool, self ).exec_after_process( app, inp_data, out_data, param_dict, job=job, **kwds ) #process results of tool @@ -3415,6 +3422,7 @@ class DataManagerTool( OutputParameterJSONTool ): return history user = trans.user assert user, 'You must be logged in to use this tool.' + assert self.allow_user_access( user ), "You must be an admin to access this tool." history = user.data_manager_histories if not history: #create @@ -3434,6 +3442,17 @@ class DataManagerTool( OutputParameterJSONTool ): history = None return history + def allow_user_access( self, user ): + """ + :returns: bool -- Whether the user is allowed to access the tool. + Data Manager tools are only accessible to admins. + """ + if super( DataManagerTool, self ).allow_user_access( user ) and self.app.config.is_admin_user( user ): + return True + if user: + user = user.id + log.debug( "User (%s) attempted to access a data manager tool (%s), but is not an admin.", user, self.id ) + return False # Populate tool_type to ToolClass mappings tool_types = {} diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index e15a76cab79..8fab8964a90 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -155,6 +155,7 @@ class DefaultToolAction( object ): submitting the job to the job queue. If history is not specified, use trans.history as destination for tool's output datasets. """ + assert tool.allow_user_access( trans.user ), "User (%s) is not allowed to access this tool." % ( trans.user ) # Set history. if not history: history = tool.get_default_history_by_trans( trans, create=True ) diff --git a/lib/galaxy/webapps/galaxy/api/tools.py b/lib/galaxy/webapps/galaxy/api/tools.py index 2d2fc535323..4b48a4bd390 100644 --- a/lib/galaxy/webapps/galaxy/api/tools.py +++ b/lib/galaxy/webapps/galaxy/api/tools.py @@ -63,7 +63,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin, UsesHistoryMix """ io_details = util.string_as_bool( kwd.get( 'io_details', False ) ) link_details = util.string_as_bool( kwd.get( 'link_details', False ) ) - tool = self._get_tool( id ) + tool = self._get_tool( id, user=trans.user ) return tool.to_dict( trans, io_details=io_details, link_details=link_details ) @_future_expose_api_anonymous @@ -89,7 +89,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin, UsesHistoryMix @_future_expose_api_anonymous def citations( self, trans, id, **kwds ): - tool = self._get_tool( id ) + tool = self._get_tool( id, user=trans.user ) rval = [] for citation in tool.citations: rval.append( citation.to_dict( 'bibtex' ) ) @@ -122,7 +122,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin, UsesHistoryMix # Get tool. tool = trans.app.toolbox.get_tool( payload[ 'tool_id' ] ) if 'tool_id' in payload else None - if not tool: + if not tool or not tool.allow_user_access( trans.user ): trans.response.status = 404 return { "message": { "type": "error", "text" : trans.app.model.Dataset.conversion_messages.NO_TOOL } } @@ -212,10 +212,10 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin, UsesHistoryMix # # -- Helper methods -- # - def _get_tool( self, id ): + def _get_tool( self, id, user=None ): id = urllib.unquote_plus( id ) tool = self.app.toolbox.get_tool( id ) - if not tool: + if not tool or not tool.allow_user_access( user ): raise exceptions.ObjectNotFound("Could not find tool with id '%s'" % id) return tool @@ -281,7 +281,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin, UsesHistoryMix # original_job = self.get_hda_job( original_dataset ) tool = trans.app.toolbox.get_tool( original_job.tool_id ) - if not tool: + if not tool or not tool.allow_user_access( trans.user ): return trans.app.model.Dataset.conversion_messages.NO_TOOL tool_params = dict( [ ( p.name, p.value ) for p in original_job.parameters ] ) diff --git a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py index c2dd91e43e6..c453bbf6d87 100644 --- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py +++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py @@ -65,7 +65,7 @@ class ToolRunner( BaseUIController ): get_loaded_tools_by_lineage=False, set_selected=refreshed_on_change ) # No tool matching the tool id, display an error (shouldn't happen) - if not tool: + if not tool or not tool.allow_user_access( trans.user ): log.error( "index called with tool id '%s' but no such tool exists", tool_id ) trans.log_event( "Tool id '%s' does not exist" % tool_id ) trans.response.status = 404 @@ -191,6 +191,8 @@ class ToolRunner( BaseUIController ): # This is expected so not an exception. tool_id_version_message = '' error( "This dataset was created by an obsolete tool (%s). Can't re-run." % tool_id ) + if not tool.allow_user_access( trans.user ): + error( "The requested tool is unknown." ) # Can't rerun upload, external data sources, et cetera. Workflow compatible will proxy this for now if not tool.is_workflow_compatible: error( "The '%s' tool does not currently support rerunning." % tool.name )