Warning

This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.webapps.galaxy.buildapp

"""
Provides factory methods to assemble the Galaxy web application
"""
import atexit
import logging
import sys
import threading
import traceback
from urllib.parse import urljoin

from paste import httpexceptions
from tuswsgi import TusMiddleware

import galaxy.app
import galaxy.datatypes.registry
import galaxy.model
import galaxy.model.mapping
import galaxy.web.framework
import galaxy.webapps.base.webapp
from galaxy import util
from galaxy.security.validate_user_input import VALID_PUBLICNAME_RE
from galaxy.util import asbool
from galaxy.util.properties import load_app_properties
from galaxy.web.framework.middleware.batch import BatchMiddleware
from galaxy.web.framework.middleware.error import ErrorMiddleware
from galaxy.web.framework.middleware.request_id import RequestIDMiddleware
from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware
from galaxy.webapps.base.webapp import build_url_map
from galaxy.webapps.util import wrap_if_allowed

log = logging.getLogger(__name__)


[docs]class GalaxyWebApplication(galaxy.webapps.base.webapp.WebApplication): injection_aware = True
[docs]def app_factory(*args, **kwargs): """ Return a wsgi application serving the root object """ return app_pair(*args, **kwargs)[0]
[docs]def app_pair(global_conf, load_app_kwds=None, wsgi_preflight=True, **kwargs): """ Return a wsgi application serving the root object and the Galaxy application. When creating an app for asgi, set wsgi_preflight to False to allow FastAPI middleware to handle CORS options, etc.. """ load_app_kwds = load_app_kwds or {} kwargs = load_app_properties( kwds=kwargs, **load_app_kwds ) # Create the Galaxy application unless passed in if 'app' in kwargs: app = kwargs.pop('app') galaxy.app.app = app else: try: app = galaxy.app.UniverseApplication(global_conf=global_conf, **kwargs) galaxy.app.app = app except Exception: traceback.print_exc() sys.exit(1) if kwargs.get('register_shutdown_at_exit', True): # Call app's shutdown method when the interpeter exits, this cleanly stops # the various Galaxy application daemon threads app.application_stack.register_postfork_function(atexit.register, app.shutdown) # Create the universe WSGI application webapp = GalaxyWebApplication(app, session_cookie='galaxysession', name='galaxy') # STANDARD CONTROLLER ROUTES webapp.add_ui_controllers('galaxy.webapps.galaxy.controllers', app) # Force /history to go to view of current webapp.add_route('/history', controller='history', action='view') webapp.add_route('/history/view/{id}', controller='history', action='view') # Force /activate to go to the controller webapp.add_route('/activate', controller='user', action='activate') # Authentication endpoints. webapp.add_route('/authnz/', controller='authnz', action='index', provider=None) webapp.add_route('/authnz/{provider}/login', controller='authnz', action='login', provider=None) webapp.add_route('/authnz/{provider}/callback', controller='authnz', action='callback', provider=None) webapp.add_route('/authnz/{provider}/disconnect/{email}', controller='authnz', action='disconnect', provider=None, email=None) webapp.add_route('/authnz/{provider}/logout', controller='authnz', action='logout', provider=None) webapp.add_route('/authnz/{provider}/create_user', controller='authnz', action='create_user') # Returns the provider specific logout url for currently logged in provider webapp.add_route('/authnz/logout', controller='authnz', action='get_logout_url') webapp.add_route('/authnz/get_cilogon_idps', controller='authnz', action='get_cilogon_idps') # These two routes handle our simple needs at the moment webapp.add_route('/async/{tool_id}/{data_id}/{data_secret}', controller='async', action='index', tool_id=None, data_id=None, data_secret=None) webapp.add_route('/{controller}/{action}', action='index') webapp.add_route('/{action}', controller='root', action='index') # allow for subdirectories in extra_files_path webapp.add_route('/datasets/{dataset_id}/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None) webapp.add_route('/datasets/{dataset_id}/{action}/{filename}', controller='dataset', action='index', dataset_id=None, filename=None) webapp.add_route('/display_application/{dataset_id}/{app_name}/{link_name}/{user_id}/{app_action}/{action_param}/{action_param_extra:.+?}', controller='dataset', action='display_application', dataset_id=None, user_id=None, app_name=None, link_name=None, app_action=None, action_param=None, action_param_extra=None) USERNAME_REQS = {'username': VALID_PUBLICNAME_RE.pattern.strip("^$")} webapp.add_route('/u/{username}/d/{slug}/{filename}', controller='dataset', action='display_by_username_and_slug', filename=None, requirements=USERNAME_REQS) webapp.add_route('/u/{username}/p/{slug}', controller='page', action='display_by_username_and_slug', requirements=USERNAME_REQS) webapp.add_route('/u/{username}/h/{slug}', controller='history', action='display_by_username_and_slug', requirements=USERNAME_REQS) webapp.add_route('/u/{username}/w/{slug}', controller='workflow', action='display_by_username_and_slug', requirements=USERNAME_REQS) webapp.add_route('/u/{username}/w/{slug}/{format}', controller='workflow', action='display_by_username_and_slug', requirements=USERNAME_REQS) webapp.add_route('/u/{username}/v/{slug}', controller='visualization', action='display_by_username_and_slug', requirements=USERNAME_REQS) # TODO: Refactor above routes into external method to allow testing in # isolation as well. populate_api_routes(webapp, app) if wsgi_preflight: # API OPTIONS RESPONSE webapp.mapper.connect( 'options', '/api/{path_info:.*?}', controller='authenticate', action='options', conditions={'method': ['OPTIONS']}, ) # CLIENTSIDE ROUTES # The following are routes that are handled completely on the clientside. # The following routes don't bootstrap any information, simply provide the # base analysis interface at which point the application takes over. webapp.add_client_route('/admin/data_tables', 'admin') webapp.add_client_route('/admin/data_types', 'admin') webapp.add_client_route('/admin/jobs', 'admin') webapp.add_client_route('/admin/invocations', 'admin') webapp.add_client_route('/admin/toolbox_dependencies', 'admin') webapp.add_client_route('/admin/data_manager{path_info:.*}', 'admin') webapp.add_client_route('/admin/error_stack', 'admin') webapp.add_client_route('/admin/users', 'admin') webapp.add_client_route('/admin/users/create', 'admin') webapp.add_client_route('/admin/display_applications', 'admin') webapp.add_client_route('/admin/reset_metadata', 'admin') webapp.add_client_route('/admin/roles', 'admin') webapp.add_client_route('/admin/forms', 'admin') webapp.add_client_route('/admin/groups', 'admin') webapp.add_client_route('/admin/repositories', 'admin') webapp.add_client_route('/admin/sanitize_allow', 'admin') webapp.add_client_route('/admin/tool_versions', 'admin') webapp.add_client_route('/admin/toolshed', 'admin') webapp.add_client_route('/admin/quotas', 'admin') webapp.add_client_route('/admin/form/{form_id}', 'admin') webapp.add_client_route('/admin/api_keys', 'admin') webapp.add_client_route('/login/confirm') webapp.add_client_route('/tools/view') webapp.add_client_route('/tools/json') webapp.add_client_route('/tours') webapp.add_client_route('/tours/{tour_id}') webapp.add_client_route('/user') webapp.add_client_route('/user/{form_id}') webapp.add_client_route('/welcome/new') webapp.add_client_route('/visualizations') webapp.add_client_route('/visualizations/edit') webapp.add_client_route('/visualizations/sharing') webapp.add_client_route('/visualizations/list_published') webapp.add_client_route('/visualizations/list') webapp.add_client_route('/pages/list') webapp.add_client_route('/pages/list_published') webapp.add_client_route('/pages/create') webapp.add_client_route('/pages/edit') webapp.add_client_route('/pages/sharing') webapp.add_client_route('/histories/citations') webapp.add_client_route('/histories/list') webapp.add_client_route('/histories/import') webapp.add_client_route('/histories/{history_id}/export') webapp.add_client_route('/histories/list_published') webapp.add_client_route('/histories/list_shared') webapp.add_client_route('/histories/rename') webapp.add_client_route('/histories/sharing') webapp.add_client_route('/histories/permissions') webapp.add_client_route('/histories/view') webapp.add_client_route('/histories/show_structure') webapp.add_client_route('/datasets/list') webapp.add_client_route('/datasets/edit') webapp.add_client_route('/collection/edit/{collection_id}') webapp.add_client_route('/datasets/error') webapp.add_client_route('/jobs/{job_id}/view') webapp.add_client_route('/datasets/{dataset_id}/details') webapp.add_client_route('/datasets/{dataset_id}/show_params') webapp.add_client_route('/workflows/list') webapp.add_client_route('/workflows/list_published') webapp.add_client_route('/workflows/create') webapp.add_client_route('/workflows/run') webapp.add_client_route('/workflows/import') webapp.add_client_route('/workflows/trs_import') webapp.add_client_route('/workflows/trs_search') webapp.add_client_route('/workflows/invocations') webapp.add_client_route('/workflows/invocations/report') # webapp.add_client_route('/workflows/invocations/view_bco') webapp.add_client_route('/custom_builds') webapp.add_client_route('/interactivetool_entry_points/list') webapp.add_client_route('/libraries{path:.*?}') # ==== Done # Indicate that all configuration settings have been provided webapp.finalize_config() # Wrap the webapp in some useful middleware if kwargs.get('middleware', True): webapp = wrap_in_middleware(webapp, global_conf, app.application_stack, **kwargs) if asbool(kwargs.get('static_enabled', True)): webapp = wrap_if_allowed(webapp, app.application_stack, build_url_map, args=(global_conf,), kwargs=kwargs) app.application_stack.register_postfork_function(postfork_setup) for th in threading.enumerate(): if th.is_alive(): log.debug("Prior to webapp return, Galaxy thread %s is alive.", th) # Return return webapp, app
[docs]def uwsgi_app(): return galaxy.webapps.base.webapp.build_native_uwsgi_app(app_factory, "galaxy")
# For backwards compatibility uwsgi_app_factory = uwsgi_app
[docs]def postfork_setup(): from galaxy.app import app app.application_stack.log_startup()
[docs]def populate_api_routes(webapp, app): webapp.add_api_controllers('galaxy.webapps.galaxy.api', app) valid_history_contents_types = [ 'dataset', 'dataset_collection', ] # Accesss HDA details via histories/{history_id}/contents/datasets/{hda_id} # and HDCA details via histories/{history_id}/contents/dataset_collections/{hdca_id} webapp.mapper.resource("content_typed", "{type:%s}s" % "|".join(valid_history_contents_types), name_prefix="history_", controller='history_contents', path_prefix='/api/histories/{history_id}/contents', parent_resources=dict(member_name='history', collection_name='histories')) # Legacy access to HDA details via histories/{history_id}/contents/{hda_id} webapp.mapper.resource('content', 'contents', controller='history_contents', name_prefix='history_', path_prefix='/api/histories/{history_id}', parent_resources=dict(member_name='history', collection_name='histories')) webapp.mapper.connect("history_contents_batch_update", "/api/histories/{history_id}/contents", controller="history_contents", action="update_batch", conditions=dict(method=["PUT"])) webapp.mapper.connect("history_contents_display", "/api/histories/{history_id}/contents/{history_content_id}/display", controller="datasets", action="display", conditions=dict(method=["GET"])) webapp.mapper.connect("history_contents_update_permissions", "/api/histories/{history_id}/contents/{history_content_id}/permissions", controller="history_contents", action="update_permissions", conditions=dict(method=["PUT"])) webapp.mapper.connect("history_contents_validate", "/api/histories/{history_id}/contents/{history_content_id}/validate", controller="history_contents", action="validate", conditions=dict(method=["PUT"])) webapp.mapper.connect("history_contents_extra_files", "/api/histories/{history_id}/contents/{history_content_id}/extra_files", controller="datasets", action="extra_files", conditions=dict(method=["GET"])) webapp.mapper.connect("history_content_as_text", "/api/datasets/{dataset_id}/get_content_as_text", controller="datasets", action="get_content_as_text", conditions=dict(method=["GET"])) webapp.mapper.connect('dataset_storage', '/api/datasets/{dataset_id}/storage', controller='datasets', action='show_storage', conditions=dict(method=["GET"])) webapp.mapper.connect('dataset_inheritance_chain', '/api/datasets/{dataset_id}/inheritance_chain', controller='datasets', action='show_inheritance_chain', conditions=dict(method=["GET"])) webapp.mapper.connect("get_metadata_file", "/api/histories/{history_id}/contents/{history_content_id}/metadata_file", controller="datasets", action="get_metadata_file", conditions=dict(method=["GET"])) webapp.mapper.connect("/api/histories/{history_id}/contents/{direction:near|before|after}/{hid}/{limit}", action="contents_near", controller='history_contents', conditions=dict(method=["GET"])) webapp.mapper.resource('user', 'users', controller='group_users', name_prefix='group_', path_prefix='/api/groups/{group_id}', parent_resources=dict(member_name='group', collection_name='groups')) webapp.mapper.resource('role', 'roles', controller='group_roles', name_prefix='group_', path_prefix='/api/groups/{group_id}', parent_resources=dict(member_name='group', collection_name='groups')) _add_item_tags_controller(webapp, name_prefix="history_content_", path_prefix='/api/histories/{history_id}/contents/{history_content_id}') webapp.mapper.connect('/api/histories/published', action='published', controller="histories", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/histories/shared_with_me', action='shared_with_me', controller="histories") webapp.mapper.connect('cloud_storage', '/api/cloud/storage/', controller='cloud', action='index', conditions=dict(method=["GET"])) webapp.mapper.connect('cloud_storage_get', '/api/cloud/storage/get', controller='cloud', action='get', conditions=dict(method=["POST"])) webapp.mapper.connect('cloud_storage_send', '/api/cloud/storage/send', controller='cloud', action='send', conditions=dict(method=["POST"])) _add_item_tags_controller(webapp, name_prefix="history_", path_prefix='/api/histories/{history_id}') _add_item_tags_controller(webapp, name_prefix="workflow_", path_prefix='/api/workflows/{workflow_id}') _add_item_annotation_controller(webapp, name_prefix="history_content_", path_prefix='/api/histories/{history_id}/contents/{history_content_id}') _add_item_annotation_controller(webapp, name_prefix="history_", path_prefix='/api/histories/{history_id}') _add_item_annotation_controller(webapp, name_prefix="workflow_", path_prefix='/api/workflows/{workflow_id}') _add_item_provenance_controller(webapp, name_prefix="history_content_", path_prefix='/api/histories/{history_id}/contents/{history_content_id}') webapp.mapper.resource('dataset', 'datasets', path_prefix='/api') webapp.mapper.resource('tool_data', 'tool_data', path_prefix='/api') webapp.mapper.connect('/api/tool_data/{id:.+?}/fields/{value:.+?}/files/{path:.+?}', action='download_field_file', controller="tool_data") webapp.mapper.connect('/api/tool_data/{id:.+?}/fields/{value:.+?}', action='show_field', controller="tool_data") webapp.mapper.connect('/api/tool_data/{id:.+?}/reload', action='reload', controller="tool_data") webapp.mapper.resource('dataset_collection', 'dataset_collections', path_prefix='/api') webapp.mapper.connect('contents_dataset_collection', '/api/dataset_collections/{hdca_id}/contents/{parent_id}', controller="dataset_collections", action="contents") webapp.mapper.resource('form', 'forms', path_prefix='/api') webapp.mapper.resource('role', 'roles', path_prefix='/api') webapp.mapper.resource('upload', 'uploads', path_prefix='/api') webapp.mapper.connect('/api/upload/resumable_upload/{session_id}', controller="uploads", action="hooks", conditions=dict(method=['PATCH'])) webapp.mapper.connect('/api/upload/resumable_upload', controller="uploads", action="hooks") webapp.mapper.connect('/api/upload/hooks', controller="uploads", action="hooks", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/ftp_files', controller='remote_files') webapp.mapper.connect('/api/remote_files', action='index', controller='remote_files', conditions=dict(method=["GET"])) webapp.mapper.connect('/api/remote_files/plugins', action='plugins', controller='remote_files', conditions=dict(method=["GET"])) webapp.mapper.resource('group', 'groups', path_prefix='/api') webapp.mapper.resource_with_deleted('quota', 'quotas', path_prefix='/api') webapp.mapper.connect('/api/cloud/authz/', action='index', controller='cloudauthz', conditions=dict(method=["GET"])) webapp.mapper.connect('/api/cloud/authz/', action='create', controller='cloudauthz', conditions=dict(method=["POST"])) webapp.mapper.connect('delete_cloudauthz_item', '/api/cloud/authz/{encoded_authz_id}', action='delete', controller='cloudauthz', conditions=dict(method=["DELETE"])) webapp.mapper.connect('upload_cloudauthz_item', '/api/cloud/authz/{encoded_authz_id}', action='update', controller="cloudauthz", conditions=dict(method=["PUT"])) webapp.mapper.connect('get_custom_builds_metadata', '/api/histories/{id}/custom_builds_metadata', controller='histories', action='get_custom_builds_metadata', conditions=dict(method=["GET"])) # ======================= # ====== TOOLS API ====== # ======================= webapp.mapper.connect('/api/tools/fetch', action='fetch', controller='tools', conditions=dict(method=["POST"])) webapp.mapper.connect('/api/tools/all_requirements', action='all_requirements', controller="tools") webapp.mapper.connect('/api/tools/error_stack', action='error_stack', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/build', action='build', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/reload', action='reload', controller="tools") webapp.mapper.connect('/api/tools/tests_summary', action='tests_summary', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/test_data_path', action='test_data_path', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/test_data_download', action='test_data_download', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/test_data', action='test_data', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/diagnostics', action='diagnostics', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/citations', action='citations', controller="tools") webapp.mapper.connect('/api/tools/{tool_id:.+?}/convert', action='conversion', controller="tools", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/tools/{id:.+?}/xrefs', action='xrefs', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/download', action='download', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/raw_tool_source', action='raw_tool_source', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/requirements', action='requirements', controller="tools") webapp.mapper.connect('/api/tools/{id:.+?}/install_dependencies', action='install_dependencies', controller="tools", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/tools/{id:.+?}/dependencies', action='install_dependencies', controller="tools", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/tools/{id:.+?}/dependencies', action='uninstall_dependencies', controller="tools", conditions=dict(method=["DELETE"])) webapp.mapper.connect('/api/tools/{id:.+?}/build_dependency_cache', action='build_dependency_cache', controller="tools", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/tools/{id:.+?}', action='show', controller="tools") webapp.mapper.resource('tool', 'tools', path_prefix='/api') webapp.mapper.resource('dynamic_tools', 'dynamic_tools', path_prefix='/api') webapp.mapper.connect('/api/sanitize_allow', action='index', controller='sanitize_allow', conditions=dict(method=["GET"])) webapp.mapper.connect('/api/sanitize_allow', action='create', controller='sanitize_allow', conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/sanitize_allow', action='delete', controller='sanitize_allow', conditions=dict(method=["DELETE"])) webapp.mapper.connect('/api/entry_points', action='index', controller="tool_entry_points") webapp.mapper.connect('/api/entry_points/{id:.+?}/access', action='access_entry_point', controller="tool_entry_points") webapp.mapper.connect('/api/entry_points/{id:.+?}', action='stop_entry_point', controller="tool_entry_points", conditions={'method': ['DELETE']}) webapp.mapper.connect('/api/dependency_resolvers/clean', action="clean", controller="tool_dependencies", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/dependency', action="manager_dependency", controller="tool_dependencies", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/dependency_resolvers/dependency', action="install_dependency", controller="tool_dependencies", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/requirements', action="manager_requirements", controller="tool_dependencies") webapp.mapper.connect('/api/dependency_resolvers/unused_paths', action="unused_dependency_paths", controller="tool_dependencies", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/dependency_resolvers/unused_paths', action="delete_unused_dependency_paths", controller="tool_dependencies", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/dependency_resolvers/toolbox', controller="tool_dependencies", action="summarize_toolbox", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/dependency_resolvers/toolbox/install', controller="tool_dependencies", action="toolbox_install", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/toolbox/uninstall', controller="tool_dependencies", action="toolbox_uninstall", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/{index}/clean', action="clean", controller="tool_dependencies", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/{index}/dependency', action="resolver_dependency", controller="tool_dependencies", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/dependency_resolvers/{index}/dependency', action="install_dependency", controller="tool_dependencies", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/dependency_resolvers/{index}/requirements', action="resolver_requirements", controller="tool_dependencies") webapp.mapper.resource('dependency_resolver', 'dependency_resolvers', controller="tool_dependencies", path_prefix='api') webapp.mapper.connect('/api/container_resolvers', action="index", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/resolve', action="resolve", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/toolbox', action="resolve_toolbox", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/resolve/install', action="resolve_with_install", controller="container_resolution", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/container_resolvers/toolbox/install', action="resolve_toolbox_with_install", controller="container_resolution", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/container_resolvers/{index}', action="show", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/{index}/resolve', action="resolve", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/{index}/toolbox', action="resolve_toolbox", controller="container_resolution", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/container_resolvers/{index}/resolve/install', action="resolve_with_install", controller="container_resolution", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/container_resolvers/{index}/toolbox/install', action="resolve_toolbox_with_install", controller="container_resolution", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/workflows/get_tool_predictions', action='get_tool_predictions', controller="workflows", conditions=dict(method=["POST"])) webapp.mapper.resource_with_deleted('user', 'users', path_prefix='/api') webapp.mapper.resource('genome', 'genomes', path_prefix='/api') webapp.mapper.connect('/api/genomes/{id}/indexes', controller='genomes', action='indexes') webapp.mapper.connect('/api/genomes/{id}/sequences', controller='genomes', action='sequences') webapp.mapper.resource('visualization', 'visualizations', path_prefix='/api') webapp.mapper.connect('/api/visualizations/{id}/sharing', action='sharing', controller="visualizations", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/visualizations/{id}/enable_link_access', action='enable_link_access', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/visualizations/{id}/disable_link_access', action='disable_link_access', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/visualizations/{id}/publish', action='publish', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/visualizations/{id}/unpublish', action='unpublish', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/visualizations/{id}/share_with_users', action='share_with_users', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/visualizations/{id}/slug', action='set_slug', controller="visualizations", conditions=dict(method=["PUT"])) webapp.mapper.resource('plugins', 'plugins', path_prefix='/api') webapp.mapper.connect('/api/workflows/build_module', action='build_module', controller="workflows") webapp.mapper.connect('/api/workflows/menu', action='get_workflow_menu', controller="workflows", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/workflows/menu', action='set_workflow_menu', controller="workflows", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/workflows/{id}/refactor', action='refactor', controller="workflows", conditions=dict(method=["PUT"])) webapp.mapper.resource('workflow', 'workflows', path_prefix='/api') webapp.mapper.connect('/api/licenses', controller='licenses', action='index', conditions=dict(method="GET")) webapp.mapper.connect('/api/licenses/{id}', controller='licenses', action='get', conditions=dict(method="GET")) webapp.mapper.resource_with_deleted('history', 'histories', path_prefix='/api') webapp.mapper.connect('/api/histories/{history_id}/citations', action='citations', controller="histories") webapp.mapper.connect('/api/histories/{id}/sharing', action='sharing', controller="histories", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/histories/{id}/enable_link_access', action='enable_link_access', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/histories/{id}/disable_link_access', action='disable_link_access', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/histories/{id}/publish', action='publish', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/histories/{id}/unpublish', action='unpublish', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/histories/{id}/share_with_users', action='share_with_users', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/histories/{id}/slug', action='set_slug', controller="histories", conditions=dict(method=["PUT"])) webapp.mapper.connect( 'dynamic_tool_confs', '/api/configuration/dynamic_tool_confs', controller="configuration", action="dynamic_tool_confs" ) webapp.mapper.connect( 'tool_lineages', '/api/configuration/tool_lineages', controller="configuration", action="tool_lineages" ) webapp.mapper.connect( '/api/configuration/toolbox', controller="configuration", action="reload_toolbox", conditions=dict(method=["PUT"]) ) webapp.mapper.resource('configuration', 'configuration', path_prefix='/api') webapp.mapper.connect("configuration_version", "/api/version", controller="configuration", action="version", conditions=dict(method=["GET"])) webapp.mapper.connect("api_whoami", "/api/whoami", controller='configuration', action='whoami', conditions=dict(method=["GET"])) webapp.mapper.connect("api_decode", "/api/configuration/decode/{encoded_id}", controller='configuration', action='decode_id', conditions=dict(method=["GET"])) webapp.mapper.resource('datatype', 'datatypes', path_prefix='/api', collection={'sniffers': 'GET', 'mapping': 'GET', 'converters': 'GET', 'edam_data': 'GET', 'edam_formats': 'GET', 'types_and_mapping': 'GET'}, parent_resources=dict(member_name='datatype', collection_name='datatypes')) webapp.mapper.resource('search', 'search', path_prefix='/api') webapp.mapper.connect('/api/pages/{id}.pdf', action='show_pdf', controller="pages", conditions=dict(method=["GET"])) webapp.mapper.resource('page', 'pages', path_prefix="/api") webapp.mapper.connect('/api/pages/{id}/sharing', action='sharing', controller="pages", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/pages/{id}/enable_link_access', action='enable_link_access', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/pages/{id}/disable_link_access', action='disable_link_access', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/pages/{id}/publish', action='publish', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/pages/{id}/unpublish', action='unpublish', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/pages/{id}/share_with_users', action='share_with_users', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.connect('/api/pages/{id}/slug', action='set_slug', controller="pages", conditions=dict(method=["PUT"])) webapp.mapper.resource('revision', 'revisions', path_prefix='/api/pages/{page_id}', controller='page_revisions', parent_resources=dict(member_name='page', collection_name='pages')) webapp.mapper.connect("history_exports", "/api/histories/{id}/exports", controller="histories", action="index_exports", conditions=dict(method=["GET"])) webapp.mapper.connect("history_archive_export", "/api/histories/{id}/exports", controller="histories", action="archive_export", conditions=dict(method=["PUT"])) webapp.mapper.connect("history_archive_download", "/api/histories/{id}/exports/{jeha_id}", controller="histories", action="archive_download", conditions=dict(method=["GET"])) webapp.mapper.connect('/api/histories/{history_id}/contents/archive', controller='history_contents', action='archive') webapp.mapper.connect('/api/histories/{history_id}/contents/archive/{filename}{.format}', controller='history_contents', action='archive') webapp.mapper.connect("/api/histories/{history_id}/contents/dataset_collections/{id}/download", controller='history_contents', action='download_dataset_collection', conditions=dict(method=["GET"])) webapp.mapper.connect("/api/dataset_collections/{id}/download", controller='history_contents', action='download_dataset_collection', conditions=dict(method=["GET"])) webapp.mapper.connect("/api/dataset_collections/{id}/copy", controller='dataset_collections', action='update', conditions=dict(method=["POST"])) webapp.mapper.connect("/api/dataset_collections/{id}/attributes", controller='dataset_collections', action='attributes', conditions=dict(method=["GET"])) webapp.mapper.connect("api_suitable_converters", "/api/dataset_collections/{id}/suitable_converters", controller='dataset_collections', action='suitable_converters', conditions=dict(method=['GET'])) webapp.mapper.connect("/api/histories/{history_id}/jobs_summary", action="index_jobs_summary", controller='history_contents', conditions=dict(method=["GET"])) webapp.mapper.connect("/api/histories/{history_id}/contents/{type:%s}s/{id}/jobs_summary" % "|".join(valid_history_contents_types), action="show_jobs_summary", controller='history_contents', conditions=dict(method=["GET"])) # ---- visualizations registry ---- generic template renderer # @deprecated: this route should be considered deprecated webapp.add_route('/visualization/show/{visualization_name}', controller='visualization', action='render', visualization_name=None) # provide an alternate route to visualization plugins that's closer to their static assets # (/plugins/visualizations/{visualization_name}/static) and allow them to use relative urls to those webapp.mapper.connect('visualization_plugin', '/plugins/visualizations/{visualization_name}/show', controller='visualization', action='render') webapp.mapper.connect('saved_visualization', '/plugins/visualizations/{visualization_name}/saved', controller='visualization', action='saved') # same with IE's webapp.mapper.connect('interactive_environment_plugin', '/plugins/interactive_environments/{visualization_name}/show', controller='visualization', action='render') webapp.mapper.connect('saved_interactive_environment', '/plugins/interactive_environments/{visualization_name}/saved', controller='visualization', action='saved') # Deprecated in favor of POST /api/workflows with 'workflow' in payload. webapp.mapper.connect('import_workflow_deprecated', '/api/workflows/upload', controller='workflows', action='import_new_workflow_deprecated', conditions=dict(method=['POST'])) webapp.mapper.connect('workflow_dict', '/api/workflows/{workflow_id}/download', controller='workflows', action='workflow_dict', conditions=dict(method=['GET'])) webapp.mapper.connect('show_versions', '/api/workflows/{workflow_id}/versions', controller='workflows', action='show_versions', conditions=dict(method=['GET'])) # Preserve the following download route for now for dependent applications -- deprecate at some point webapp.mapper.connect('workflow_dict', '/api/workflows/download/{workflow_id}', controller='workflows', action='workflow_dict', conditions=dict(method=['GET'])) # Deprecated in favor of POST /api/workflows with shared_workflow_id in payload. webapp.mapper.connect('import_shared_workflow_deprecated', '/api/workflows/import', controller='workflows', action='import_shared_workflow_deprecated', conditions=dict(method=['POST'])) webapp.mapper.connect( 'trs_search', '/api/trs_search', controller='trs_search', action="index", conditions=dict(method=['GET']) ) webapp.mapper.connect( 'trs_consume_get_servers', '/api/trs_consume/servers', controller='trs_consumer', action="get_servers", conditions=dict(method=['GET']) ) webapp.mapper.connect( 'trs_consume_get_tool', '/api/trs_consume/{trs_server}/tools/{tool_id}', controller='trs_consumer', action="get_tool", conditions=dict(method=['GET']) ) webapp.mapper.connect( 'trs_consume_get_tool_versions', '/api/trs_consume/{trs_server}/tools/{tool_id}/versions', controller='trs_consumer', action="get_tool_versions", conditions=dict(method=['GET']) ) webapp.mapper.connect( 'trs_consume_get_tool_version', '/api/trs_consume/{trs_server}/tools/{tool_id}/versions/{version_id}', controller='trs_consumer', action="get_tool_version", conditions=dict(method=['GET']) ) webapp.mapper.connect( 'trs_consume_import_tool_version', '/api/trs_consume/{trs_server}/tools/{tool_id}/versions/{version_id}/import', controller='trs_consumer', action="import_tool_version", conditions=dict(method=['POST']) ) # route for creating/getting converted datasets webapp.mapper.connect('/api/datasets/{dataset_id}/converted', controller='datasets', action='converted', ext=None) webapp.mapper.connect('/api/datasets/{dataset_id}/converted/{ext}', controller='datasets', action='converted') webapp.mapper.connect('/api/datasets/{dataset_id}/permissions', controller='datasets', action='update_permissions', conditions=dict(method=["PUT"])) webapp.mapper.connect( 'list_invocations', '/api/invocations', controller='workflows', action='index_invocations', conditions=dict(method=['GET']) ) # API refers to usages and invocations - these mean the same thing but the # usage routes should be considered deprecated. invoke_names = { "invocations": "", "usage": "_deprecated", } for noun, suffix in invoke_names.items(): name = f"{noun}{suffix}" webapp.mapper.connect( f'list_workflow_{name}', '/api/workflows/{workflow_id}/%s' % noun, controller='workflows', action='index_invocations', conditions=dict(method=['GET']) ) webapp.mapper.connect( f'workflow_{name}', '/api/workflows/{workflow_id}/%s' % noun, controller='workflows', action='invoke', conditions=dict(method=['POST']) ) def connect_invocation_endpoint(endpoint_name, endpoint_suffix, action, conditions=None): # /api/invocations/<invocation_id> # /api/workflows/<workflow_id>/invocations/<invocation_id> # /api/workflows/<workflow_id>/usage/<invocation_id> (deprecated) conditions = conditions or dict(method=['GET']) webapp.mapper.connect( f'workflow_invocation_{endpoint_name}', f"/api/workflows/{{workflow_id}}/invocations/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( f'workflow_usage_{endpoint_name}', f"/api/workflows/{{workflow_id}}/usage/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, ) webapp.mapper.connect( f'invocation_{endpoint_name}', f"/api/invocations/{{invocation_id}}{endpoint_suffix}", controller='workflows', action=action, conditions=conditions, ) connect_invocation_endpoint('show', '', action='show_invocation') connect_invocation_endpoint('show_report', '/report', action='show_invocation_report') connect_invocation_endpoint('show_report_pdf', '/report.pdf', action='show_invocation_report_pdf') connect_invocation_endpoint('biocompute/download', '/biocompute/download', action='download_invocation_bco') connect_invocation_endpoint('biocompute', '/biocompute', action='export_invocation_bco') connect_invocation_endpoint('jobs_summary', '/jobs_summary', action='invocation_jobs_summary') connect_invocation_endpoint('step_jobs_summary', '/step_jobs_summary', action='invocation_step_jobs_summary') connect_invocation_endpoint('cancel', '', action='cancel_invocation', conditions=dict(method=['DELETE'])) connect_invocation_endpoint('show_step', '/steps/{step_id}', action='invocation_step') connect_invocation_endpoint('update_step', '/steps/{step_id}', action='update_invocation_step', conditions=dict(method=['PUT'])) # ============================ # ===== AUTHENTICATE API ===== # ============================ webapp.mapper.connect('api_key_retrieval', '/api/authenticate/baseauth/', controller='authenticate', action='get_api_key', conditions=dict(method=["GET"])) # ====================================== # ====== DISPLAY APPLICATIONS API ====== # ====================================== webapp.mapper.connect('index', '/api/display_applications', controller='display_applications', action='index', conditions=dict(method=["GET"])) webapp.mapper.connect('reload', '/api/display_applications/reload', controller='display_applications', action='reload', conditions=dict(method=["POST"])) # ===================== # ===== TOURS API ===== # ===================== webapp.mapper.connect('index', '/api/tours', controller='tours', action='index', conditions=dict(method=["GET"])) webapp.mapper.connect('show', '/api/tours/{tour_id}', controller='tours', action='show', conditions=dict(method=["GET"])) webapp.mapper.connect('update_tour', '/api/tours/{tour_id}', controller='tours', action='update_tour', conditions=dict(method=["POST"])) # ================================ # ===== USERS API ===== # ================================ webapp.mapper.connect('api_key', '/api/users/{id}/api_key', controller='users', action='api_key', conditions=dict(method=["POST"])) webapp.mapper.connect('api_key', '/api/users/{id}/api_key', controller='users', action='get_or_create_api_key', conditions=dict(method=["GET"])) webapp.mapper.connect('get_api_key', '/api/users/{id}/api_key/inputs', controller='users', action='get_api_key', conditions=dict(method=["GET"])) webapp.mapper.connect('set_api_key', '/api/users/{id}/api_key/inputs', controller='users', action='set_api_key', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_information', '/api/users/{id}/information/inputs', controller='users', action='get_information', conditions=dict(method=["GET"])) webapp.mapper.connect('set_information', '/api/users/{id}/information/inputs', controller='users', action='set_information', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_password', '/api/users/{id}/password/inputs', controller='users', action='get_password', conditions=dict(method=["GET"])) webapp.mapper.connect('set_password', '/api/users/{id}/password/inputs', controller='users', action='set_password', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_permissions', '/api/users/{id}/permissions/inputs', controller='users', action='get_permissions', conditions=dict(method=["GET"])) webapp.mapper.connect('set_permissions', '/api/users/{id}/permissions/inputs', controller='users', action='set_permissions', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_toolbox_filters', '/api/users/{id}/toolbox_filters/inputs', controller='users', action='get_toolbox_filters', conditions=dict(method=["GET"])) webapp.mapper.connect('set_toolbox_filters', '/api/users/{id}/toolbox_filters/inputs', controller='users', action='set_toolbox_filters', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_communication', '/api/users/{id}/communication/inputs', controller='users', action='get_communication', conditions=dict(method=["GET"])) webapp.mapper.connect('set_communication', '/api/users/{id}/communication/inputs', controller='users', action='set_communication', conditions=dict(method=["PUT"])) webapp.mapper.connect('get_custom_builds', '/api/users/{id}/custom_builds', controller='users', action='get_custom_builds', conditions=dict(method=["GET"])) webapp.mapper.connect('add_custom_builds', '/api/users/{id}/custom_builds/{key}', controller='users', action='add_custom_builds', conditions=dict(method=["PUT"])) webapp.mapper.connect('delete_custom_builds', '/api/users/{id}/custom_builds/{key}', controller='users', action='delete_custom_builds', conditions=dict(method=["DELETE"])) webapp.mapper.connect('set_favorite_tool', '/api/users/{id}/favorites/{object_type}', controller='users', action='set_favorite', conditions=dict(method=["PUT"])) webapp.mapper.connect('remove_favorite_tool', '/api/users/{id}/favorites/{object_type}/{object_id:.*?}', controller='users', action='remove_favorite', conditions=dict(method=["DELETE"])) # ======================== # ===== WEBHOOKS API ===== # ======================== webapp.mapper.connect('get_all_webhooks', '/api/webhooks', controller='webhooks', action='all_webhooks', conditions=dict(method=['GET'])) webapp.mapper.connect('get_webhook_data', '/api/webhooks/{webhook_id}/data', controller='webhooks', action='webhook_data', conditions=dict(method=['GET'])) # ==================== # ===== TAGS API ===== # ==================== webapp.mapper.connect('update_tags', '/api/tags', controller='tags', action='update', conditions=dict(method=['PUT'])) # ======================= # ===== LIBRARY API ===== # ======================= webapp.mapper.connect('update_library', '/api/libraries/{id}', controller='libraries', action='update', conditions=dict(method=["PATCH", "PUT"])) webapp.mapper.connect('show_library_permissions', '/api/libraries/{encoded_library_id}/permissions', controller='libraries', action='get_permissions', conditions=dict(method=["GET"])) # POST for legacy reasons, but this should be a PUT. webapp.mapper.connect('set_library_permissions', '/api/libraries/{encoded_library_id}/permissions', controller='libraries', action='set_permissions', conditions=dict(method=["POST", "PUT"])) webapp.mapper.connect('show_ld_item', '/api/libraries/datasets/{id}', controller='library_datasets', action='show', conditions=dict(method=["GET"])) webapp.mapper.connect('load_ld', '/api/libraries/datasets/', controller='library_datasets', action='load', conditions=dict(method=["POST"])) webapp.mapper.connect('show_version_of_ld_item', '/api/libraries/datasets/{encoded_dataset_id}/versions/{encoded_ldda_id}', controller='library_datasets', action='show_version', conditions=dict(method=["GET"])) webapp.mapper.connect('update_ld', '/api/libraries/datasets/{encoded_dataset_id}', controller='library_datasets', action='update', conditions=dict(method=["PATCH"])) webapp.mapper.connect('show_legitimate_ld_roles', '/api/libraries/datasets/{encoded_dataset_id}/permissions', controller='library_datasets', action='show_roles', conditions=dict(method=["GET"])) webapp.mapper.connect('update_ld_permissions', '/api/libraries/datasets/{encoded_dataset_id}/permissions', controller='library_datasets', action='update_permissions', conditions=dict(method=["POST"])) webapp.mapper.connect('delete_ld_item', '/api/libraries/datasets/{encoded_dataset_id}', controller='library_datasets', action='delete', conditions=dict(method=["DELETE"])) webapp.mapper.connect('download_ld_items', '/api/libraries/datasets/download/{archive_format}', controller='library_datasets', action='download', conditions=dict(method=["POST", "GET"])) webapp.mapper.resource_with_deleted('library', 'libraries', path_prefix='/api') webapp.mapper.resource('content', 'contents', controller='library_contents', name_prefix='library_', path_prefix='/api/libraries/{library_id}', parent_resources=dict(member_name='library', collection_name='libraries')) _add_item_extended_metadata_controller(webapp, name_prefix="library_dataset_", path_prefix='/api/libraries/{library_id}/contents/{library_content_id}') # ======================= # ===== FOLDERS API ===== # ======================= webapp.mapper.connect('add_history_datasets_to_library', '/api/folders/{encoded_folder_id}/contents', controller='folder_contents', action='create', conditions=dict(method=["POST"])) webapp.mapper.connect('create_folder', '/api/folders/{encoded_parent_folder_id}', controller='folders', action='create', conditions=dict(method=["POST"])) webapp.mapper.connect('delete_folder', '/api/folders/{encoded_folder_id}', controller='folders', action='delete', conditions=dict(method=["DELETE"])) webapp.mapper.connect('update_folder', '/api/folders/{encoded_folder_id}', controller='folders', action='update', conditions=dict(method=["PATCH", "PUT"])) webapp.mapper.resource('folder', 'folders', path_prefix='/api') webapp.mapper.connect('show_folder_permissions', '/api/folders/{encoded_folder_id}/permissions', controller='folders', action='get_permissions', conditions=dict(method=["GET"])) webapp.mapper.connect('set_folder_permissions', '/api/folders/{encoded_folder_id}/permissions', controller='folders', action='set_permissions', conditions=dict(method=["POST"])) webapp.mapper.resource('content', 'contents', controller='folder_contents', name_prefix='folder_', path_prefix='/api/folders/{folder_id}', parent_resources=dict(member_name='folder', collection_name='folders'), conditions=dict(method=["GET"])) webapp.mapper.resource('job', 'jobs', path_prefix='/api') webapp.mapper.connect('job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict(method=['POST'])) webapp.mapper.connect('job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict(method=['GET'])) webapp.mapper.connect('job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict(method=['GET'])) webapp.mapper.connect('build_for_rerun', '/api/jobs/{id}/build_for_rerun', controller='jobs', action='build_for_rerun', conditions=dict(method=['GET'])) webapp.mapper.connect('resume', '/api/jobs/{id}/resume', controller='jobs', action='resume', conditions=dict(method=['PUT'])) webapp.mapper.connect('job_error', '/api/jobs/{id}/error', controller='jobs', action='error', conditions=dict(method=['POST'])) webapp.mapper.connect('common_problems', '/api/jobs/{id}/common_problems', controller='jobs', action='common_problems', conditions=dict(method=['GET'])) # Job metrics and parameters by job id or dataset id (for slightly different accessibility checking) webapp.mapper.connect('metrics', '/api/jobs/{job_id}/metrics', controller='jobs', action='metrics', conditions=dict(method=['GET'])) webapp.mapper.connect('destination_params', '/api/jobs/{job_id}/destination_params', controller='jobs', action='destination_params', conditions=dict(method=['GET'])) webapp.mapper.connect('show_job_lock', '/api/job_lock', controller='jobs', action='show_job_lock', conditions=dict(method=['GET'])) webapp.mapper.connect('update_job_lock', '/api/job_lock', controller='jobs', action='update_job_lock', conditions=dict(method=['PUT'])) webapp.mapper.connect('dataset_metrics', '/api/datasets/{dataset_id}/metrics', controller='jobs', action='metrics', conditions=dict(method=['GET'])) webapp.mapper.connect('parameters_display', '/api/jobs/{job_id}/parameters_display', controller='jobs', action='parameters_display', conditions=dict(method=['GET'])) webapp.mapper.connect('dataset_parameters_display', '/api/datasets/{dataset_id}/parameters_display', controller='jobs', action='parameters_display', conditions=dict(method=['GET'])) # Job files controllers. Only for consumption by remote job runners. webapp.mapper.resource('file', 'files', controller="job_files", name_prefix="job_", path_prefix='/api/jobs/{job_id}', parent_resources=dict(member_name="job", collection_name="jobs")) webapp.mapper.resource('port', 'ports', controller="job_ports", name_prefix="job_", path_prefix='/api/jobs/{job_id}', parent_resources=dict(member_name="job", collection_name="jobs")) _add_item_extended_metadata_controller(webapp, name_prefix="history_dataset_", path_prefix='/api/histories/{history_id}/contents/{history_content_id}') # ==================== # ===== TOOLSHED ===== # ==================== # Handle displaying tool help images and README file images contained in repositories installed from the tool shed. webapp.add_route('/admin_toolshed/static/images/{repository_id}/{image_file:.+?}', controller='admin_toolshed', action='display_image_in_repository', repository_id=None, image_file=None) # Do the same but without a repository id webapp.add_route('/shed_tool_static/{shed}/{owner}/{repo}/{tool}/{version}/{image_file:.+?}', controller='shed_tool_static', action='index', shed=None, owner=None, repo=None, tool=None, version=None, image_file=None) webapp.mapper.connect('tool_shed_contents', '/api/tool_shed/contents', controller='toolshed', action='show', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_shed_category_contents', '/api/tool_shed/category', controller='toolshed', action='category', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_shed_repository_details', '/api/tool_shed/repository', controller='toolshed', action='repository', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_sheds', '/api/tool_shed', controller='toolshed', action='index', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_shed_search', '/api/tool_shed/search', controller='toolshed', action='search', conditions=dict(method=["GET", "POST"])) webapp.mapper.connect('tool_shed_request', '/api/tool_shed/request', controller='toolshed', action='request', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_shed_status', '/api/tool_shed/status', controller='toolshed', action='status', conditions=dict(method=["GET", "POST"])) webapp.mapper.connect('shed_tool_json', '/api/tool_shed/tool_json', controller='toolshed', action='tool_json', conditions=dict(method=["GET"])) webapp.mapper.connect('tool_shed_repository', '/api/tool_shed_repositories/:id/status', controller='tool_shed_repositories', action='status', conditions=dict(method=["GET"])) webapp.mapper.connect('install_repository', '/api/tool_shed_repositories', controller='tool_shed_repositories', action='install_repository_revision', conditions=dict(method=['POST'])) webapp.mapper.connect('install_repository', '/api/tool_shed_repositories/install', controller='tool_shed_repositories', action='install', conditions=dict(method=['POST'])) webapp.mapper.connect('check_for_updates', '/api/tool_shed_repositories/check_for_updates', controller='tool_shed_repositories', action='check_for_updates', conditions=dict(method=['GET'])) webapp.mapper.connect('tool_shed_repository', '/api/tool_shed_repositories', controller='tool_shed_repositories', action='uninstall_repository', conditions=dict(method=["DELETE"])) webapp.mapper.connect('tool_shed_repository', '/api/tool_shed_repositories/{id}', controller='tool_shed_repositories', action='uninstall_repository', conditions=dict(method=["DELETE"])) webapp.mapper.connect('reset_metadata_on_selected_installed_repositories', '/api/tool_shed_repositories/reset_metadata_on_selected_installed_repositories', controller='tool_shed_repositories', action='reset_metadata_on_selected_installed_repositories', conditions=dict(method=['POST'])) # Galaxy API for tool shed features. webapp.mapper.resource('tool_shed_repository', 'tool_shed_repositories', member={'repair_repository_revision': 'POST', 'exported_workflows': 'GET', 'import_workflow': 'POST', 'import_workflows': 'POST'}, collection={'get_latest_installable_revision': 'POST', 'reset_metadata_on_installed_repositories': 'POST'}, controller='tool_shed_repositories', name_prefix='tool_shed_repository_', path_prefix='/api', new={'install_repository_revision': 'POST'}, parent_resources=dict(member_name='tool_shed_repository', collection_name='tool_shed_repositories')) # ==== Trace/Metrics Logger # Connect logger from app if app.trace_logger: webapp.trace_logger = app.trace_logger # metrics logging API # webapp.mapper.connect( "index", "/api/metrics", # controller="metrics", action="index", conditions=dict( method=["GET"] ) ) # webapp.mapper.connect( "show", "/api/metrics/{id}", # controller="metrics", action="show", conditions=dict( method=["GET"] ) ) webapp.mapper.connect("create", "/api/metrics", controller="metrics", action="create", conditions=dict(method=["POST"]))
def _add_item_tags_controller(webapp, name_prefix, path_prefix, **kwd): # Not just using map.resources because actions should be based on name not id controller = f"{name_prefix}tags" name = f"{name_prefix}tag" path = f"{path_prefix}/tags" map = webapp.mapper # Allow view items' tags. map.connect(name, path, controller=controller, action="index", conditions=dict(method=["GET"])) # Allow remove tag from item map.connect(f"{name}_delete", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="delete", conditions=dict(method=["DELETE"])) # Allow create a new tag with from name map.connect(f"{name}_create", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="create", conditions=dict(method=["POST"])) # Allow update tag value map.connect(f"{name}_update", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="update", conditions=dict(method=["PUT"])) # Allow show tag by name map.connect(f"{name}_show", "%s/tags/{tag_name}" % path_prefix, controller=controller, action="show", conditions=dict(method=["GET"])) def _add_item_extended_metadata_controller(webapp, name_prefix, path_prefix, **kwd): controller = f"{name_prefix}extended_metadata" name = f"{name_prefix}extended_metadata" webapp.mapper.resource(name, "extended_metadata", path_prefix=path_prefix, controller=controller) def _add_item_annotation_controller(webapp, name_prefix, path_prefix, **kwd): controller = f"{name_prefix}annotations" name = f"{name_prefix}annotation" webapp.mapper.resource(name, "annotation", path_prefix=path_prefix, controller=controller) def _add_item_provenance_controller(webapp, name_prefix, path_prefix, **kwd): controller = f"{name_prefix}provenance" name = f"{name_prefix}provenance" webapp.mapper.resource(name, "provenance", path_prefix=path_prefix, controller=controller)
[docs]def wrap_in_middleware(app, global_conf, application_stack, **local_conf): """ Based on the configuration wrap `app` in a set of common and useful middleware. """ webapp = app stack = application_stack # Merge the global and local configurations conf = global_conf.copy() conf.update(local_conf) debug = asbool(conf.get('debug', False)) # First put into place httpexceptions, which must be most closely # wrapped around the application (it can interact poorly with # other middleware): app = wrap_if_allowed(app, stack, httpexceptions.make_middleware, name='paste.httpexceptions', args=(conf,)) # Statsd request timing and profiling statsd_host = conf.get('statsd_host', None) if statsd_host: from galaxy.web.framework.middleware.statsd import StatsdMiddleware app = wrap_if_allowed(app, stack, StatsdMiddleware, args=(statsd_host, conf.get('statsd_port', 8125), conf.get('statsd_prefix', 'galaxy'), conf.get('statsd_influxdb', False), conf.get('statsd_mock_calls', False))) log.info("Enabling 'statsd' middleware") # If we're using remote_user authentication, add middleware that # protects Galaxy from improperly configured authentication in the # upstream server single_user = conf.get('single_user', None) use_remote_user = asbool(conf.get('use_remote_user', False)) or single_user if use_remote_user: from galaxy.web.framework.middleware.remoteuser import RemoteUser app = wrap_if_allowed(app, stack, RemoteUser, kwargs=dict( maildomain=conf.get('remote_user_maildomain', None), display_servers=util.listify(conf.get('display_servers', '')), single_user=single_user, admin_users=conf.get('admin_users', '').split(','), remote_user_header=conf.get('remote_user_header', 'HTTP_REMOTE_USER'), remote_user_secret_header=conf.get('remote_user_secret', None), normalize_remote_user_email=conf.get('normalize_remote_user_email', False))) # The recursive middleware allows for including requests in other # requests or forwarding of requests, all on the server side. if asbool(conf.get('use_recursive', True)): from paste import recursive app = wrap_if_allowed(app, stack, recursive.RecursiveMiddleware, args=(conf,)) # If sentry logging is enabled, log here before propogating up to # the error middleware sentry_dsn = conf.get('sentry_dsn', None) if sentry_dsn: from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware app = wrap_if_allowed(app, stack, SentryWsgiMiddleware) # Various debug middleware that can only be turned on if the debug # flag is set, either because they are insecure or greatly hurt # performance if debug: # Middleware to check for WSGI compliance if asbool(conf.get('use_lint', False)): from paste import lint app = wrap_if_allowed(app, stack, lint.make_middleware, name='paste.lint', args=(conf,)) # Middleware to run the python profiler on each request if asbool(conf.get('use_profile', False)): from paste.debug import profile app = wrap_if_allowed(app, stack, profile.ProfileMiddleware, args=(conf,)) # Error middleware app = wrap_if_allowed(app, stack, ErrorMiddleware, args=(conf,)) # Transaction logging (apache access.log style) if asbool(conf.get('use_translogger', True)): from galaxy.web.framework.middleware.translogger import TransLogger app = wrap_if_allowed(app, stack, TransLogger) # TUS upload middleware app = wrap_if_allowed(app, stack, TusMiddleware, kwargs={ 'upload_path': urljoin(f"{application_stack.config.galaxy_url_prefix}/", 'api/upload/resumable_upload'), 'tmp_dir': application_stack.config.tus_upload_store or application_stack.config.new_file_path, 'max_size': application_stack.config.maximum_upload_file_size }) # X-Forwarded-Host handling app = wrap_if_allowed(app, stack, XForwardedHostMiddleware) # Request ID middleware app = wrap_if_allowed(app, stack, RequestIDMiddleware) # api batch call processing middleware app = wrap_if_allowed(app, stack, BatchMiddleware, args=(webapp, {})) if asbool(conf.get('enable_per_request_sql_debugging', False)): from galaxy.web.framework.middleware.sqldebug import SQLDebugMiddleware app = wrap_if_allowed(app, stack, SQLDebugMiddleware, args=(webapp, {})) return app