diff --git a/ckan/config/middleware/flask_app.py b/ckan/config/middleware/flask_app.py index eaf98a3e0ba..c9cb56185f7 100644 --- a/ckan/config/middleware/flask_app.py +++ b/ckan/config/middleware/flask_app.py @@ -27,7 +27,9 @@ from ckan.common import c from ckan.plugins import PluginImplementations from ckan.plugins.interfaces import IBlueprint -from ckan.views import identify_user, set_cors_headers_for_response +from ckan.views import (identify_user, + set_cors_headers_for_response, + check_session_cookie) from ckan.config.middleware import common_middleware @@ -102,7 +104,8 @@ def ckan_before_request(): @app.after_request def ckan_after_request(response): - set_cors_headers_for_response(response) + response = check_session_cookie(response) + response = set_cors_headers_for_response(response) # log time between before and after view r_time = time.time() - c._request_timer diff --git a/ckan/lib/base.py b/ckan/lib/base.py index 24b6f3a57fe..1bf7e292376 100644 --- a/ckan/lib/base.py +++ b/ckan/lib/base.py @@ -26,7 +26,9 @@ import ckan.plugins as p import ckan.model as model import ckan.lib.maintain as maintain -from ckan.views import identify_user, set_cors_headers_for_response +from ckan.views import (identify_user, + set_cors_headers_for_response, + check_session_cookie) # These imports are for legacy usages and will be removed soon these should # be imported directly from ckan.common for internal ckan code and via the @@ -246,30 +248,7 @@ def __call__(self, environ, start_response): finally: model.Session.remove() - for cookie in request.cookies: - # Remove the ckan session cookie if not used e.g. logged out - if cookie == 'ckan' and not c.user: - # Check session for valid data (including flash messages) - # (DGU also uses session for a shopping basket-type behaviour) - is_valid_cookie_data = False - for key, value in session.items(): - if not key.startswith('_') and value: - is_valid_cookie_data = True - break - if not is_valid_cookie_data: - if session.id: - if not session.get('lang'): - self.log.debug('No session data any more - ' - 'deleting session') - self.log.debug('Session: %r', session.items()) - session.delete() - else: - response.delete_cookie(cookie) - self.log.debug('No session data any more - ' - 'deleting session cookie') - # Remove auth_tkt repoze.who cookie if user not logged in. - elif cookie == 'auth_tkt' and not session.id: - response.delete_cookie(cookie) + check_session_cookie(response) return res diff --git a/ckan/views/__init__.py b/ckan/views/__init__.py index c0538e8977b..b8be17f6fde 100644 --- a/ckan/views/__init__.py +++ b/ckan/views/__init__.py @@ -5,7 +5,7 @@ from paste.deploy.converters import asbool import ckan.model as model -from ckan.common import c, request +from ckan.common import c, request, session import ckan.plugins as p import logging @@ -15,6 +15,36 @@ APIKEY_HEADER_NAME_DEFAULT = 'X-CKAN-API-Key' +def check_session_cookie(response): + ''' + The cookies for auth (auth_tkt) and session (ckan) are separate. This + checks whether a user is logged in, and determines the validity of the + session cookie, removing it if necessary. + ''' + for cookie in request.cookies: + # Remove the ckan session cookie if logged out. + if cookie == 'ckan' and not c.user: + # Check session for valid data (including flash messages) + is_valid_cookie_data = False + for key, value in session.items(): + if not key.startswith('_') and value: + is_valid_cookie_data = True + break + if not is_valid_cookie_data: + if session.id: + log.debug('No valid session data - deleting session') + log.debug('Session: %r', session.items()) + session.delete() + else: + log.debug('No session id - deleting session cookie') + response.delete_cookie(cookie) + # Remove auth_tkt repoze.who cookie if user not logged in. + elif cookie == 'auth_tkt' and not session.id: + response.delete_cookie(cookie) + + return response + + def set_cors_headers_for_response(response): ''' Set up Access Control Allow headers if either origin_allow_all is True, or @@ -40,6 +70,8 @@ def set_cors_headers_for_response(response): response.headers['Access-Control-Allow-Headers'] = \ "X-CKAN-API-KEY, Authorization, Content-Type" + return response + def identify_user(): '''Try to identify the user