diff --git a/horizon/middleware.py b/horizon/middleware.py index c2a1344961..6cd9d420a8 100644 --- a/horizon/middleware.py +++ b/horizon/middleware.py @@ -122,11 +122,22 @@ class HorizonMiddleware(object): getattr(django_messages, tag)(request, message, extra_tags) if response['location'].startswith(settings.LOGOUT_URL): redirect_response = http.HttpResponse(status=401) + # This header is used for handling the logout in JS + redirect_response['logout'] = True if self.logout_reason is not None: utils.add_logout_reason( request, redirect_response, self.logout_reason) else: redirect_response = http.HttpResponse() + # Copy cookies from HttpResponseRedirect towards HttpResponse + for cookie_name, cookie in response.cookies.iteritems(): + cookie_kwargs = dict(( + (key, value) for key, value in cookie.iteritems() + if key in ('max_age', 'expires', 'path', 'domain', + 'secure', 'httponly') and value + )) + redirect_response.set_cookie( + cookie_name, cookie.value, **cookie_kwargs) redirect_response['X-Horizon-Location'] = response['location'] return redirect_response if queued_msgs: diff --git a/horizon/static/horizon/js/horizon.modals.js b/horizon/static/horizon/js/horizon.modals.js index a47b706d2d..23bbdc2495 100644 --- a/horizon/static/horizon/js/horizon.modals.js +++ b/horizon/static/horizon/js/horizon.modals.js @@ -121,8 +121,12 @@ horizon.addInitFunction(function() { } }, error: function (jqXHR, status, errorThrown) { - $form.closest(".modal").modal("hide"); - horizon.alert("error", gettext("There was an error submitting the form. Please try again.")); + if (jqXHR.getResponseHeader('logout')) { + location.href = jqXHR.getResponseHeader("X-Horizon-Location"); + } else { + $form.closest(".modal").modal("hide"); + horizon.alert("error", gettext("There was an error submitting the form. Please try again.")); + } } }); }); diff --git a/horizon/utils/functions.py b/horizon/utils/functions.py index 1144d17e18..adc1737b8e 100644 --- a/horizon/utils/functions.py +++ b/horizon/utils/functions.py @@ -1,5 +1,8 @@ import math +from django.conf import settings # noqa +from django.contrib.auth import logout # noqa +from django import http from django.utils.encoding import force_unicode # noqa from django.utils.functional import lazy # noqa from django.utils import translation @@ -24,3 +27,16 @@ def add_logout_reason(request, response, reason): with translation.override(lang): reason = unicode(reason).encode('utf-8') response.set_cookie('logout_reason', reason, max_age=30) + + +def logout_with_message(request, msg): + """Send HttpResponseRedirect to LOGOUT_URL. + + `msg` is a message displayed on the login page after the logout, to explain + the logout reson. + """ + logout(request) + response = http.HttpResponseRedirect( + '%s?next=%s' % (settings.LOGOUT_URL, request.path)) + add_logout_reason(request, response, msg) + return response diff --git a/openstack_dashboard/api/keystone.py b/openstack_dashboard/api/keystone.py index 16dbfb5ec1..3a178648b2 100644 --- a/openstack_dashboard/api/keystone.py +++ b/openstack_dashboard/api/keystone.py @@ -23,7 +23,6 @@ import logging import urlparse from django.conf import settings # noqa -from django.contrib.auth import logout # noqa from django.utils.translation import ugettext_lazy as _ # noqa from keystoneclient import exceptions as keystone_exceptions @@ -32,6 +31,7 @@ from openstack_auth import backend from horizon import exceptions from horizon import messages +from horizon.utils import functions as utils from openstack_dashboard.api import base @@ -354,8 +354,11 @@ def user_update(request, user, **data): if password: try: user_update_password(request, user, password) - if user == request.user.id: - logout(request) + if user.id == request.user.id: + return utils.logout_with_message( + request, + _("Password changed. Please log in again to continue.") + ) except Exception: error = exceptions.handle(request, ignore=True) @@ -367,6 +370,11 @@ def user_update(request, user, **data): if not data['password']: data.pop('password') user = manager.update(user, **data) + if data.get('password') and user.id == request.user.id: + return utils.logout_with_message( + request, + _("Password changed. Please log in again to continue.") + ) return VERSIONS.upgrade_v2_user(user) diff --git a/openstack_dashboard/dashboards/admin/users/forms.py b/openstack_dashboard/dashboards/admin/users/forms.py index 6edeabb220..803b1c008a 100644 --- a/openstack_dashboard/dashboards/admin/users/forms.py +++ b/openstack_dashboard/dashboards/admin/users/forms.py @@ -21,6 +21,7 @@ import logging from django.forms import ValidationError # noqa +from django import http from django.utils.translation import ugettext_lazy as _ # noqa from django.views.decorators.debug import sensitive_variables # noqa @@ -185,10 +186,14 @@ class UpdateUserForm(BaseUserForm): data.pop('domain_name') try: - api.keystone.user_update(request, user, **data) + response = api.keystone.user_update(request, user, **data) messages.success(request, _('User has been updated successfully.')) except Exception: - exceptions.handle(request, ignore=True) + response = exceptions.handle(request, ignore=True) messages.error(request, _('Unable to update the user.')) - return True + + if isinstance(response, http.HttpResponse): + return response + else: + return True