def main(): import zope.app.wsgi zope_conf = os.path.join(here, 'zope.conf') zope = zope.app.wsgi.getWSGIApplication(zope_conf) from repoze.who.middleware import PluggableAuthenticationMiddleware from repoze.who.config import WhoConfig parser = WhoConfig(here) parser.parse(open(os.path.join(here, 'who.ini'))) log_stream = sys.stdout log_level = logging.DEBUG app = PluggableAuthenticationMiddleware( zope, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream, log_level, ) from paste import httpserver httpserver.serve(app, host='0.0.0.0', port='9876')
def make_middleware_with_config(app, global_conf, config_file, log_file=None, log_level=None, skip_authentication=False): """ Proxy :func:`repoze.who.config.make_middleware_with_config` to skip authentication when required. If ``skip_authentication`` evaluates to ``True``, then the returned middleware will be an instance of :class:`AuthenticationForgerMiddleware`. """ if not asbool(skip_authentication): # We must not replace the middleware return mk_mw_cfg(app, global_conf, config_file, log_file, log_level) # We must replace the middleware: parser = WhoConfig(global_conf['here']) parser.parse(open(config_file)) return AuthenticationForgerMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, remote_user_key=parser.remote_user_key, )
def add_auth_middleware(self, app, skip_authentication): """ Configure authentication and authorization. :param app: The TG2 application. :param skip_authentication: Should authentication be skipped if explicitly requested? (used by repoze.who-testutil) :type skip_authentication: bool """ if asbool(config.get('loom.profile', False)): log.debug('Setting up profiling middleware') app = AccumulatingProfileMiddleware( app, log_filename='/home/volkmuth/profile/app.log', cachegrind_filename='/home/volkmuth/profile/cachegrind.out.app', discard_first_request=False, flush_at_shutdown=True, path='/__profile__') parser = WhoConfig(config['here']) parser.parse(open(config.get('who.config_file', 'who.ini'))) app = make_middleware(skip_authentication, app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, remote_user_key=parser.remote_user_key) #app = make_who_with_config(app, config, config.get('who.config_file','who.ini'), # config.get('who.log_file','stdout'), config.get('who.log_level','debug'), # skip_authentication # ) app = ModuleMiddleware(app) return app
def _mk_mw_cfg(app, global_conf, config_file, log_file=None, log_level=None): """ Inspiré par C{repoze.who.config:make_middleware_with_config}. """ parser = WhoConfig(global_conf['here']) parser.parse(open(config_file)) log_stream = None if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: log_stream = open(log_file, 'wb') if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return VigiloAuthMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream, log_level, parser.remote_user_key, )
def api_factory_from_settings(settings, prefix="who."): """Create a new repoze.who APIFactory from the deployment settings. This function uses the paster deployment settings to create a repoze.who APIFactory object. Settings starting with "who." are collected and formatted into an ini-file which can be read by the repoze.who config parser, and the resulting APIFactory object is returned. """ # If we have already built and cached one, just use it directly. cache_key = prefix + "api_factory" if cache_key in settings: return settings[cache_key] # Grab out all the settings keys that start with our prefix. who_settings = {} for name, value in settings.iteritems(): if not name.startswith(prefix): continue who_settings[name[len(prefix):]] = value # Construct a who.ini config file in memory. # First, read in any config file specified in the settings. who_ini_lines = [] if "config_file" in who_settings: with open(who_settings["config_file"], "r") as f: who_ini_lines.extend(ln.strip() for ln in f) # Format any dotted setting names into an ini-file section. # For example, a settings file line like: # who.identifiers.plugins = blah # Will become an ini-file entry like: # [identifiers] # plugins = blah for name, value in who_settings.iteritems(): if isinstance(value, (list, tuple)): value = " ".join(value) else: value = str(value) try: section, var = name.rsplit(".", 1) except ValueError: pass else: who_ini_lines.append("[%s]" % (section.replace(".", ":"),)) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig(who_settings.get("here", "")) parser.parse("\n".join(who_ini_lines)) api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Cache it so we don't have to repeat all that work. settings[cache_key] = api_factory return api_factory
def _make_api_factory(self): parser = WhoConfig("") parser.parse(WHO_CONFIG) return APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider)
def api_factory_from_settings(settings, prefix="who."): """Create a new repoze.who APIFactory from the deployment settings. This function uses the paster deployment settings to create a repoze.who APIFactory object. Settings starting with "who." are collected and formatted into an ini-file which can be read by the repoze.who config parser, and the resulting APIFactory object is returned. """ # If we have already built and cached one, just use it directly. cache_key = prefix + "api_factory" if cache_key in settings: return settings[cache_key] # Grab out all the settings keys that start with our prefix. who_settings = {} for name, value in settings.iteritems(): if not name.startswith(prefix): continue who_settings[name[len(prefix):]] = value # Construct a who.ini config file in memory. # First, read in any config file specified in the settings. who_ini_lines = [] if "config_file" in who_settings: with open(who_settings["config_file"], "r") as f: who_ini_lines.extend(ln.strip() for ln in f) # Format any dotted setting names into an ini-file section. # For example, a settings file line like: # who.identifiers.plugins = blah # Will become an ini-file entry like: # [identifiers] # plugins = blah for name, value in who_settings.iteritems(): if isinstance(value, (list, tuple)): value = " ".join(value) else: value = str(value) try: section, var = name.rsplit(".", 1) except ValueError: pass else: who_ini_lines.append("[%s]" % (section.replace(".", ":"), )) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig(who_settings.get("here", "")) parser.parse("\n".join(who_ini_lines)) api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Cache it so we don't have to repeat all that work. settings[cache_key] = api_factory return api_factory
def _wsgi_app(self): parser = WhoConfig("") parser.parse(WHO_CONFIG) def application(environ, start_response): start_response("401 Unauthorized", []) return [""] return PluggableAuthenticationMiddleware( application, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider)
def _configure_api_factory(): global api_factory if api_factory is None: config = WhoConfig(here='/tmp') # XXX config file location config.parse(WHO_CONFIG) api_factory = APIFactory(identifiers=config.identifiers, authenticators=config.authenticators, challengers=config.challengers, mdproviders=config.mdproviders, request_classifier=config.request_classifier, challenge_decider=config.challenge_decider, ) return api_factory
def _wsgi_app(self): parser = WhoConfig("") parser.parse(WHO_CONFIG) def application(environ, start_response): start_response("401 Unauthorized", []) return [""] return PluggableAuthenticationMiddleware(application, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider)
def make_middleware_with_config(app, global_conf, config_file, who_config_file='', log_file=None, log_level=None): """Override repoze.what.plugins.config:make_middleware_with_config Allows us to call a Baruwa modified authentication stark """ if not who_config_file: who_config_file = config_file who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(who_config_file)) what_parser = WhatConfig(global_conf['here']) what_parser.parse(open(config_file)) log_stream = None if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: try: log_stream = open(log_file, 'wb') except IOError: log_stream = None if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return setup_auth( app, group_adapters=what_parser.group_adapters, permission_adapters=what_parser.permission_adapters, identifiers=who_parser.identifiers, authenticators=who_parser.authenticators, challengers=who_parser.challengers, mdproviders=who_parser.mdproviders, classifier=who_parser.request_classifier, challenge_decider=who_parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=who_parser.remote_user_key, )
def make_middleware_with_config(app, global_conf, config_file, who_config_file="", log_file=None, log_level=None): """Override repoze.what.plugins.config:make_middleware_with_config Allows us to call a Baruwa modified authentication stark """ if not who_config_file: who_config_file = config_file who_parser = WhoConfig(global_conf["here"]) who_parser.parse(open(who_config_file)) what_parser = WhatConfig(global_conf["here"]) what_parser.parse(open(config_file)) log_stream = None if log_file is not None: if log_file.lower() == "stdout": log_stream = sys.stdout else: try: log_stream = open(log_file, "wb") except IOError: log_stream = None if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return setup_auth( app, group_adapters=what_parser.group_adapters, permission_adapters=what_parser.permission_adapters, identifiers=who_parser.identifiers, authenticators=who_parser.authenticators, challengers=who_parser.challengers, mdproviders=who_parser.mdproviders, classifier=who_parser.request_classifier, challenge_decider=who_parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=who_parser.remote_user_key, )
def make_middleware_with_config(app, global_conf, log_file=None): """Override repoze.what.plugins.config:make_middleware_with_config Allows us to call a Baruwa modified authentication stark and use single configuration file """ who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(global_conf['__file__'])) what_parser = WhatConfig(global_conf['here']) what_parser.parse(open(global_conf['__file__'])) log_level = 'DEBUG' if asbool(global_conf['debug']) else 'INFO' log_stream = None if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: try: log_stream = open(log_file, 'wb') except IOError: log_stream = None if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return setup_auth(app, group_adapters=what_parser.group_adapters, permission_adapters=what_parser.permission_adapters, identifiers=who_parser.identifiers, authenticators=who_parser.authenticators, challengers=who_parser.challengers, mdproviders=who_parser.mdproviders, classifier=who_parser.request_classifier, challenge_decider=who_parser.challenge_decider, log_stream = log_stream, log_level = log_level, remote_user_key = who_parser.remote_user_key, )
def make_who_middleware(app, config): who_config = pkg_resources.resource_stream(__name__, 'who.ini').read() who_config = who_config % dict( cookie=config['who_cookie'], secret=config['who_secret'], realm=config.get('who_realm', config['system_name'])) parser = WhoConfig(config['here']) parser.parse(who_config) return PluggableAuthenticationMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, None, # log_stream logging.INFO, parser.remote_user_key, )
def __init__(self, config): # Load the auth backend if specified. # There may not be one configured if repoze.who is going to look # elsewhere for credentials, e.g. in a htpasswd database. self.config = config try: self.backend = load_and_configure(self.config, 'auth') except KeyError: self.backend = None self.logger = CLIENT_HOLDER.default_client # Extract who-related settings from the config or from our defaults. # the configured authentication backend. who_settings = self._get_who_settings(self.config) # Build up a who.ini config file in memory. # Any settings of the form "A.B.C = X" get translated into # a config file section like "[A:B]\nC = X" who_ini_lines = [] for key, value in who_settings.iteritems(): try: section, var = key.rsplit(".", 1) except ValueError: pass else: section = section.replace(".", ":") who_ini_lines.append("[%s]" % (section,)) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig("") parser.parse("\n".join(who_ini_lines)) self._api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Give all backend plugins access to the config. self._configure_backend_plugins(self._api_factory)
def make_middleware_with_config(app, global_conf, config_file, who_config_file = '', log_file=None, log_level=None): if not who_config_file: who_config_file = config_file who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(who_config_file)) what_parser = WhatConfig(global_conf['here']) what_parser.parse(open(config_file)) log_stream = None if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: log_stream = open(log_file, 'wb') if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return setup_auth(app, group_adapters=what_parser.group_adapters, permission_adapters=what_parser.permission_adapters, identifiers=who_parser.identifiers, authenticators=who_parser.authenticators, challengers=who_parser.challengers, mdproviders=who_parser.mdproviders, classifier=who_parser.request_classifier, challenge_decider=who_parser.challenge_decider, log_stream = log_stream, log_level = log_level, remote_user_key = who_parser.remote_user_key, )
def __init__(self, config): # Load the auth backend if specified. # There may not be one configured if repoze.who is going to look # elsewhere for credentials, e.g. in a htpasswd database. self.config = config try: self.backend = load_and_configure(self.config, 'auth') except KeyError: self.backend = None self.logger = CLIENT_HOLDER.default_client # Extract who-related settings from the config or from our defaults. # the configured authentication backend. who_settings = self._get_who_settings(self.config) # Build up a who.ini config file in memory. # Any settings of the form "A.B.C = X" get translated into # a config file section like "[A:B]\nC = X" who_ini_lines = [] for key, value in who_settings.iteritems(): try: section, var = key.rsplit(".", 1) except ValueError: pass else: section = section.replace(".", ":") who_ini_lines.append("[%s]" % (section, )) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig("") parser.parse("\n".join(who_ini_lines)) self._api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Give all backend plugins access to the config. self._configure_backend_plugins(self._api_factory)
def make_flask_stack(conf, **app_conf): """ This has to pass the flask app through all the same middleware that Pylons used """ root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) debug = asbool(conf.get('debug', conf.get('DEBUG', False))) testing = asbool(app_conf.get('testing', app_conf.get('TESTING', False))) app = flask_app = CKANFlask(__name__) app.debug = debug app.testing = testing app.template_folder = os.path.join(root, 'templates') app.app_ctx_globals_class = CKAN_AppCtxGlobals app.url_rule_class = CKAN_Rule app.jinja_options = jinja_extensions.get_jinja_env_options() # Update Flask config with the CKAN values. We use the common config # object as values might have been modified on `load_environment` if config: app.config.update(config) else: app.config.update(conf) app.config.update(app_conf) # Do all the Flask-specific stuff before adding other middlewares # Secret key needed for flask-debug-toolbar and sessions if not app.config.get('SECRET_KEY'): app.config['SECRET_KEY'] = config.get('beaker.session.secret') if not app.config.get('SECRET_KEY'): raise RuntimeError(u'You must provide a value for the secret key' ' with the SECRET_KEY config option') if debug: from flask_debugtoolbar import DebugToolbarExtension app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False DebugToolbarExtension(app) # Use Beaker as the Flask session interface class BeakerSessionInterface(SessionInterface): def open_session(self, app, request): if 'beaker.session' in request.environ: return request.environ['beaker.session'] def save_session(self, app, session, response): session.save() namespace = 'beaker.session.' session_opts = dict([(k.replace('beaker.', ''), v) for k, v in config.iteritems() if k.startswith(namespace)]) if (not session_opts.get('session.data_dir') and session_opts.get('session.type', 'file') == 'file'): cache_dir = app_conf.get('cache_dir') or app_conf.get('cache.dir') session_opts['session.data_dir'] = '{data_dir}/sessions'.format( data_dir=cache_dir) app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() # Add Jinja2 extensions and filters app.jinja_env.filters['empty_and_escape'] = \ jinja_extensions.empty_and_escape # Common handlers for all requests app.before_request(ckan_before_request) app.after_request(ckan_after_request) # Template context processors app.context_processor(helper_functions) app.context_processor(c_object) @app.context_processor def ungettext_alias(): u''' Provide `ungettext` as an alias of `ngettext` for backwards compatibility ''' return dict(ungettext=ungettext) # Babel pairs = [(os.path.join(root, u'i18n'), 'ckan')] + [ (p.i18n_directory(), p.i18n_domain()) for p in PluginImplementations(ITranslation) ] i18n_dirs, i18n_domains = zip(*pairs) app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = ';'.join(i18n_dirs) app.config[u'BABEL_DOMAIN'] = 'ckan' app.config[u'BABEL_MULTIPLE_DOMAINS'] = ';'.join(i18n_domains) babel = CKANBabel(app) babel.localeselector(get_locale) @app.route('/hello', methods=['GET']) def hello_world(): return 'Hello World, this is served by Flask' @app.route('/hello', methods=['POST']) def hello_world_post(): return 'Hello World, this was posted to Flask' # Auto-register all blueprints defined in the `views` folder _register_core_blueprints(app) _register_error_handler(app) # Set up each IBlueprint extension as a Flask Blueprint for plugin in PluginImplementations(IBlueprint): if hasattr(plugin, 'get_blueprint'): plugin_blueprints = plugin.get_blueprint() if not isinstance(plugin_blueprints, list): plugin_blueprints = [plugin_blueprints] for blueprint in plugin_blueprints: app.register_extension_blueprint(blueprint) lib_plugins.register_package_blueprints(app) lib_plugins.register_group_blueprints(app) # Set flask routes in named_routes for rule in app.url_map.iter_rules(): if '.' not in rule.endpoint: continue controller, action = rule.endpoint.split('.') needed = list(rule.arguments - set(rule.defaults or {})) route = { rule.endpoint: { 'action': action, 'controller': controller, 'highlight_actions': action, 'needed': needed } } config['routes.named_routes'].update(route) # Start other middleware for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Fanstatic fanstatic_enable_rollup = asbool(app_conf.get('fanstatic_enable_rollup', False)) if debug: fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, 'rollup': fanstatic_enable_rollup, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, 'rollup': fanstatic_enable_rollup, } root_path = config.get('ckan.root_path', None) if root_path: root_path = re.sub('/{{LANG}}', '', root_path) fanstatic_config['base_url'] = root_path app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Update the main CKAN config object with the Flask specific keys # that were set here or autogenerated flask_config_keys = set(flask_app.config.keys()) - set(config.keys()) for key in flask_config_keys: config[key] = flask_app.config[key] # Add a reference to the actual Flask app so it's easier to access app._wsgi_app = flask_app return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age)) app = Cascade(extra_static_parsers + static_parsers) return app
def make_flask_stack(conf, **app_conf): """ This has to pass the flask app through all the same middleware that Pylons used """ root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) debug = asbool(conf.get('debug', conf.get('DEBUG', False))) testing = asbool(app_conf.get('testing', app_conf.get('TESTING', False))) app = flask_app = CKANFlask(__name__) app.debug = debug app.testing = testing app.template_folder = os.path.join(root, 'templates') app.app_ctx_globals_class = CKAN_AppCtxGlobals app.url_rule_class = CKAN_Rule app.jinja_options = jinja_extensions.get_jinja_env_options() # Update Flask config with the CKAN values. We use the common config # object as values might have been modified on `load_environment` if config: app.config.update(config) else: app.config.update(conf) app.config.update(app_conf) # Do all the Flask-specific stuff before adding other middlewares # Secret key needed for flask-debug-toolbar and sessions if not app.config.get('SECRET_KEY'): app.config['SECRET_KEY'] = config.get('beaker.session.secret') if not app.config.get('SECRET_KEY'): raise RuntimeError(u'You must provide a value for the secret key' ' with the SECRET_KEY config option') if debug: from flask_debugtoolbar import DebugToolbarExtension app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False DebugToolbarExtension(app) # Use Beaker as the Flask session interface class BeakerSessionInterface(SessionInterface): def open_session(self, app, request): if 'beaker.session' in request.environ: return request.environ['beaker.session'] def save_session(self, app, session, response): session.save() namespace = 'beaker.session.' session_opts = dict([(k.replace('beaker.', ''), v) for k, v in config.iteritems() if k.startswith(namespace)]) if (not session_opts.get('session.data_dir') and session_opts.get('session.type', 'file') == 'file'): cache_dir = app_conf.get('cache_dir') or app_conf.get('cache.dir') session_opts['session.data_dir'] = '{data_dir}/sessions'.format( data_dir=cache_dir) app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() # Add Jinja2 extensions and filters app.jinja_env.filters['empty_and_escape'] = \ jinja_extensions.empty_and_escape # Common handlers for all requests app.before_request(ckan_before_request) app.after_request(ckan_after_request) # Template context processors app.context_processor(helper_functions) app.context_processor(c_object) @app.context_processor def ungettext_alias(): u''' Provide `ungettext` as an alias of `ngettext` for backwards compatibility ''' return dict(ungettext=ungettext) # Babel pairs = [(os.path.join(root, u'i18n'), 'ckan') ] + [(p.i18n_directory(), p.i18n_domain()) for p in PluginImplementations(ITranslation)] i18n_dirs, i18n_domains = zip(*pairs) app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = ';'.join(i18n_dirs) app.config[u'BABEL_DOMAIN'] = 'ckan' app.config[u'BABEL_MULTIPLE_DOMAINS'] = ';'.join(i18n_domains) babel = CKANBabel(app) babel.localeselector(get_locale) @app.route('/hello', methods=['GET']) def hello_world(): return 'Hello World, this is served by Flask' @app.route('/hello', methods=['POST']) def hello_world_post(): return 'Hello World, this was posted to Flask' # Auto-register all blueprints defined in the `views` folder _register_core_blueprints(app) _register_error_handler(app) # Set up each IBlueprint extension as a Flask Blueprint for plugin in PluginImplementations(IBlueprint): if hasattr(plugin, 'get_blueprint'): app.register_extension_blueprint(plugin.get_blueprint()) lib_plugins.register_group_plugins(app) lib_plugins.register_package_plugins(app) # Set flask routes in named_routes for rule in app.url_map.iter_rules(): if '.' not in rule.endpoint: continue controller, action = rule.endpoint.split('.') needed = list(rule.arguments - set(rule.defaults or {})) route = { rule.endpoint: { 'action': action, 'controller': controller, 'highlight_actions': action, 'needed': needed } } config['routes.named_routes'].update(route) # Start other middleware for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Fanstatic if debug: fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } root_path = config.get('ckan.root_path', None) if root_path: root_path = re.sub('/{{LANG}}', '', root_path) fanstatic_config['base_url'] = root_path app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.'.format( plugin.__class__.__name__)) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key) # Update the main CKAN config object with the Flask specific keys # that were set here or autogenerated flask_config_keys = set(flask_app.config.keys()) - set(config.keys()) for key in flask_config_keys: config[key] = flask_app.config[key] # Add a reference to the actual Flask app so it's easier to access app._wsgi_app = flask_app return app
def make_app(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(conf, app_conf) # The Pylons WSGI app app = PylonsApp() # set pylons globals app_globals.reset() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin # Monkey patches for repoze.who.openid # Fixes #1659 - enable log-out when CKAN mounted at non-root URL from ckan.lib import repoze_patch OpenIdIdentificationPlugin.identify = repoze_patch.identify OpenIdIdentificationPlugin.redirect_to_logged_in = repoze_patch.redirect_to_logged_in OpenIdIdentificationPlugin._redirect_to_loginform = repoze_patch._redirect_to_loginform OpenIdIdentificationPlugin.challenge = repoze_patch.challenge who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware(app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) app = I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers + static_parsers) # Page cache if asbool(config.get('ckan.page_cache_enabled')): app = PageCacheMiddleware(app, config) # Tracking if asbool(config.get('ckan.tracking_enabled', 'false')): app = TrackingMiddleware(app, config) return app
def make_flask_stack(conf): """ This has to pass the flask app through all the same middleware that Pylons used """ root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) debug = asbool(conf.get('debug', conf.get('DEBUG', False))) testing = asbool(conf.get('testing', conf.get('TESTING', False))) app = flask_app = CKANFlask(__name__, static_url_path='') # Register storage for accessing group images, site logo, etc. storage_folder = [] storage = uploader.get_storage_path() if storage: storage_folder = [os.path.join(storage, 'storage')] # Static files folders (core and extensions) public_folder = config.get(u'ckan.base_public_folder') app.static_folder = config.get( 'extra_public_paths', '' ).split(',') + [os.path.join(root, public_folder)] + storage_folder app.jinja_options = jinja_extensions.get_jinja_env_options() app.jinja_env.policies['ext.i18n.trimmed'] = True app.debug = debug app.testing = testing app.template_folder = os.path.join(root, 'templates') app.app_ctx_globals_class = CKAN_AppCtxGlobals app.url_rule_class = CKAN_Rule # Update Flask config with the CKAN values. We use the common config # object as values might have been modified on `load_environment` if config: app.config.update(config) else: app.config.update(conf) # Do all the Flask-specific stuff before adding other middlewares # Secret key needed for flask-debug-toolbar and sessions if not app.config.get('SECRET_KEY'): app.config['SECRET_KEY'] = config.get('beaker.session.secret') if not app.config.get('SECRET_KEY'): raise RuntimeError(u'You must provide a value for the secret key' ' with the SECRET_KEY config option') root_path = config.get('ckan.root_path', None) if debug: from flask_debugtoolbar import DebugToolbarExtension app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False debug_ext = DebugToolbarExtension() # register path that includes `ckan.site_root` before # initializing debug app. In such a way, our route receives # higher precedence. # TODO: After removal of Pylons code, switch to # `APPLICATION_ROOT` config value for flask application. Right # now it's a bad option because we are handling both pylons # and flask urls inside helpers and splitting this logic will # bring us tons of headache. if root_path: app.add_url_rule( root_path.replace('{{LANG}}', '').rstrip('/') + '/_debug_toolbar/static/<path:filename>', '_debug_toolbar.static', debug_ext.send_static_file ) debug_ext.init_app(app) from werkzeug.debug import DebuggedApplication app.wsgi_app = DebuggedApplication(app.wsgi_app, True) # Use Beaker as the Flask session interface class BeakerSessionInterface(SessionInterface): def open_session(self, app, request): if 'beaker.session' in request.environ: return request.environ['beaker.session'] def save_session(self, app, session, response): session.save() namespace = 'beaker.session.' session_opts = {k.replace('beaker.', ''): v for k, v in six.iteritems(config) if k.startswith(namespace)} if (not session_opts.get('session.data_dir') and session_opts.get('session.type', 'file') == 'file'): cache_dir = conf.get('cache_dir') or conf.get('cache.dir') session_opts['session.data_dir'] = '{data_dir}/sessions'.format( data_dir=cache_dir) app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() # Add Jinja2 extensions and filters app.jinja_env.filters['empty_and_escape'] = \ jinja_extensions.empty_and_escape # Common handlers for all requests app.before_request(ckan_before_request) app.after_request(ckan_after_request) # Template context processors app.context_processor(helper_functions) app.context_processor(c_object) @app.context_processor def ungettext_alias(): u''' Provide `ungettext` as an alias of `ngettext` for backwards compatibility ''' return dict(ungettext=ungettext) # Babel _ckan_i18n_dir = i18n.get_ckan_i18n_dir() pairs = [ (_ckan_i18n_dir, u'ckan') ] + [ (p.i18n_directory(), p.i18n_domain()) for p in PluginImplementations(ITranslation) ] i18n_dirs, i18n_domains = zip(*pairs) app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = ';'.join(i18n_dirs) app.config[u'BABEL_DOMAIN'] = 'ckan' app.config[u'BABEL_MULTIPLE_DOMAINS'] = ';'.join(i18n_domains) babel = CKANBabel(app) babel.localeselector(get_locale) # WebAssets _setup_webassets(app) # Auto-register all blueprints defined in the `views` folder _register_core_blueprints(app) _register_error_handler(app) # Set up each IBlueprint extension as a Flask Blueprint for plugin in PluginImplementations(IBlueprint): if hasattr(plugin, 'get_blueprint'): plugin_blueprints = plugin.get_blueprint() if not isinstance(plugin_blueprints, list): plugin_blueprints = [plugin_blueprints] for blueprint in plugin_blueprints: app.register_extension_blueprint(blueprint) lib_plugins.register_package_blueprints(app) lib_plugins.register_group_blueprints(app) # Set flask routes in named_routes # TODO: refactor whatever helper is using this to not do it if 'routes.named_routes' not in config: config['routes.named_routes'] = {} for rule in app.url_map.iter_rules(): if '.' not in rule.endpoint: continue controller, action = rule.endpoint.split('.') needed = list(rule.arguments - set(rule.defaults or {})) route = { rule.endpoint: { 'action': action, 'controller': controller, 'highlight_actions': action, 'needed': needed } } config['routes.named_routes'].update(route) # Start other middleware for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(conf['who.config_file'])) app = PluggableAuthenticationMiddleware( RepozeAdapterMiddleware(app), who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Update the main CKAN config object with the Flask specific keys # that were set here or autogenerated flask_config_keys = set(flask_app.config.keys()) - set(config.keys()) for key in flask_config_keys: config[key] = flask_app.config[key] # Prevent the host from request to be added to the new header location. app = HostHeaderMiddleware(app) if six.PY3: app = I18nMiddleware(app) if asbool(config.get('ckan.tracking_enabled', 'false')): app = TrackingMiddleware(app, config) # Add a reference to the actual Flask app so it's easier to access app._wsgi_app = flask_app return app
def add_auth_middleware(self, app, skip_authentication): """ """ log_stream = config.get('who.log_stream', 'stdout') log_stream = LOG_STREAMS.get(log_stream, log_stream) if isinstance(log_stream, basestring): log_stream = logging.getLogger(log_stream) log_level = LOG_LEVELS.get(config['who.log_level'], logging.ERROR) log.debug("LOG_STREAM %s LOG_LEVEL %s", str(log_stream), str(log_level)) if 'who.config_file' in config and asbool( config.get('bisque.has_database')): parser = WhoConfig(config['here']) parser.parse(open(config['who.config_file'])) if not asbool(skip_authentication): app = PluggableAuthenticationMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=parser.remote_user_key, ) else: app = AuthenticationForgerMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=parser.remote_user_key, ) else: log.info("MEX auth only") # Add mex only authentication from repoze.who.plugins.basicauth import BasicAuthPlugin from bq.core.lib.mex_auth import make_plugin from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider basicauth = BasicAuthPlugin('repoze.who') mexauth = make_plugin() identifiers = [('mexauth', mexauth)] authenticators = [('mexauth', mexauth)] challengers = [] mdproviders = [] app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream=log_stream, log_level=log_level, ) return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware(app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers+static_parsers) return app
def make_pylons_stack(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(conf, app_conf) # The Pylons WSGI app app = pylons_app = CKANPylonsApp() # set pylons globals app_globals.reset() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # app = QueueLogMiddleware(app) if asbool(config.get('ckan.use_pylons_response_cleanup_middleware', True)): app = execute_on_completion(app, config, cleanup_pylons_response_string) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 400, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 403, 404]) else: app = StatusCodeRedirect(app, [400, 403, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Establish the Registry for this application app = RegistryManager(app) app = common_middleware.I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError, e: # errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers + static_parsers)
def make_pylons_stack(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # The Pylons WSGI app app = pylons_app = CKANPylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # app = QueueLogMiddleware(app) if asbool(config.get('ckan.use_pylons_response_cleanup_middleware', True)): app = execute_on_completion(app, config, cleanup_pylons_response_string) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.'.format( plugin.__class__.__name__)) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 400, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 403, 404]) else: app = StatusCodeRedirect(app, [400, 403, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key) # Establish the Registry for this application app = RegistryManager(app) app = common_middleware.I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool( config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError, e: # errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age)) app = Cascade(extra_static_parsers + static_parsers)