From 77ec41bb6f542077503106cacc1dbd28118c50b4 Mon Sep 17 00:00:00 2001 From: Felix Hammerl Date: Wed, 24 Feb 2016 10:13:25 +0100 Subject: Issue #617: Sanitize received content Sanitizes received HTML content with DOMPurify, making it safe for displaying and templating. Sanitizes received plain text content by encoding every single character as HTML entity. --- web-ui/test/spec/helpers/sanitizer.spec.js | 49 ++++++++++++++++++++++++++++ web-ui/test/spec/helpers/view_helper.spec.js | 7 ---- web-ui/test/test-main.js | 3 +- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 web-ui/test/spec/helpers/sanitizer.spec.js (limited to 'web-ui/test') diff --git a/web-ui/test/spec/helpers/sanitizer.spec.js b/web-ui/test/spec/helpers/sanitizer.spec.js new file mode 100644 index 00000000..acd4b2b2 --- /dev/null +++ b/web-ui/test/spec/helpers/sanitizer.spec.js @@ -0,0 +1,49 @@ +define(['helpers/sanitizer'], function (sanitizer) { + 'use strict'; + + describe('sanitizer', function () { + + describe('sanitizer.addLineBreaks', function () { + it('should add line breaks', function () { + var expectedOutput = 'foo
bar'; + var output = sanitizer.addLineBreaks('foo\nbar'); + expect(output).toEqual(expectedOutput); + }); + }); + + describe('sanitizer.purifyHtml', function () { + it('should fire up DOMPurify', function () { + var expectedOutput = '123I am a dolphin!'; + var output = sanitizer.purifyHtml('123I am a dolphin!'); + expect(output).toEqual(expectedOutput); + }); + }); + + describe('sanitizer.purifyText', function () { + it('should escape HTML', function () { + var expectedOutput = '123<a>asd</a>'; + var output = sanitizer.purifyText('123asd'); + expect(output).toEqual(expectedOutput); + }); + }); + + describe('sanitizer.sanitize', function () { + it('should sanitize a plaintext mail', function () { + var expectedOutput = '123<a>asd</a>'; + var output = sanitizer.sanitize({ + textPlainBody: '123asd' + }); + expect(output).toEqual(expectedOutput); + }); + + it('should sanitize an html mail', function () { + var expectedOutput = '
123I am a dolphin!foobar
'; + var output = sanitizer.sanitize({ + htmlBody: '
123I am a dolphin!foobar
' + }); + expect(output).toEqual(expectedOutput); + }); + }); + + }); +}); diff --git a/web-ui/test/spec/helpers/view_helper.spec.js b/web-ui/test/spec/helpers/view_helper.spec.js index 92a31a1f..b2f597c2 100644 --- a/web-ui/test/spec/helpers/view_helper.spec.js +++ b/web-ui/test/spec/helpers/view_helper.spec.js @@ -90,13 +90,6 @@ define(['helpers/view_helper'], function (viewHelper) { }); }); - it('each line of plain text mail gets a new paragraph', function () { - var formattedMail = $('
'); - formattedMail.html(viewHelper.formatMailBody(testData.parsedMail.simpleTextPlain)); - expect(formattedMail).toContainHtml('
Hello Everyone
'); - }); - - it('escape html in plain text body', function () { var formattedMail = $('
'); var mail = testData.parsedMail.simpleTextPlain; diff --git a/web-ui/test/test-main.js b/web-ui/test/test-main.js index 7d87d9de..17ba3876 100644 --- a/web-ui/test/test-main.js +++ b/web-ui/test/test-main.js @@ -14,6 +14,8 @@ requirejs.config({ 'lib': 'app/js/lib', 'hbs': 'app/js/generated/hbs', 'flight': 'app/bower_components/flight', + 'DOMPurify': 'app/bower_components/DOMPurify/dist/purify.min', + 'he': 'app/bower_components/he/he', 'views': 'app/js/views', 'helpers': 'app/js/helpers', 'feedback': 'app/js/feedback', @@ -35,7 +37,6 @@ requirejs.config({ 'user_settings': 'app/js/user_settings' }, - deps: tests, callback: function () { -- cgit v1.2.3 From 44dfe4c23716c98c06bde1f5ada4a405041d52d4 Mon Sep 17 00:00:00 2001 From: Felix Hammerl Date: Wed, 24 Feb 2016 10:54:11 +0100 Subject: Clean up jshintrc --- web-ui/test/spec/mail_view/ui/draft_box.spec.js | 2 -- web-ui/test/spec/mail_view/ui/draft_save_status.spec.js | 2 -- web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js | 2 -- web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js | 2 -- web-ui/test/spec/mail_view/ui/send_button.spec.js | 2 -- web-ui/test/spec/page/router/url_params.spec.js | 2 -- web-ui/test/spec/tags/data/tags.spec.js | 2 -- web-ui/test/spec/user_alerts/ui/user_alerts.spec.js | 2 -- 8 files changed, 16 deletions(-) (limited to 'web-ui/test') diff --git a/web-ui/test/spec/mail_view/ui/draft_box.spec.js b/web-ui/test/spec/mail_view/ui/draft_box.spec.js index f095f5e5..921767ba 100644 --- a/web-ui/test/spec/mail_view/ui/draft_box.spec.js +++ b/web-ui/test/spec/mail_view/ui/draft_box.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('mail_view/ui/draft_box', function () { 'use strict'; diff --git a/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js b/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js index 0e428066..0db823d9 100644 --- a/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js +++ b/web-ui/test/spec/mail_view/ui/draft_save_status.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('mail_view/ui/draft_save_status', function () { 'use strict'; diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js index a3b3381f..5bca73fe 100644 --- a/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('mail_view/ui/recipients/recipients',function () { 'use strict'; var recipientsUpdatedEvent; diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js index 51f18db3..db240379 100644 --- a/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients_iterator.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - define(['mail_view/ui/recipients/recipients_iterator'], function (RecipientsIterator) { 'use strict'; diff --git a/web-ui/test/spec/mail_view/ui/send_button.spec.js b/web-ui/test/spec/mail_view/ui/send_button.spec.js index 351b4a08..480fe7a8 100644 --- a/web-ui/test/spec/mail_view/ui/send_button.spec.js +++ b/web-ui/test/spec/mail_view/ui/send_button.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('mail_view/ui/send_button', function () { 'use strict'; diff --git a/web-ui/test/spec/page/router/url_params.spec.js b/web-ui/test/spec/page/router/url_params.spec.js index 24cc3797..3c550a43 100644 --- a/web-ui/test/spec/page/router/url_params.spec.js +++ b/web-ui/test/spec/page/router/url_params.spec.js @@ -1,5 +1,3 @@ -/* global jasmine */ - require(['page/router/url_params'], function (urlParams) { 'use strict'; diff --git a/web-ui/test/spec/tags/data/tags.spec.js b/web-ui/test/spec/tags/data/tags.spec.js index 7c4cd4e0..6760b7ac 100644 --- a/web-ui/test/spec/tags/data/tags.spec.js +++ b/web-ui/test/spec/tags/data/tags.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('tags/data/tags', function () { 'use strict'; diff --git a/web-ui/test/spec/user_alerts/ui/user_alerts.spec.js b/web-ui/test/spec/user_alerts/ui/user_alerts.spec.js index 5d87795a..bde3b7fa 100644 --- a/web-ui/test/spec/user_alerts/ui/user_alerts.spec.js +++ b/web-ui/test/spec/user_alerts/ui/user_alerts.spec.js @@ -1,5 +1,3 @@ -/* global Pixelated */ - describeComponent('user_alerts/ui/user_alerts', function () { 'use strict'; -- cgit v1.2.3 From 9573bdca55ddc5488066d3af525e41ed1d872ea6 Mon Sep 17 00:00:00 2001 From: NavaL Date: Wed, 24 Feb 2016 16:33:20 +0100 Subject: Backend and frontend protection against csrf attacks: - root resources changes the csrf token cookie everytime it is loaded, in particular during the intestitial load during login - it will also add that cookie on single user mode - initialize will still load all resources - but they you cant access them if the csrf token do not match - all ajax calls needs to add the token to the header - non ajax get requests do not need xsrf token validation - non ajax post will have to send the token in as a form input or in the content Issue #612 --- web-ui/test/spec/helpers/browser.spec.js | 12 +++++++++++ .../test/spec/helpers/monitored_ajax_call.spec.js | 24 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 web-ui/test/spec/helpers/browser.spec.js (limited to 'web-ui/test') diff --git a/web-ui/test/spec/helpers/browser.spec.js b/web-ui/test/spec/helpers/browser.spec.js new file mode 100644 index 00000000..5b740da8 --- /dev/null +++ b/web-ui/test/spec/helpers/browser.spec.js @@ -0,0 +1,12 @@ +define(['helpers/browser'], function (browser) { + 'use strict'; + + describe('browser ', function() { + it('gets cookie', function() { + document.cookie = 'TWISTED_SESSION=ff895ffc45a4ce140bfc5dda6c61d232; i18next=en-us'; + expect(browser.getCookie('TWISTED_SESSION')).toEqual('ff895ffc45a4ce140bfc5dda6c61d232'); + expect(browser.getCookie('i18next')).toEqual('en-us'); + }); + + }); +}); diff --git a/web-ui/test/spec/helpers/monitored_ajax_call.spec.js b/web-ui/test/spec/helpers/monitored_ajax_call.spec.js index 972ca3ae..c0d55198 100644 --- a/web-ui/test/spec/helpers/monitored_ajax_call.spec.js +++ b/web-ui/test/spec/helpers/monitored_ajax_call.spec.js @@ -1,6 +1,24 @@ define(['helpers/monitored_ajax'], function (monitoredAjax) { 'use strict'; describe('monitoredAjaxCall', function () { + + describe('default configs', function () { + + it('should always attach the xsrf token in the header', function () { + var component = { trigger: function () {}}; + var d = $.Deferred(); + spyOn($, 'ajax').and.returnValue(d); + document.cookie = 'XSRF-TOKEN=ff895ffc45a4ce140bfc5dda6c61d232; i18next=en-us'; + var anyUrl = '/'; + + monitoredAjax(component, anyUrl, {}); + + expect($.ajax.calls.mostRecent().args[1].headers).toEqual({ 'X-XSRF-TOKEN' : 'ff895ffc45a4ce140bfc5dda6c61d232' }); + + }); + + }); + describe('when dealing with errors', function () { _.each( @@ -19,7 +37,7 @@ define(['helpers/monitored_ajax'], function (monitoredAjax) { d.reject({ responseJSON: {}}, errorType, ''); expect(component.trigger).toHaveBeenCalledWith(document, Pixelated.events.ui.userAlerts.displayMessage, - { message: errorMessage }); + { message: errorMessage, class: 'error' }); }); }); @@ -33,7 +51,7 @@ define(['helpers/monitored_ajax'], function (monitoredAjax) { d.reject({ responseJSON: { message: 'Server Message'}}, 'error', ''); expect(component.trigger).toHaveBeenCalledWith(document, Pixelated.events.ui.userAlerts.displayMessage, - { message: 'Server Message' }); + { message: 'Server Message', class: 'error' }); }); }); @@ -76,4 +94,4 @@ define(['helpers/monitored_ajax'], function (monitoredAjax) { }); }); -}); \ No newline at end of file +}); -- cgit v1.2.3 From 1e1668f98afd04e2da7c779a825e6d28e777fec7 Mon Sep 17 00:00:00 2001 From: NavaL Date: Thu, 25 Feb 2016 09:16:28 +0100 Subject: changed logout to post Issue #612 --- web-ui/test/spec/page/logout.spec.js | 53 ++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'web-ui/test') 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('', {}); - 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('', {}); - 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('', {}); + + 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('', {}); + + 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('
    ', {}); @@ -36,6 +58,21 @@ describeComponent('page/logout', function () { expect(logout_icon).toExist(); expect(logout_icon.innerHTML).toContain('
    '); }); + + it('should submit logout form if logout is enabled', function () { + spyOn(features, 'isLogoutEnabled').and.returnValue(true); + + this.setupComponent('', {}); + + var logout_form = this.component.$node.find('form')[0]; + spyOn(logout_form, 'submit'); + + this.component.$node.click(); + + expect(logout_form.submit).toHaveBeenCalled(); + }); + + }); }); -- cgit v1.2.3