commit/galaxy-central: 6 new changesets
6 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/d816d6602e18/ Changeset: d816d6602e18 Branch: custom-toolbox2 User: BjoernGruening Date: 2013-06-13 22:46:22 Summary: Implement the ability to change the tool-panel as user prederence. Affected #: 10 files diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -6,8 +6,9 @@ import logging, logging.config import ConfigParser from datetime import timedelta -from galaxy.util import string_as_bool, listify, parse_xml - +from galaxy.util import string_as_bool +from galaxy.util import listify +from galaxy.util import parse_xml from galaxy import eggs import pkg_resources @@ -64,9 +65,14 @@ tcf = kwargs[ 'tool_config_files' ] else: tcf = 'tool_conf.xml' - self.tool_filters = listify( kwargs.get( "tool_filters", [] ) ) - self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ) ) - self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ) ) + self.tool_filters = listify( kwargs.get( "tool_filters", [] ), do_strip=True ) + self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ), do_strip=True ) + self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ), do_strip=True ) + + self.user_tool_filters = listify( kwargs.get( "user_tool_filters", [] ), do_strip=True ) + self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True ) + self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True ) + self.tool_configs = [ resolve_path( p, self.root ) for p in listify( tcf ) ] self.shed_tool_data_path = kwargs.get( "shed_tool_data_path", None ) if self.shed_tool_data_path: @@ -459,3 +465,4 @@ sentry_handler = SentryHandler( config.sentry_dsn ) sentry_handler.setLevel( logging.WARN ) root.addHandler( sentry_handler ) + diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -3267,7 +3267,7 @@ #end of Data Manager Classes class UserPreference ( object ): - def __init__( self, name=None, value=None ): + def __init__( self, name=None, value=None): self.name = name self.value = value diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -3426,3 +3426,4 @@ class InterruptedUpload( Exception ): pass + diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/filters/__init__.py --- a/lib/galaxy/tools/filters/__init__.py +++ b/lib/galaxy/tools/filters/__init__.py @@ -1,4 +1,5 @@ - +from galaxy.util import listify +from copy import deepcopy class FilterFactory( object ): """ @@ -15,17 +16,29 @@ self.default_filters = dict( tool=[ _not_hidden ], section=[], label=[] ) # Add dynamic filters to these default filters. config = toolbox.app.config - self.__init_filters( "tool", config.tool_filters ) - self.__init_filters( "section", config.tool_section_filters ) - self.__init_filters( "label", config.tool_label_filters ) + self.__init_filters( "tool", config.tool_filters, self.default_filters ) + self.__init_filters( "section", config.tool_section_filters, self.default_filters ) + self.__init_filters( "label", config.tool_label_filters, self.default_filters ) def build_filters( self, trans, **kwds ): """ Build list of filters to check tools against given current context. """ - filters = self.default_filters.copy() - - if not trans.user: + filters = deepcopy( self.default_filters ) + if trans.user: + for name, value in trans.user.preferences.items(): + if value.strip(): + user_filters = listify( value, do_strip=True ) + category = '' + if name == 'toolbox_tool_filters': + category = "tool" + elif name == 'toolbox_section_filters': + category = "section" + elif name == 'toolbox_label_filters': + category = "label" + if category: + self.__init_filters( category, user_filters, filters ) + else: filters[ "tool" ].append( _requires_login ) if kwds.get( "trackster", False ): @@ -33,10 +46,11 @@ return filters - def __init_filters( self, key, filters ): + def __init_filters( self, key, filters, toolbox_filters ): for filter in filters: filter_function = self.__build_filter_function( filter ) - self.default_filters[ key ].append( filter_function ) + toolbox_filters[ key ].append( filter_function ) + return toolbox_filters def __build_filter_function( self, filter_name ): """Obtain python function (importing a submodule if needed) diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/tools/filters/examples.py --- /dev/null +++ b/lib/galaxy/tools/filters/examples.py @@ -0,0 +1,115 @@ +import logging +log = logging.getLogger( __name__ ) + + +def restrict_encode( content, tool ): + """ + Disable the random interval ENCODE tool + + This tool filter will disable all the ENCODE tool when enabled. + """ + if tool.id == 'random_intervals1': + return False + return True + + +def restrict_text( content, section ): + """ + Disable Text sections + + This tool filter will disable all Tools groups under a 'Text' section when enabled. + """ + if section.name.find('Text') != -1: + return False + return True + + +def restrict_upload_to_admins( context, tool ): + """ + Disable Upload tool for all non-admin users. + + This tool filter will hide the upload tool from all users except admin + users. + + This can be enabled by renaming this file to examples.py and adding + the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:restrict_upload_to_admins + """ + if tool.name == "Upload File": + return context.trans.user_is_admin() + return True + + +def disable_gatk( context, tool ): + """ + This tool filter will disable all gatk tools when enabled. + + This can be enabled by renaming this file to examples.py and adding the following to the + ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:disable_gatk + """ + return not any( [ requirement.name == "gatk" for requirement in tool.requirements ] ) + + +def explicit_user_mapping( context, section ): + """ + This tool section filter uses an explicit mapping to describe what users can view + which tool sections. Anonymous users will only be able to view the "Get Data" + tool section (with id getext). This can be enabled by renaming this file to + examples.py and adding the following to the ``app:main`` section of + ``universe_wsgi.ini``: + + tool_section_filters = examples:explicit_user_mapping + """ + users_sections = { + None: [ "getext" ], + "bob@example.com": [ "getext", "textutil", "filter" ], + "mary@example.com": [ "getext", "textutil", "filter", "ngs" ], + } + user = context.trans.user + email = user and user.email + valid_sections = users_sections.get( email, [] ) + return section.id in valid_sections + + +DEVELOPERS = [ "mary@example.com" ] + + +def restrict_development_tools( context, tool ): + """ + This tool filter will disable all tools with the string alpha appearing in + the version for all users except those explicitly appearing in the DEVELOPERS list + defined above. This can be enabled by renaming this file to examples.py and + adding the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:restrict_development_tools + """ + version = tool.version + user = context.trans.user + email = user and user.email + return "alpha" not in version or email in DEVELOPERS + + +def per_host_tool_sections( context, section ): + """ + This tool section filter results in different sections being display based on + the URL the user is making the request to. This could allow a single Galaxy instance + to seem like several different instances hosting different tools based on the URL used + to access the Galxy. This can be enabled by renaming this file to examples.py and adding + the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_section_filters = examples:per_host_tool_sections + """ + host = context.trans.request.host + # Core tools used by all virtual hosts. + valid_sections = [ "getext", "textutil", "filter" ] + if "ngs.galaxy.example.com" in host: + valid_sections += [ "ngs" ] + elif "microarray.galaxy.example.com" in host: + valid_sections += [ "microarray" ] + elif "proteomics.galaxy.example.com" in host: + valid_sections += [ "proteomics" ] + return section.id in valid_sections + diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/util/__init__.py --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -496,7 +496,7 @@ else: return False -def listify( item ): +def listify( item, do_strip=False ): """ Make a single item a single item list, or return a list if passed a list. Passing a None returns an empty list. @@ -506,7 +506,10 @@ elif isinstance( item, list ): return item elif isinstance( item, basestring ) and item.count( ',' ): - return item.split( ',' ) + if do_strip: + return [token.strip() for token in item.split( ',' )] + else: + return item.split( ',' ) else: return [ item ] @@ -746,6 +749,32 @@ current_group, e ) ) +def docstring_trim(docstring): + """Trimming python doc strings. Taken from: http://www.python.org/dev/peps/pep-0257/""" + if not docstring: + return '' + # Convert tabs to spaces (following the normal Python rules) + # and split into a list of lines: + lines = docstring.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxint + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxint: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + # Return a single string: + return '\n'.join(trimmed) + def nice_size(size): """ Returns a readably formatted string with the size diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -9,14 +9,24 @@ import string import random from galaxy import web -from galaxy import util, model +from galaxy import util +from galaxy import model from galaxy.model.orm import and_ -from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname -from galaxy.util.json import from_json_string, to_json_string +from galaxy.security.validate_user_input import validate_email +from galaxy.security.validate_user_input import validate_publicname +from galaxy.security.validate_user_input import validate_password +from galaxy.security.validate_user_input import transform_publicname +from galaxy.util.json import from_json_string +from galaxy.util.json import to_json_string +from galaxy.util import listify +from galaxy.util import docstring_trim from galaxy.web import url_for -from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin -from galaxy.web.form_builder import CheckboxField, build_select_field +from galaxy.web.base.controller import BaseUIController +from galaxy.web.base.controller import UsesFormDefinitionsMixin +from galaxy.web.form_builder import CheckboxField +from galaxy.web.form_builder import build_select_field from galaxy.web.framework.helpers import time_ago, grids +from galaxy.web.framework.helpers import grids log = logging.getLogger( __name__ ) @@ -101,6 +111,7 @@ use_panels=use_panels, message=message, status='error' ) ) + @web.expose def openid_process( self, trans, **kwd ): '''Handle's response from OpenID Providers''' @@ -221,6 +232,7 @@ redirect=redirect, message=message, status=status ) ) + @web.expose def openid_associate( self, trans, cntrller='user', **kwd ): '''Associates a user with an OpenID log in''' @@ -359,6 +371,7 @@ user_type_form_definition=user_type_form_definition, widgets=widgets, openids=openids ) + @web.expose @web.require_login( 'manage OpenIDs' ) def openid_disassociate( self, trans, **kwd ): @@ -465,6 +478,7 @@ openid_providers=trans.app.openid_providers, form_input_auto_focus=True, active_view="user" ) + def __validate_login( self, trans, **kwd ): message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) @@ -662,6 +676,7 @@ message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) ) success = True return ( message, status, user, success ) + def __get_user_type_form_definition( self, trans, user=None, **kwd ): params = util.Params( kwd ) if user and user.values: @@ -673,6 +688,7 @@ else: user_type_form_definition = None return user_type_form_definition + def __get_widgets( self, trans, user_type_form_definition, user=None, **kwd ): widgets = [] if user_type_form_definition: @@ -774,6 +790,7 @@ username=user.username, message=message, status=status ) + @web.expose def edit_info( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -882,6 +899,7 @@ action='manage_user_info', cntrller=cntrller, **kwd ) ) + @web.expose def reset_password( self, trans, email=None, **kwd ): if trans.app.config.smtp_server is None: @@ -929,6 +947,7 @@ return trans.fill_template( '/user/reset_password.mako', message=message, status=status ) + def __validate( self, trans, params, email, password, confirm, username ): # If coming from the tool shed webapp, we'll require a public user name if trans.webapp.name == 'tool_shed': @@ -950,6 +969,7 @@ if user_type_fd_id in [ 'none' ]: return "Select the user's type and information" return message + @web.expose def set_default_permissions( self, trans, cntrller, **kwd ): """Sets the user's default permissions for the new histories""" @@ -975,7 +995,128 @@ status=status ) else: # User not logged in, history group must be only public - return trans.show_error_message( "You must be logged in to change your default permitted actions." ) + return trans.show_error_message( "You must be logged in to change your default permitted actions." ) + + @web.expose + @web.require_login() + def toolbox_filters( self, trans, cntrller, **kwd ): + """ + Sets the user's default filters for the toolbox. + Toolbox filters are specified in universe_wsgi.ini. + The user can activate them and the choice is stored in user_preferences. + """ + + def get_filter_mapping( db_filters, config_filters ): + """ + Compare the allowed filters from the universe_wsgi.ini config file with the previously saved or default filters from the database. + We need that to toogle the checkboxes for the formular in the right way. + Furthermore we extract all information associated to a filter to display them in the formular. + """ + filters = list() + for filter_name in config_filters: + if ":" in filter_name: + # Should be a submodule of filters (e.g. examples:restrict_development_tools) + (module_name, function_name) = filter_name.rsplit(":", 1) + module_name = 'galaxy.tools.filters.%s' % module_name.strip() + module = __import__( module_name, globals(), fromlist=['temp_module'] ) + function = getattr( module, function_name.strip() ) + else: + # No module found it has to be explicitly imported. + module = __import__( 'galaxy.tools.filters', globals(), fromlist=['temp_module'] ) + function = getattr( globals(), filter_name.strip() ) + + doc_string = docstring_trim( function.__doc__ ) + split = doc_string.split('\n\n') + if split: + sdesc = split[0] + else: + log.error( 'No description specified in the __doc__ string for %s.' % filter_name ) + if len(split) > 1: + description = split[1] + else: + description = '' + + if filter_name in db_filters: + filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=True ) ) + else: + filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=False ) ) + return filters + + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + + user_id = params.get( 'user_id', False ) + if user_id: + user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) ) + else: + user = trans.user + + if user: + saved_user_tool_filters = list() + saved_user_section_filters = list() + saved_user_label_filters = list() + + for name, value in user.preferences.items(): + if name == 'toolbox_tool_filters': + saved_user_tool_filters = listify( value, do_strip=True ) + elif name == 'toolbox_section_filters': + saved_user_section_filters = listify( value, do_strip=True ) + elif name == 'toolbox_label_filters': + saved_user_label_filters = listify( value, do_strip=True ) + + tool_filters = get_filter_mapping( saved_user_tool_filters, trans.app.config.user_tool_filters ) + section_filters = get_filter_mapping( saved_user_section_filters, trans.app.config.user_section_filters ) + label_filters = get_filter_mapping( saved_user_label_filters, trans.app.config.user_label_filters ) + + return trans.fill_template( 'user/toolbox_filters.mako', + cntrller=cntrller, + message=message, + tool_filters=tool_filters, + section_filters=section_filters, + label_filters=label_filters, + user=user, + status=status ) + else: + # User not logged in, history group must be only public + return trans.show_error_message( "You must be logged in to change private toolbox filters." ) + + @web.expose + @web.require_login( "to change the private toolbox filters" ) + def edit_toolbox_filters( self, trans, cntrller, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + user_id = params.get( 'user_id', False ) + if not user_id: + # User must be logged in to create a new address + return trans.show_error_message( "You must be logged in to change the ToolBox filters." ) + + user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) ) + + if params.get( 'edit_toolbox_filter_button', False ): + tool_filters = list() + section_filters = list() + label_filters = list() + for name, state in params.flatten(): + if state == 'on': + if name.startswith('t_'): + tool_filters.append( name[2:] ) + elif name.startswith('l_'): + label_filters.append( name[2:] ) + elif name.startswith('s_'): + section_filters.append( name[2:] ) + user.preferences['toolbox_tool_filters'] = ','.join( tool_filters ) + user.preferences['toolbox_section_filters'] = ','.join( section_filters ) + user.preferences['toolbox_label_filters'] = ','.join( label_filters ) + + trans.sa_session.add( user ) + trans.sa_session.flush() + message = 'ToolBox filters has been updated.' + kwd = dict( message=message, status='done' ) + + # Display the ToolBox filters form with the current values filled in + return self.toolbox_filters( trans, cntrller, **kwd ) + @web.expose @web.require_login( "to get most recently used tool" ) @web.json_pretty @@ -998,7 +1139,8 @@ "minsizehint" : tool.uihints.get( 'minwidth', -1 ), "description" : tool.description } - return tool_info + return tool_info + @web.expose def manage_addresses(self, trans, **kwd): if trans.user: @@ -1020,6 +1162,7 @@ else: # User not logged in, history group must be only public return trans.show_error_message( "You must be logged in to change your default permitted actions." ) + @web.expose def new_address( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -1104,6 +1247,7 @@ phone=phone, message=message, status=status ) + @web.expose def edit_address( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -1118,7 +1262,7 @@ address_id = params.get( 'address_id', None ) if not address_id: return trans.show_error_message( "No address id received for editing." ) - address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) ) + address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) ) if params.get( 'edit_address_button', False ): short_desc = util.restore_text( params.get( 'short_desc', '' ) ) name = util.restore_text( params.get( 'name', '' ) ) @@ -1181,6 +1325,7 @@ address_obj=address_obj, message=message, status=status ) + @web.expose def delete_address( self, trans, cntrller, address_id=None, user_id=None ): try: @@ -1201,6 +1346,7 @@ user_id=user_id, message=message, status=status ) ) + @web.expose def undelete_address( self, trans, cntrller, address_id=None, user_id=None ): try: @@ -1220,6 +1366,7 @@ user_id=user_id, message=message, status=status ) ) + @web.expose def set_user_pref_async( self, trans, pref_name, pref_value ): """ Set a user preference asynchronously. If user is not logged in, do nothing. """ @@ -1232,7 +1379,7 @@ """ Log a user action asynchronously. If user is not logged in, do nothing. """ if trans.user: trans.log_action( trans.get_user(), action, context, params ) - + @web.expose @web.require_login() def dbkeys( self, trans, **kwds ): diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf templates/user/index.mako --- a/templates/user/index.mako +++ b/templates/user/index.mako @@ -13,6 +13,7 @@ <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li><li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li> + <li><a href="${h.url_for( controller='user', action='toolbox_filters', cntrller=cntrller )}">${_('Manage your ToolBox filters')}</a></li> %if trans.app.config.enable_openid: <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li> %endif diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf templates/user/toolbox_filters.mako --- /dev/null +++ b/templates/user/toolbox_filters.mako @@ -0,0 +1,91 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if message: + ${render_msg( message, status )} +%endif +</br> +</br> + +<ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a> + </li> +</ul> + +%if tool_filters or section_filters or label_filters: + <div class="toolForm"> + <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > + % if tool_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Tools</div> + <div class="toolFormBody"> + % for filter in tool_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="t_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="t_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + + % if section_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Sections</div> + <div class="toolFormBody"> + % for filter in section_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="s_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="s_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + + % if label_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Labels</div> + <div class="toolFormBody"> + % for filter in label_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="l_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="l_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + <div class="form-row"> + <input type="submit" name="edit_toolbox_filter_button" value="Save changes"> + </div> + </form> + </div> +%else: + ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )} +%endif diff -r 6f9e73ec3e99d43f14e3d735ecfe7b66ea38472a -r d816d6602e18fd8e04c5d141527ca77a3e39e6cf universe_wsgi.ini.sample --- a/universe_wsgi.ini.sample +++ b/universe_wsgi.ini.sample @@ -682,6 +682,18 @@ # if running many handlers. #cache_user_job_count = False +# ToolBox filtering +# Modules from lib/galaxy/tools/filters/ can be specified in the following lines. +# tool_* filters will be applied for all users and can not be changed by them. +# user_tool_* filters will be shown under user preferences and can be toogled +# on and off by runtime +#tool_filters +#tool_label_filters +#tool_section_filters +#user_tool_filters = examples:restrict_upload_to_admins, examples:restrict_encode +#user_tool_section_filters = examples:restrict_text +#user_tool_label_filters = examples:restrict_upload_to_admins, examples:restrict_encode + # ---- Galaxy Message Queue ------------------------------------------------- # Galaxy uses AMQ protocol to receive messages from external sources like https://bitbucket.org/galaxy/galaxy-central/commits/fb1b676f51b2/ Changeset: fb1b676f51b2 User: dannon Date: 2013-10-17 19:40:04 Summary: Merged custom-toolbox2 Affected #: 10 files diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/config.py --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -6,8 +6,9 @@ import logging, logging.config import ConfigParser from datetime import timedelta -from galaxy.util import string_as_bool, listify, parse_xml - +from galaxy.util import string_as_bool +from galaxy.util import listify +from galaxy.util import parse_xml from galaxy import eggs import pkg_resources @@ -64,9 +65,14 @@ tcf = kwargs[ 'tool_config_files' ] else: tcf = 'tool_conf.xml,shed_tool_conf.xml' - self.tool_filters = listify( kwargs.get( "tool_filters", [] ) ) - self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ) ) - self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ) ) + self.tool_filters = listify( kwargs.get( "tool_filters", [] ), do_strip=True ) + self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ), do_strip=True ) + self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ), do_strip=True ) + + self.user_tool_filters = listify( kwargs.get( "user_tool_filters", [] ), do_strip=True ) + self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True ) + self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True ) + self.tool_configs = [ resolve_path( p, self.root ) for p in listify( tcf ) ] self.shed_tool_data_path = kwargs.get( "shed_tool_data_path", None ) if self.shed_tool_data_path: @@ -489,3 +495,4 @@ sentry_handler = SentryHandler( config.sentry_dsn ) sentry_handler.setLevel( logging.WARN ) root.addHandler( sentry_handler ) + diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -3359,7 +3359,7 @@ #end of Data Manager Classes class UserPreference ( object ): - def __init__( self, name=None, value=None ): + def __init__( self, name=None, value=None): self.name = name self.value = value diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -3433,3 +3433,4 @@ class InterruptedUpload( Exception ): pass + diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/filters/__init__.py --- a/lib/galaxy/tools/filters/__init__.py +++ b/lib/galaxy/tools/filters/__init__.py @@ -1,4 +1,5 @@ - +from galaxy.util import listify +from copy import deepcopy class FilterFactory( object ): """ @@ -15,25 +16,39 @@ self.default_filters = dict( tool=[ _not_hidden, _handle_requires_login ], section=[], label=[] ) # Add dynamic filters to these default filters. config = toolbox.app.config - self.__init_filters( "tool", config.tool_filters ) - self.__init_filters( "section", config.tool_section_filters ) - self.__init_filters( "label", config.tool_label_filters ) + self.__init_filters( "tool", config.tool_filters, self.default_filters ) + self.__init_filters( "section", config.tool_section_filters, self.default_filters ) + self.__init_filters( "label", config.tool_label_filters, self.default_filters ) def build_filters( self, trans, **kwds ): """ Build list of filters to check tools against given current context. """ - filters = self.default_filters.copy() - + filters = deepcopy( self.default_filters ) + if trans.user: + for name, value in trans.user.preferences.items(): + if value.strip(): + user_filters = listify( value, do_strip=True ) + category = '' + if name == 'toolbox_tool_filters': + category = "tool" + elif name == 'toolbox_section_filters': + category = "section" + elif name == 'toolbox_label_filters': + category = "label" + if category: + self.__init_filters( category, user_filters, filters ) + else: if kwds.get( "trackster", False ): filters[ "tool" ].append( _has_trackster_conf ) return filters - def __init_filters( self, key, filters ): + def __init_filters( self, key, filters, toolbox_filters ): for filter in filters: filter_function = self.__build_filter_function( filter ) - self.default_filters[ key ].append( filter_function ) + toolbox_filters[ key ].append( filter_function ) + return toolbox_filters def __build_filter_function( self, filter_name ): """Obtain python function (importing a submodule if needed) diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/tools/filters/examples.py --- /dev/null +++ b/lib/galaxy/tools/filters/examples.py @@ -0,0 +1,115 @@ +import logging +log = logging.getLogger( __name__ ) + + +def restrict_encode( content, tool ): + """ + Disable the random interval ENCODE tool + + This tool filter will disable all the ENCODE tool when enabled. + """ + if tool.id == 'random_intervals1': + return False + return True + + +def restrict_text( content, section ): + """ + Disable Text sections + + This tool filter will disable all Tools groups under a 'Text' section when enabled. + """ + if section.name.find('Text') != -1: + return False + return True + + +def restrict_upload_to_admins( context, tool ): + """ + Disable Upload tool for all non-admin users. + + This tool filter will hide the upload tool from all users except admin + users. + + This can be enabled by renaming this file to examples.py and adding + the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:restrict_upload_to_admins + """ + if tool.name == "Upload File": + return context.trans.user_is_admin() + return True + + +def disable_gatk( context, tool ): + """ + This tool filter will disable all gatk tools when enabled. + + This can be enabled by renaming this file to examples.py and adding the following to the + ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:disable_gatk + """ + return not any( [ requirement.name == "gatk" for requirement in tool.requirements ] ) + + +def explicit_user_mapping( context, section ): + """ + This tool section filter uses an explicit mapping to describe what users can view + which tool sections. Anonymous users will only be able to view the "Get Data" + tool section (with id getext). This can be enabled by renaming this file to + examples.py and adding the following to the ``app:main`` section of + ``universe_wsgi.ini``: + + tool_section_filters = examples:explicit_user_mapping + """ + users_sections = { + None: [ "getext" ], + "bob@example.com": [ "getext", "textutil", "filter" ], + "mary@example.com": [ "getext", "textutil", "filter", "ngs" ], + } + user = context.trans.user + email = user and user.email + valid_sections = users_sections.get( email, [] ) + return section.id in valid_sections + + +DEVELOPERS = [ "mary@example.com" ] + + +def restrict_development_tools( context, tool ): + """ + This tool filter will disable all tools with the string alpha appearing in + the version for all users except those explicitly appearing in the DEVELOPERS list + defined above. This can be enabled by renaming this file to examples.py and + adding the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_filters = examples:restrict_development_tools + """ + version = tool.version + user = context.trans.user + email = user and user.email + return "alpha" not in version or email in DEVELOPERS + + +def per_host_tool_sections( context, section ): + """ + This tool section filter results in different sections being display based on + the URL the user is making the request to. This could allow a single Galaxy instance + to seem like several different instances hosting different tools based on the URL used + to access the Galxy. This can be enabled by renaming this file to examples.py and adding + the following to the ``app:main`` section of ``universe_wsgi.ini``: + + tool_section_filters = examples:per_host_tool_sections + """ + host = context.trans.request.host + # Core tools used by all virtual hosts. + valid_sections = [ "getext", "textutil", "filter" ] + if "ngs.galaxy.example.com" in host: + valid_sections += [ "ngs" ] + elif "microarray.galaxy.example.com" in host: + valid_sections += [ "microarray" ] + elif "proteomics.galaxy.example.com" in host: + valid_sections += [ "proteomics" ] + return section.id in valid_sections + diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/util/__init__.py --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -504,7 +504,7 @@ else: return False -def listify( item ): +def listify( item, do_strip=False ): """ Make a single item a single item list, or return a list if passed a list. Passing a None returns an empty list. @@ -514,7 +514,10 @@ elif isinstance( item, list ): return item elif isinstance( item, basestring ) and item.count( ',' ): - return item.split( ',' ) + if do_strip: + return [token.strip() for token in item.split( ',' )] + else: + return item.split( ',' ) else: return [ item ] @@ -778,6 +781,32 @@ current_group, e ) ) +def docstring_trim(docstring): + """Trimming python doc strings. Taken from: http://www.python.org/dev/peps/pep-0257/""" + if not docstring: + return '' + # Convert tabs to spaces (following the normal Python rules) + # and split into a list of lines: + lines = docstring.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxint + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxint: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + # Return a single string: + return '\n'.join(trimmed) + def nice_size(size): """ Returns a readably formatted string with the size diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -10,15 +10,25 @@ import random import urllib from galaxy import web -from galaxy import util, model +from galaxy import util +from galaxy import model from galaxy.model.orm import and_ -from galaxy.security.validate_user_input import validate_email, validate_publicname, validate_password, transform_publicname -from galaxy.util.json import from_json_string, to_json_string +from galaxy.security.validate_user_input import validate_email +from galaxy.security.validate_user_input import validate_publicname +from galaxy.security.validate_user_input import validate_password +from galaxy.security.validate_user_input import transform_publicname +from galaxy.util.json import from_json_string +from galaxy.util.json import to_json_string +from galaxy.util import listify +from galaxy.util import docstring_trim from galaxy.web import url_for -from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin -from galaxy.web.form_builder import CheckboxField, build_select_field +from galaxy.web.base.controller import BaseUIController +from galaxy.web.base.controller import UsesFormDefinitionsMixin +from galaxy.web.form_builder import CheckboxField +from galaxy.web.form_builder import build_select_field from galaxy.web.framework.helpers import time_ago, grids from datetime import datetime, timedelta +from galaxy.web.framework.helpers import grids from galaxy.util import hash_util log = logging.getLogger( __name__ ) @@ -104,6 +114,7 @@ use_panels=use_panels, message=message, status='error' ) ) + @web.expose def openid_process( self, trans, **kwd ): '''Handle's response from OpenID Providers''' @@ -231,6 +242,7 @@ redirect=redirect, message=message, status=status ) ) + @web.expose def openid_associate( self, trans, cntrller='user', **kwd ): '''Associates a user with an OpenID log in''' @@ -369,6 +381,7 @@ user_type_form_definition=user_type_form_definition, widgets=widgets, openids=openids ) + @web.expose @web.require_login( 'manage OpenIDs' ) def openid_disassociate( self, trans, **kwd ): @@ -849,6 +862,7 @@ else: user_type_form_definition = None return user_type_form_definition + def __get_widgets( self, trans, user_type_form_definition, user=None, **kwd ): widgets = [] if user_type_form_definition: @@ -950,6 +964,7 @@ username=user.username, message=message, status=status ) + @web.expose def edit_info( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -1058,6 +1073,7 @@ action='manage_user_info', cntrller=cntrller, **kwd ) ) + @web.expose def reset_password( self, trans, email=None, **kwd ): if trans.app.config.smtp_server is None: @@ -1105,6 +1121,7 @@ return trans.fill_template( '/user/reset_password.mako', message=message, status=status ) + def __validate( self, trans, params, email, password, confirm, username ): # If coming from the tool shed webapp, we'll require a public user name if trans.webapp.name == 'tool_shed': @@ -1126,6 +1143,7 @@ if user_type_fd_id in [ 'none' ]: return "Select the user's type and information" return message + @web.expose def set_default_permissions( self, trans, cntrller, **kwd ): """Sets the user's default permissions for the new histories""" @@ -1152,6 +1170,127 @@ else: # User not logged in, history group must be only public return trans.show_error_message( "You must be logged in to change your default permitted actions." ) + + @web.expose + @web.require_login() + def toolbox_filters( self, trans, cntrller, **kwd ): + """ + Sets the user's default filters for the toolbox. + Toolbox filters are specified in universe_wsgi.ini. + The user can activate them and the choice is stored in user_preferences. + """ + + def get_filter_mapping( db_filters, config_filters ): + """ + Compare the allowed filters from the universe_wsgi.ini config file with the previously saved or default filters from the database. + We need that to toogle the checkboxes for the formular in the right way. + Furthermore we extract all information associated to a filter to display them in the formular. + """ + filters = list() + for filter_name in config_filters: + if ":" in filter_name: + # Should be a submodule of filters (e.g. examples:restrict_development_tools) + (module_name, function_name) = filter_name.rsplit(":", 1) + module_name = 'galaxy.tools.filters.%s' % module_name.strip() + module = __import__( module_name, globals(), fromlist=['temp_module'] ) + function = getattr( module, function_name.strip() ) + else: + # No module found it has to be explicitly imported. + module = __import__( 'galaxy.tools.filters', globals(), fromlist=['temp_module'] ) + function = getattr( globals(), filter_name.strip() ) + + doc_string = docstring_trim( function.__doc__ ) + split = doc_string.split('\n\n') + if split: + sdesc = split[0] + else: + log.error( 'No description specified in the __doc__ string for %s.' % filter_name ) + if len(split) > 1: + description = split[1] + else: + description = '' + + if filter_name in db_filters: + filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=True ) ) + else: + filters.append( dict( filterpath=filter_name, short_desc=sdesc, desc=description, checked=False ) ) + return filters + + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + + user_id = params.get( 'user_id', False ) + if user_id: + user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) ) + else: + user = trans.user + + if user: + saved_user_tool_filters = list() + saved_user_section_filters = list() + saved_user_label_filters = list() + + for name, value in user.preferences.items(): + if name == 'toolbox_tool_filters': + saved_user_tool_filters = listify( value, do_strip=True ) + elif name == 'toolbox_section_filters': + saved_user_section_filters = listify( value, do_strip=True ) + elif name == 'toolbox_label_filters': + saved_user_label_filters = listify( value, do_strip=True ) + + tool_filters = get_filter_mapping( saved_user_tool_filters, trans.app.config.user_tool_filters ) + section_filters = get_filter_mapping( saved_user_section_filters, trans.app.config.user_section_filters ) + label_filters = get_filter_mapping( saved_user_label_filters, trans.app.config.user_label_filters ) + + return trans.fill_template( 'user/toolbox_filters.mako', + cntrller=cntrller, + message=message, + tool_filters=tool_filters, + section_filters=section_filters, + label_filters=label_filters, + user=user, + status=status ) + else: + # User not logged in, history group must be only public + return trans.show_error_message( "You must be logged in to change private toolbox filters." ) + + @web.expose + @web.require_login( "to change the private toolbox filters" ) + def edit_toolbox_filters( self, trans, cntrller, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + user_id = params.get( 'user_id', False ) + if not user_id: + # User must be logged in to create a new address + return trans.show_error_message( "You must be logged in to change the ToolBox filters." ) + + user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( user_id ) ) + + if params.get( 'edit_toolbox_filter_button', False ): + tool_filters = list() + section_filters = list() + label_filters = list() + for name, state in params.flatten(): + if state == 'on': + if name.startswith('t_'): + tool_filters.append( name[2:] ) + elif name.startswith('l_'): + label_filters.append( name[2:] ) + elif name.startswith('s_'): + section_filters.append( name[2:] ) + user.preferences['toolbox_tool_filters'] = ','.join( tool_filters ) + user.preferences['toolbox_section_filters'] = ','.join( section_filters ) + user.preferences['toolbox_label_filters'] = ','.join( label_filters ) + + trans.sa_session.add( user ) + trans.sa_session.flush() + message = 'ToolBox filters has been updated.' + kwd = dict( message=message, status='done' ) + + # Display the ToolBox filters form with the current values filled in + return self.toolbox_filters( trans, cntrller, **kwd ) + @web.expose @web.require_login( "to get most recently used tool" ) @web.json_pretty @@ -1175,6 +1314,7 @@ "description" : tool.description } return tool_info + @web.expose def manage_addresses(self, trans, **kwd): if trans.user: @@ -1196,6 +1336,7 @@ else: # User not logged in, history group must be only public return trans.show_error_message( "You must be logged in to change your default permitted actions." ) + @web.expose def new_address( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -1280,6 +1421,7 @@ phone=phone, message=message, status=status ) + @web.expose def edit_address( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -1357,6 +1499,7 @@ address_obj=address_obj, message=message, status=status ) + @web.expose def delete_address( self, trans, cntrller, address_id=None, user_id=None ): try: @@ -1377,6 +1520,7 @@ user_id=user_id, message=message, status=status ) ) + @web.expose def undelete_address( self, trans, cntrller, address_id=None, user_id=None ): try: @@ -1396,6 +1540,7 @@ user_id=user_id, message=message, status=status ) ) + @web.expose def set_user_pref_async( self, trans, pref_name, pref_value ): """ Set a user preference asynchronously. If user is not logged in, do nothing. """ diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 templates/user/index.mako --- a/templates/user/index.mako +++ b/templates/user/index.mako @@ -13,6 +13,7 @@ <li><a href="${h.url_for( controller='user', action='manage_user_info', cntrller=cntrller )}">${_('Manage your information')}</a></li><li><a href="${h.url_for( controller='user', action='set_default_permissions', cntrller=cntrller )}">${_('Change default permissions')}</a> for new histories</li><li><a href="${h.url_for( controller='user', action='api_keys', cntrller=cntrller )}">${_('Manage your API keys')}</a></li> + <li><a href="${h.url_for( controller='user', action='toolbox_filters', cntrller=cntrller )}">${_('Manage your ToolBox filters')}</a></li> %if trans.app.config.enable_openid: <li><a href="${h.url_for( controller='user', action='openid_manage', cntrller=cntrller )}">${_('Manage OpenIDs')}</a> linked to your account</li> %endif diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 templates/user/toolbox_filters.mako --- /dev/null +++ b/templates/user/toolbox_filters.mako @@ -0,0 +1,91 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if message: + ${render_msg( message, status )} +%endif +</br> +</br> + +<ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='user', action='index', cntrller=cntrller )}">User preferences</a> + </li> +</ul> + +%if tool_filters or section_filters or label_filters: + <div class="toolForm"> + <form name="toolbox_filter" id="toolbox_filter" action="${h.url_for( controller='user', action='edit_toolbox_filters', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" > + % if tool_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Tools</div> + <div class="toolFormBody"> + % for filter in tool_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="t_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="t_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + + % if section_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Sections</div> + <div class="toolFormBody"> + % for filter in section_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="s_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="s_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + + % if label_filters: + <div class="toolFormTitle">Edit ToolBox filters :: Labels</div> + <div class="toolFormBody"> + % for filter in label_filters: + <div class="form-row"> + <div style="float: left; width: 40px; margin-right: 10px;"> + % if filter['checked']: + <input type="checkbox" name="l_${filter['filterpath']}" checked="checked"> + % else: + <input type="checkbox" name="l_${filter['filterpath']}"> + % endif + </div> + <div style="float: left; margin-right: 10px;"> + ${filter['short_desc']} + <div class="toolParamHelp" style="clear: both;">${filter['desc']}</div> + </div> + <div style="clear: both"></div> + </div> + % endfor + </div> + % endif + <div class="form-row"> + <input type="submit" name="edit_toolbox_filter_button" value="Save changes"> + </div> + </form> + </div> +%else: + ${render_msg( 'No filter available. Contact you system administrator or check your configuration file.', 'info' )} +%endif diff -r f1d77cc9136794e0272f2ed9b1b33f976f3a0f10 -r fb1b676f51b224a4f3b830402d79652850dd9261 universe_wsgi.ini.sample --- a/universe_wsgi.ini.sample +++ b/universe_wsgi.ini.sample @@ -758,6 +758,18 @@ # if running many handlers. #cache_user_job_count = False +# ToolBox filtering +# Modules from lib/galaxy/tools/filters/ can be specified in the following lines. +# tool_* filters will be applied for all users and can not be changed by them. +# user_tool_* filters will be shown under user preferences and can be toogled +# on and off by runtime +#tool_filters +#tool_label_filters +#tool_section_filters +#user_tool_filters = examples:restrict_upload_to_admins, examples:restrict_encode +#user_tool_section_filters = examples:restrict_text +#user_tool_label_filters = examples:restrict_upload_to_admins, examples:restrict_encode + # ---- Galaxy Message Queue ------------------------------------------------- # Galaxy uses AMQ protocol to receive messages from external sources like https://bitbucket.org/galaxy/galaxy-central/commits/74100455218f/ Changeset: 74100455218f User: dannon Date: 2013-10-17 19:41:45 Summary: Fix duplicate import from bad merge Affected #: 1 file diff -r fb1b676f51b224a4f3b830402d79652850dd9261 -r 74100455218f1dbfb2ef39aceda4f88ae15e50ef lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -28,7 +28,6 @@ from galaxy.web.form_builder import build_select_field from galaxy.web.framework.helpers import time_ago, grids from datetime import datetime, timedelta -from galaxy.web.framework.helpers import grids from galaxy.util import hash_util log = logging.getLogger( __name__ ) https://bitbucket.org/galaxy/galaxy-central/commits/bdf393fb4155/ Changeset: bdf393fb4155 User: dannon Date: 2013-10-17 20:09:07 Summary: Fix indentation from merge Affected #: 1 file diff -r 74100455218f1dbfb2ef39aceda4f88ae15e50ef -r bdf393fb4155bed5f633d2daf9cd6a96ab46e7ce lib/galaxy/tools/filters/__init__.py --- a/lib/galaxy/tools/filters/__init__.py +++ b/lib/galaxy/tools/filters/__init__.py @@ -39,8 +39,8 @@ if category: self.__init_filters( category, user_filters, filters ) else: - if kwds.get( "trackster", False ): - filters[ "tool" ].append( _has_trackster_conf ) + if kwds.get( "trackster", False ): + filters[ "tool" ].append( _has_trackster_conf ) return filters https://bitbucket.org/galaxy/galaxy-central/commits/f888228f48d8/ Changeset: f888228f48d8 User: dannon Date: 2013-10-17 21:31:15 Summary: Merge w/ central Affected #: 1 file diff -r bdf393fb4155bed5f633d2daf9cd6a96ab46e7ce -r f888228f48d89ade8b8f49a4d777c573174392d1 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py --- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py @@ -293,7 +293,7 @@ full_path_to_dir = os.path.abspath( install_dir ) td_common_util.move_file( current_dir=work_dir, source=downloaded_filename, - destination_dir=full_path_to_dir ) + destination=full_path_to_dir ) if action_type == 'download_by_url': # Eliminate the download_by_url action so remaining actions can be processed correctly. filtered_actions = actions[ 1: ] @@ -551,7 +551,7 @@ full_path_to_dir = os.path.abspath( install_dir ) td_common_util.move_file( current_dir=work_dir, source=downloaded_filename, - destination_dir=full_path_to_dir ) + destination=full_path_to_dir ) def log_results( command, fabric_AttributeString, file_path ): """ https://bitbucket.org/galaxy/galaxy-central/commits/acf1a0062ea8/ Changeset: acf1a0062ea8 Branch: custom-toolbox2 User: dannon Date: 2013-10-17 21:32:40 Summary: Close feature branch for toolbox filtering 2 Affected #: 0 files Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.
participants (1)
-
commits-noreply@bitbucket.org