diff --git a/package.json b/package.json index 279dcb7..f7acb0d 100644 --- a/package.json +++ b/package.json @@ -5,33 +5,34 @@ "name": "Neosavvy, Inc." }, "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-nodeunit": "~0.2.0", - "grunt-contrib-uglify": "~0.2.2", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-watch": "~0.5.1", - "karma": "~0.10.1", - "grunt-karma": "~0.6.1", - "karma-jasmine": "*", - "karma-requirejs": "*", - "karma-coffee-preprocessor": "*", - "karma-chrome-launcher": "*", - "karma-firefox-launcher": "*", - "karma-phantomjs-launcher": "*", - "karma-script-launcher": "*", - "grunt-ngdocs": "~0.1.7", - "karma-coverage": "~0.1.0", - "grunt-nodemon": "~0.1.1", - "express": "~3.4.0", - "grunt-concurrent": "~0.4.0", - "grunt-open": "~0.2.2", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-copy": "~0.4.1", - "grunt-contrib-qunit": "~0.3.0", - "grunt-contrib-jshint": "~0.6.4", - "grunt-shell": "~0.4.0", - "grunt-bower-task": "~0.3.2", - "http-proxy": "~0.10.3" + "grunt": "0.4.1", + "grunt-contrib-nodeunit": "0.2.0", + "grunt-contrib-uglify": "0.2.2", + "grunt-contrib-concat": "0.3.0", + "grunt-contrib-watch": "0.5.1", + "karma": "0.10.1", + "grunt-karma": "0.6.1", + "karma-jasmine": "0.1.0", + "karma-requirejs": "0.2.1", + "karma-chrome-launcher": "0.1.2", + "karma-firefox-launcher": "0.1.3", + "karma-phantomjs-launcher": "0.1.2", + "karma-script-launcher": "0.1.0", + "karma-ng-html2js-preprocessor": "0.1.0", + "karma-coffee-preprocessor": "0.1.0", + "grunt-ngdocs": "0.1.7", + "karma-coverage": "0.1.0", + "grunt-nodemon": "0.1.1", + "express": "3.4.0", + "grunt-concurrent": "0.4.0", + "grunt-open": "0.2.2", + "grunt-contrib-clean": "0.5.0", + "grunt-contrib-copy": "0.4.1", + "grunt-contrib-qunit": "0.3.0", + "grunt-contrib-jshint": "0.6.4", + "grunt-shell": "0.4.0", + "grunt-bower-task": "0.3.2", + "http-proxy": "0.10.3" }, "paths": { "libraries": "src/main/resources/lib", diff --git a/src/main/resources/library/services/service-extensions.js b/src/main/resources/library/services/service-extensions.js index 5101f2b..7df424e 100644 --- a/src/main/resources/library/services/service-extensions.js +++ b/src/main/resources/library/services/service-extensions.js @@ -59,6 +59,28 @@ Neosavvy.AngularCore.Services.factory('nsServiceExtensions', } } + /** + * Below to functions from: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/ + */ + function csrfSafeMethod(method) { + // these HTTP methods do not require CSRF protection + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); + } + + function sameOrigin(url) { + // test that a given url is a same-origin URL + // url could be relative or scheme relative or absolute + var host = document.location.host; // host + port + var protocol = document.location.protocol; + var sr_origin = '//' + host; + var origin = protocol + sr_origin; + // Allow absolute or scheme relative URLs to same origin + return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || + (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || + // or any other URL that isn't scheme relative or absolute i.e relative. + !(/^(\/\/|http:|https:).*/.test(url)); + } + return { /** * @ngdoc method @@ -207,6 +229,18 @@ Neosavvy.AngularCore.Services.factory('nsServiceExtensions', if (params.ajax) { request = _.merge(request, params.ajax); } + if (params.csrfToken) { + $.ajaxSetup({ + beforeSend: function(xhr, settings) { + if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) { + // Send the token to same-origin, relative URLs only. + // Send the token only if the method warrants CSRF protection + // Using the CSRFToken value acquired earlier + xhr.setRequestHeader("X-CSRFToken", params.csrfToken); + } + } + }); + } var jqXhr = $.ajax(request); jqXhr.done(function (data, textStatus) { storeInCache(params, textStatus, jqXhr.responseText, (jqXhr.getAllResponseHeaders() || {})); diff --git a/src/test/resources/library/services/service-extensions-spec.js b/src/test/resources/library/services/service-extensions-spec.js index bf49b95..0a37e82 100644 --- a/src/test/resources/library/services/service-extensions-spec.js +++ b/src/test/resources/library/services/service-extensions-spec.js @@ -371,6 +371,11 @@ describe("nsServiceExtensions", function () { extensions.jqRequest({method: 'GET', url: 'http://www.neosavvy.co.uk', cache: cacheSpy}); expect(cacheSpy.put).toHaveBeenCalledWith('http://www.neosavvy.co.uk', [200, JSON.stringify([{"name":"Tom"}, {"name":"Jerry"}, {"name":"Clark"}]), {}]); }); + + it("Should set the csrftoken header in the request when options.csrftoken is set to a value", function () { + extensions.jqRequest({method: "GET", url: "http://api.github.com", data: {food: "Fish"}, ajax: {url: "http://www.neosavvy.com", crossDomain: false}, csrfToken:"adamsToken"}); + expect(ajaxSpy).toHaveBeenCalledWith({type: "GET", url:"http://www.neosavvy.com", data: {food: "Fish"}, crossDomain: false}); + }); }); describe("ajax fail", function () {