summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNavaL <mnandri@thoughtworks.com>2016-02-25 09:16:28 +0100
committerNavaL <mnandri@thoughtworks.com>2016-02-25 09:43:02 +0100
commit1e1668f98afd04e2da7c779a825e6d28e777fec7 (patch)
tree3083f6e70f1e3ae004326ff2ece87a768794c40a
parent9573bdca55ddc5488066d3af525e41ed1d872ea6 (diff)
changed logout to post
Issue #612
-rw-r--r--service/pixelated/resources/logout_resource.py2
-rw-r--r--service/test/integration/test_logout.py6
-rw-r--r--service/test/support/integration/multi_user_client.py9
-rw-r--r--service/test/unit/resources/test_logout_resources.py8
-rw-r--r--web-ui/app/js/helpers/browser.js2
-rw-r--r--web-ui/app/js/page/logout.js13
-rw-r--r--web-ui/app/scss/_styles.scss1
-rw-r--r--web-ui/app/templates/page/logout.hbs7
-rw-r--r--web-ui/test/spec/page/logout.spec.js53
9 files changed, 84 insertions, 17 deletions
diff --git a/service/pixelated/resources/logout_resource.py b/service/pixelated/resources/logout_resource.py
index fe80316e..344ad2e9 100644
--- a/service/pixelated/resources/logout_resource.py
+++ b/service/pixelated/resources/logout_resource.py
@@ -8,7 +8,7 @@ class LogoutResource(BaseResource):
BASE_URL = "logout"
isLeaf = True
- def render_GET(self, request):
+ def render_POST(self, request):
session = self.get_session(request)
self._services_factory.log_out_user(session.user_uuid)
session.expire()
diff --git a/service/test/integration/test_logout.py b/service/test/integration/test_logout.py
index 52f7e34f..da414126 100644
--- a/service/test/integration/test_logout.py
+++ b/service/test/integration/test_logout.py
@@ -13,10 +13,11 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+import json
+
from mockito import verify
from twisted.internet import defer
-from test.support.integration import load_mail_from_file
from test.support.integration.multi_user_client import MultiUserClient
from test.support.integration.soledad_test_base import SoledadTestBase
@@ -34,7 +35,8 @@ class MultiUserLogoutTest(MultiUserClient, SoledadTestBase):
yield self.wait_for_session_user_id_to_finish()
- response, request = self.get("/logout", as_json=False, from_request=login_request)
+ response, request = self.post("/logout", json.dumps({'csrftoken': [login_request.getCookie('XSRF-TOKEN')]}),
+ from_request=login_request, as_json=False)
yield response
self.assertEqual(302, request.responseCode) # redirected
diff --git a/service/test/support/integration/multi_user_client.py b/service/test/support/integration/multi_user_client.py
index fa65fb06..5f24456b 100644
--- a/service/test/support/integration/multi_user_client.py
+++ b/service/test/support/integration/multi_user_client.py
@@ -82,3 +82,12 @@ class MultiUserClient(AppTestClient):
session = from_request.getSession()
request.session = session
return self._render(request, as_json)
+
+ def post(self, path, body='', headers=None, ajax=True, csrf='token', as_json=True, from_request=None):
+ headers = headers or {'Content-Type': 'application/json'}
+ request = request_mock(path=path, method="POST", body=body, headers=headers, ajax=ajax, csrf=csrf)
+
+ if from_request:
+ session = from_request.getSession()
+ request.session = session
+ return self._render(request, as_json)
diff --git a/service/test/unit/resources/test_logout_resources.py b/service/test/unit/resources/test_logout_resources.py
index 48cf9db9..6246eeb9 100644
--- a/service/test/unit/resources/test_logout_resources.py
+++ b/service/test/unit/resources/test_logout_resources.py
@@ -1,6 +1,7 @@
from mock import patch
from mockito import mock, verify
from twisted.trial import unittest
+from twisted.web.error import UnsupportedMethod
from twisted.web.test.requesthelper import DummyRequest
from pixelated.resources.logout_resource import LogoutResource
@@ -16,6 +17,7 @@ class TestLogoutResource(unittest.TestCase):
@patch('twisted.web.util.redirectTo')
def test_logout(self, mock_redirect):
request = DummyRequest(['/logout'])
+ request.method = 'POST'
mock_redirect.return_value = 'haha'
@@ -29,3 +31,9 @@ class TestLogoutResource(unittest.TestCase):
d.addCallback(expire_session_and_redirect)
return d
+
+ def test_get_is_not_supported_for_logout(self):
+ request = DummyRequest(['/logout'])
+ request.method = 'GET'
+
+ self.assertRaises(UnsupportedMethod, self.web.get, request)
diff --git a/web-ui/app/js/helpers/browser.js b/web-ui/app/js/helpers/browser.js
index 23aa79c8..dacf2263 100644
--- a/web-ui/app/js/helpers/browser.js
+++ b/web-ui/app/js/helpers/browser.js
@@ -26,7 +26,7 @@ define([], function () {
function getCookie(name) {
var value = '; ' + document.cookie;
var parts = value.split('; ' + name + '=');
- if (parts.length === 2) return parts.pop().split(';').shift();
+ if (parts.length === 2) { return parts.pop().split(';').shift(); }
}
return {
diff --git a/web-ui/app/js/page/logout.js b/web-ui/app/js/page/logout.js
index d881f6c2..81b57db2 100644
--- a/web-ui/app/js/page/logout.js
+++ b/web-ui/app/js/page/logout.js
@@ -14,19 +14,28 @@
* You should have received a copy of the GNU Affero General Public License
* along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
*/
-define(['flight/lib/component', 'features', 'views/templates'], function (defineComponent, features, templates) {
+define(['flight/lib/component', 'features', 'views/templates', 'helpers/browser'],
+ function (defineComponent, features, templates, browser) {
'use strict';
return defineComponent(function () {
+ this.defaultAttrs({form: '#logout-form'});
+
this.render = function () {
- var logoutHTML = templates.page.logout({ logout_url: features.getLogoutUrl() });
+ var logoutHTML = templates.page.logout({ logout_url: features.getLogoutUrl(),
+ csrf_token: browser.getCookie('XSRF-TOKEN')});
this.$node.html(logoutHTML);
};
+ this.logout = function(){
+ this.select('form').submit();
+ };
+
this.after('initialize', function () {
if (features.isLogoutEnabled()) {
this.render();
+ this.on(this.$node, 'click', this.logout);
}
});
diff --git a/web-ui/app/scss/_styles.scss b/web-ui/app/scss/_styles.scss
index a7d6dedf..63f15f6a 100644
--- a/web-ui/app/scss/_styles.scss
+++ b/web-ui/app/scss/_styles.scss
@@ -8,6 +8,7 @@
#logout {
color: $white;
+ cursor: pointer;
}
.search-highlight {
diff --git a/web-ui/app/templates/page/logout.hbs b/web-ui/app/templates/page/logout.hbs
index dd931274..3768d24f 100644
--- a/web-ui/app/templates/page/logout.hbs
+++ b/web-ui/app/templates/page/logout.hbs
@@ -1,8 +1,9 @@
<ul id="logout">
- <a title="logout" href={{logout_url}}>
- <li>
+ <form id="logout-form" method="POST" action="{{ logout_url }}">
+ <input type="hidden" name="csrftoken" value="{{ csrf_token }}" />
+ <li>
<div class="fa fa-sign-out"></div>
<i class="shortcut-label"></i> Logout
</li>
- </a>
+ </form>
</ul>
diff --git a/web-ui/test/spec/page/logout.spec.js b/web-ui/test/spec/page/logout.spec.js
index 7e384cad..a8b882b0 100644
--- a/web-ui/test/spec/page/logout.spec.js
+++ b/web-ui/test/spec/page/logout.spec.js
@@ -8,26 +8,48 @@ describeComponent('page/logout', function () {
features = require('features');
});
- it('should provide logout link if logout is enabled', function () {
+ it('should provide logout form if logout is enabled', function () {
spyOn(features, 'isLogoutEnabled').and.returnValue(true);
this.setupComponent('<nav id="logout"></nav>', {});
- var logout_link = this.component.$node.find('a')[0];
- expect(logout_link).toExist();
- expect(logout_link.href).toMatch('test/logout/url');
+ var logout_form = this.component.$node.find('form')[0];
+ expect(logout_form).toExist();
+ expect(logout_form.action).toMatch('test/logout/url');
+ expect(logout_form.method).toMatch('POST');
});
- it('should not provide logout link if disabled', function() {
+ it('should not provide logout form if logout is disabled', function () {
spyOn(features, 'isLogoutEnabled').and.returnValue(false);
this.setupComponent('<nav id="logout"></nav>', {});
- var logout_link = this.component.$node.find('a')[0];
- expect(logout_link).not.toExist();
+ var logout_form = this.component.$node.find('form')[0];
+ expect(logout_form).not.toExist();
});
- it('should render logout in collapsed nav bar if logout is enabled', function() {
+ it('should provide csrf token if logout is enabled', function () {
+ spyOn(features, 'isLogoutEnabled').and.returnValue(true);
+ document.cookie = 'XSRF-TOKEN=ff895ffc45a4ce140bfc5dda6c61d232; i18next=en-us';
+
+ this.setupComponent('<nav id="logout"></nav>', {});
+
+ var logout_input = this.component.$node.find('input')[0];
+ expect(logout_input).toExist();
+ expect(logout_input.value).toEqual('ff895ffc45a4ce140bfc5dda6c61d232');
+ expect(logout_input.type).toEqual('hidden');
+ });
+
+ it('should not provide csrf token if logout is disabled', function () {
+ spyOn(features, 'isLogoutEnabled').and.returnValue(false);
+
+ this.setupComponent('<nav id="logout"></nav>', {});
+
+ var logout_input = this.component.$node.find('input')[0];
+ expect(logout_input).not.toExist();
+ });
+
+ xit('should render logout in collapsed nav bar if logout is enabled', function() {
spyOn(features, 'isLogoutEnabled').and.returnValue(true);
this.setupComponent('<ul id="logout-shortcuts" class="shortcuts"></ul>', {});
@@ -36,6 +58,21 @@ describeComponent('page/logout', function () {
expect(logout_icon).toExist();
expect(logout_icon.innerHTML).toContain('<div class="fa fa-sign-out"></div>');
});
+
+ it('should submit logout form if logout is enabled', function () {
+ spyOn(features, 'isLogoutEnabled').and.returnValue(true);
+
+ this.setupComponent('<nav id="logout"></nav>', {});
+
+ var logout_form = this.component.$node.find('form')[0];
+ spyOn(logout_form, 'submit');
+
+ this.component.$node.click();
+
+ expect(logout_form.submit).toHaveBeenCalled();
+ });
+
+
});
});