Merge lp:~rvb/maas/logout-fix-1.2 into lp:maas/1.2

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 1388
Proposed branch: lp:~rvb/maas/logout-fix-1.2
Merge into: lp:maas/1.2
Diff against target: 122 lines (+70/-4)
3 files modified
src/maasserver/templates/maasserver/logout_confirm.html (+21/-0)
src/maasserver/tests/test_views_account.py (+25/-2)
src/maasserver/views/account.py (+24/-2)
To merge this branch: bzr merge lp:~rvb/maas/logout-fix-1.2
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+214546@code.launchpad.net

Commit message

Backport revision 2219: Add a "logout confirmation" page. Using this, the logout action is protected against CSRF attacks because it uses a POST request, in conjunction with Django's CSRF protection feature.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'src/maasserver/templates/maasserver/logout_confirm.html'
--- src/maasserver/templates/maasserver/logout_confirm.html 1970-01-01 00:00:00 +0000
+++ src/maasserver/templates/maasserver/logout_confirm.html 2014-04-14 14:00:37 +0000
@@ -0,0 +1,21 @@
1{% extends "maasserver/base.html" %}
2
3{% block nav-active-settings %}active{% endblock %}
4{% block title %}Logout{% endblock %}
5{% block page-title %}Logout{% endblock %}
6
7{% block content %}
8 <div class="block auto-width">
9 <h2>
10 Are you sure you want to log out?
11 </h2>
12 <p>
13 <form action="." method="post">{% csrf_token %}
14 <input type="hidden" name="post" value="yes" />
15 <input type="submit" value="Log out" class="right" />
16 <a href="{% url 'index' %}">Cancel</a>
17 </form>
18 </p>
19 </div>
20{% endblock %}
21
022
=== modified file 'src/maasserver/tests/test_views_account.py'
--- src/maasserver/tests/test_views_account.py 2012-06-25 13:59:23 +0000
+++ src/maasserver/tests/test_views_account.py 2014-04-14 14:00:37 +0000
@@ -1,4 +1,4 @@
1# Copyright 2012 Canonical Ltd. This software is licensed under the1# Copyright 2012-2014 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Test maasserver account views."""4"""Test maasserver account views."""
@@ -13,9 +13,15 @@
13__all__ = []13__all__ = []
1414
15from django.conf import settings15from django.conf import settings
16from django.contrib.auth import SESSION_KEY
17from django.core.urlresolvers import reverse
16from lxml.html import fromstring18from lxml.html import fromstring
19from maasserver.testing import get_content_links
17from maasserver.testing.factory import factory20from maasserver.testing.factory import factory
18from maasserver.testing.testcase import TestCase21from maasserver.testing.testcase import (
22 LoggedInTestCase,
23 TestCase,
24 )
1925
2026
21class TestLogin(TestCase):27class TestLogin(TestCase):
@@ -34,3 +40,20 @@
34 response = self.client.get('/accounts/login/')40 response = self.client.get('/accounts/login/')
35 self.assertTrue(response.context['no_users'])41 self.assertTrue(response.context['no_users'])
36 self.assertEqual(path, response.context['create_command'])42 self.assertEqual(path, response.context['create_command'])
43
44
45class TestLogout(LoggedInTestCase):
46
47 def test_logout_link_present_on_homepage(self):
48 response = self.client.get(reverse('index'))
49 logout_link = reverse('logout')
50 self.assertIn(
51 logout_link,
52 get_content_links(response, element='#user-options'))
53
54 def test_loggout_uses_POST(self):
55 # Using POST for logging out, along with Django's csrf_token
56 # tag, guarantees that we're protected against CSRF attacks on
57 # the loggout page.
58 self.client.post(reverse('logout'))
59 self.assertNotIn(SESSION_KEY, self.client.session.keys())
3760
=== modified file 'src/maasserver/views/account.py'
--- src/maasserver/views/account.py 2012-06-25 13:59:23 +0000
+++ src/maasserver/views/account.py 2014-04-14 14:00:37 +0000
@@ -15,6 +15,7 @@
15 "logout",15 "logout",
16 ]16 ]
1717
18from django import forms
18from django.conf import settings as django_settings19from django.conf import settings as django_settings
19from django.contrib import messages20from django.contrib import messages
20from django.contrib.auth.views import (21from django.contrib.auth.views import (
@@ -22,6 +23,8 @@
22 logout as dj_logout,23 logout as dj_logout,
23 )24 )
24from django.core.urlresolvers import reverse25from django.core.urlresolvers import reverse
26from django.shortcuts import render_to_response
27from django.template import RequestContext
25from maasserver.models import UserProfile28from maasserver.models import UserProfile
2629
2730
@@ -33,6 +36,25 @@
33 return dj_login(request, extra_context=extra_context)36 return dj_login(request, extra_context=extra_context)
3437
3538
39class LogoutForm(forms.Form):
40 """Log-out confirmation form.
41
42 There is nothing interesting in this form, but it's needed in order
43 to get Django's CSRF protection during logout.
44 """
45
46
36def logout(request):47def logout(request):
37 messages.info(request, "You have been logged out.")48 if request.method == 'POST':
38 return dj_logout(request, next_page=reverse('login'))49 form = LogoutForm(request.POST)
50 if form.is_valid():
51 messages.info(request, "You have been logged out.")
52 return dj_logout(request, next_page=reverse('login'))
53 else:
54 form = LogoutForm()
55
56 return render_to_response(
57 'maasserver/logout_confirm.html',
58 {'form': form},
59 context_instance=RequestContext(request),
60 )

Subscribers

People subscribed via source and target branches

to status/vote changes: