diff --git a/ckan/config/middleware/flask_app.py b/ckan/config/middleware/flask_app.py index cf5e28f007b..ee0c0c6813d 100644 --- a/ckan/config/middleware/flask_app.py +++ b/ckan/config/middleware/flask_app.py @@ -11,6 +11,10 @@ from werkzeug.exceptions import HTTPException from werkzeug.routing import Rule +from flask_debugtoolbar import DebugToolbarExtension + +from paste.deploy.converters import asbool + from ckan.lib import helpers from ckan.lib import jinja_extensions from ckan.common import config, g @@ -30,7 +34,12 @@ def make_flask_stack(conf, **app_conf): root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + debug = asbool(app_conf.get('debug', app_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 @@ -43,6 +52,19 @@ def make_flask_stack(conf, **app_conf): 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: + app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False + DebugToolbarExtension(app) + # Add Jinja2 extensions and filters extensions = [ 'jinja2.ext.do', 'jinja2.ext.with_', diff --git a/ckan/tests/config/test_middleware.py b/ckan/tests/config/test_middleware.py index 400f4294c13..92efe05513b 100644 --- a/ckan/tests/config/test_middleware.py +++ b/ckan/tests/config/test_middleware.py @@ -2,12 +2,13 @@ import mock import wsgiref -from nose.tools import assert_equals, assert_not_equals, eq_ +from nose.tools import assert_equals, assert_not_equals, eq_, assert_raises from routes import url_for from flask import Blueprint import ckan.plugins as p import ckan.tests.helpers as helpers +from ckan.common import config from ckan.config.middleware import AskAppDispatcherMiddleware from ckan.config.middleware.flask_app import CKANFlask @@ -446,3 +447,31 @@ class MockPylonsController(p.toolkit.BaseController): def view(self): return 'Hello World, this is served from a Pylons extension' + + +class TestSecretKey(object): + + @helpers.change_config('SECRET_KEY', 'super_secret_stuff') + def test_secret_key_is_used_if_present(self): + + app = helpers._get_test_app() + + eq_(app.flask_app.config['SECRET_KEY'], + u'super_secret_stuff') + + @helpers.change_config('SECRET_KEY', None) + def test_beaker_secret_is_used_by_default(self): + + app = helpers._get_test_app() + + eq_(app.flask_app.config['SECRET_KEY'], + config['beaker.session.secret']) + + @helpers.change_config('SECRET_KEY', None) + @helpers.change_config('beaker.session.secret', None) + def test_no_beaker_secret_crashes(self): + + assert_raises(ValueError, helpers._get_test_app) + + # TODO: When Pylons is finally removed, we should test for + # RuntimeError instead (thrown on `make_flask_stack`) diff --git a/ckan/tests/helpers.py b/ckan/tests/helpers.py index bfda83a1a1e..cca05ecdce2 100644 --- a/ckan/tests/helpers.py +++ b/ckan/tests/helpers.py @@ -155,6 +155,7 @@ def _get_test_app(): ''' config['ckan.legacy_templates'] = False + config['testing'] = True app = ckan.config.middleware.make_app(config['global_conf'], **config) app = CKANTestApp(app) return app diff --git a/dev-requirements.txt b/dev-requirements.txt index 095abe8a547..54503afe28e 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,6 +4,7 @@ beautifulsoup4==4.4.1 coveralls #Let Unpinned - Requires latest coveralls docutils==0.12 factory-boy==2.1.1 +Flask-DebugToolbar==0.10.0 httpretty==0.8.3 mock==2.0.0 pep8==1.4.6 diff --git a/test-core.ini b/test-core.ini index 5687a2f0867..aae1b7fe836 100644 --- a/test-core.ini +++ b/test-core.ini @@ -12,14 +12,11 @@ use = egg:ckan full_stack = true cache_dir = %(here)s/data debug = false +testing = true -#faster_db_test_hacks = True -# Specify the database for SQLAlchemy to use: -# * Postgres is currently required for a production CKAN deployment -# * Sqlite (memory or file) can be used as a quick alternative for testing +# Specify the Postgres database for SQLAlchemy to use sqlalchemy.url = postgresql://ckan_default:pass@localhost/ckan_test -#sqlalchemy.url = sqlite:/// ## Datastore ckan.datastore.write_url = postgresql://ckan_default:pass@localhost/datastore_test