diff --git a/ckan/controllers/user.py b/ckan/controllers/user.py index d17df6fc410..81ec29fbae1 100644 --- a/ckan/controllers/user.py +++ b/ckan/controllers/user.py @@ -52,6 +52,11 @@ def _setup_template_variables(self, context): ## end hooks + def _get_repoze_handler(self, handler_name): + '''Returns the URL that repoze.who will respond to and perform a + login or logout.''' + return getattr(request.environ['repoze.who.plugins']['friendlyform'], handler_name) + def index(self): LIMIT = 20 @@ -165,7 +170,9 @@ def _save_new(self, context): return self.new(data_dict, errors, error_summary) if not c.user: # Redirect to a URL picked up by repoze.who which performs the login - h.redirect_to('/login_generic?login=%s&password=%s' % ( + login_url = self._get_repoze_handler('login_handler_path') + h.redirect_to('%s?login=%s&password=%s' % ( + login_url, str(data_dict['name']), quote(data_dict['password1'].encode('utf-8')))) else: @@ -257,6 +264,7 @@ def login(self): g.openid_enabled = False if not c.user: + c.login_handler = h.url_for(self._get_repoze_handler('login_handler_path')) return render('user/login.html') else: return render('user/logout_first.html') @@ -283,10 +291,10 @@ def logged_in(self): h.redirect_to(locale=lang, controller='user', action='login') def logout(self): - # save our language in the session so we don't loose it + # save our language in the session so we don't lose it session['lang'] = request.environ.get('CKAN_LANG') session.save() - h.redirect_to('/user/logout') + h.redirect_to(self._get_repoze_handler('logout_handler_path')) def set_lang(self, lang): # this allows us to set the lang in session. Used for logging diff --git a/ckan/lib/base.py b/ckan/lib/base.py index ffb79a7c4fb..4f77150e8a3 100644 --- a/ckan/lib/base.py +++ b/ckan/lib/base.py @@ -169,9 +169,11 @@ def _identify_user(self): b) For API calls he may set a header with his API key. If the user is identified then: c.user = user name (unicode) + c.userobj = user object c.author = user name otherwise: c.user = None + c.userobj = None c.author = user\'s IP address (unicode) ''' # see if it was proxied first @@ -180,8 +182,10 @@ def _identify_user(self): c.remote_addr = request.environ.get('REMOTE_ADDR', 'Unknown IP Address') # environ['REMOTE_USER'] is set by repoze.who if it authenticates a user's - # cookie or OpenID. (But it doesn't check the user (still) exists in our - # database - we need to do that here. + # cookie or OpenID. But repoze.who doesn't check the user (still) + # exists in our database - we need to do that here. (Another way would + # be with an userid_checker, but that would mean another db access. + # See: http://docs.repoze.org/who/1.0/narr.html#module-repoze.who.plugins.sql ) c.user = request.environ.get('REMOTE_USER', '') if c.user: c.user = c.user.decode('utf8') @@ -210,38 +214,41 @@ def __call__(self, environ, start_response): # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] + try: + res = WSGIController.__call__(self, environ, start_response) + finally: + model.Session.remove() + # Clean out any old cookies as they may contain api keys etc # This also improves the cachability of our pages as cookies # prevent proxy servers from caching content unless they have # been configured to ignore them. - # we do not want to clear cookies when setting the user lang - if not environ.get('PATH_INFO').startswith('/user/set_lang'): - for cookie in request.cookies: - if cookie.startswith('ckan') and cookie not in ['ckan']: - response.delete_cookie(cookie) - # Remove the ckan session cookie if not used e.g. logged out - elif 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'): - session.delete() - else: - 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) - - try: - return WSGIController.__call__(self, environ, start_response) - finally: - model.Session.remove() + for cookie in request.cookies: + if cookie.startswith('ckan') and cookie not in ['ckan']: + response.delete_cookie(cookie) + # Remove the ckan session cookie if not used e.g. logged out + elif 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) + + return res def __after__(self, action, **params): self._set_cors() diff --git a/ckan/templates/user/login.html b/ckan/templates/user/login.html index 9fdf3df1f39..8575e62e20f 100644 --- a/ckan/templates/user/login.html +++ b/ckan/templates/user/login.html @@ -22,7 +22,7 @@
-
+