Skip to content

Commit

Permalink
[FIX #11] Fixed the URL where the CSRF token is retrieved
Browse files Browse the repository at this point in the history
  • Loading branch information
huafu committed Mar 30, 2015
1 parent d24a27e commit 23e6753
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 37 deletions.
71 changes: 44 additions & 27 deletions addon/adapters/sails-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ var EmberString = Ember.String;
var fmt = EmberString.fmt;
var pluralize = EmberString.pluralize;
var camelize = EmberString.camelize;
var run = Ember.run;
var next = run.next;
var $ = Ember.$;
var RSVP = Ember.RSVP;

/**
* Base adapter for SailsJS adapters
Expand All @@ -27,6 +31,13 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
* @type Boolean
*/
useCSRF: null,
/**
* Path where to GET the CSRF
* @since 0.0.15
* @property csrfTokenPath
* @type String
*/
csrfTokenPath: '/csrfToken',
/**
* The csrfToken
* @since 0.0.1
Expand Down Expand Up @@ -71,29 +82,31 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
options.data = {};
}
run = function () {
return self._request(out, url, method, options).then(function (response) {
self.info(fmt('%@ %@ request on %@: SUCCESS', out.protocol, method, url));
self.debug(' → request:', options.data);
self.debug(' ← response:', response);
if (self.isErrorObject(response)) {
if (response.errors) {
return Ember.RSVP.reject(new DS.InvalidError(self.formatError(response)));
return self._request(out, url, method, options)
.then(function (response) {
self.info(fmt('%@ %@ request on %@: SUCCESS', out.protocol, method, url));
self.debug(' → request:', options.data);
self.debug(' ← response:', response);
if (self.isErrorObject(response)) {
if (response.errors) {
return RSVP.reject(new DS.InvalidError(self.formatError(response)));
}
return RSVP.reject(response);
}
return Ember.RSVP.reject(response);
}
return response;
}).catch(function (error) {
self.warn(fmt('%@ %@ request on %@: ERROR', out.protocol, method, url));
self.info(' → request:', options.data);
self.info(' ← error:', error);
return Ember.RSVP.reject(error);
});
return response;
}).catch(function (error) {
self.warn(fmt('%@ %@ request on %@: ERROR', out.protocol, method, url));
self.info(' → request:', options.data);
self.info(' ← error:', error);
return RSVP.reject(error);
});
};
if (method !== 'GET') {
return this.fetchCSRFToken().then(function () {
self.checkCSRF(options.data);
return run();
});
return this.fetchCSRFToken()
.then(function () {
self.checkCSRF(options.data);
return run();
});
}
else {
return run();
Expand All @@ -110,7 +123,7 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
var data;

try {
data = Ember.$.parseJSON(jqXHR.responseText);
data = $.parseJSON(jqXHR.responseText);
}
catch (err) {
data = jqXHR.responseText;
Expand All @@ -134,13 +147,13 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
* @since 0.0.3
* @method fetchCSRFToken
* @param {Boolean} [force] If `true`, the token will be fetched even if it has already been fetched
* @return {Ember.RSVP.Promise}
* @return {RSVP.Promise}
*/
fetchCSRFToken: function (force) {
var self = this;
if (this.get('useCSRF') && (force || !this.get('csrfToken'))) {
if (this.get('isLoadingCSRF')) {
return new Ember.RSVP.Promise(function (resolve, reject) {
return new RSVP.Promise(function (resolve, reject) {
self.one('didLoadCSRF', function (token, error) {
if (token) {
resolve(token);
Expand All @@ -157,21 +170,25 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
this.debug('fetching CSRF token...');
return this._fetchCSRFToken()
.then(function (token) {
if (!token) {
self.error('Got an empty CSRF token from the server.');
return RSVP.reject('Got an empty CSRF token from the server!');
}
self.set('isLoadingCSRF', false);
self.info('got a new CSRF token:', token);
self.set('csrfToken', token);
Ember.run.next(self, 'trigger', 'didLoadCSRF', token);
next(self, 'trigger', 'didLoadCSRF', token);
return token;
})
.catch(function (error) {
self.set('isLoadingCSRF', false);
self.error('error trying to get new CSRF token:', error);
Ember.run.next(self, 'trigger', 'didLoadCSRF', null, error);
next(self, 'trigger', 'didLoadCSRF', null, error);
return error;
});
}
}
return Ember.RSVP.resolve(null);
return RSVP.resolve(null);
},

/**
Expand Down Expand Up @@ -227,7 +244,7 @@ export default DS.RESTAdapter.extend(Ember.Evented, WithLoggerMixin, {
this.info('adding CSRF token');
if (!this.csrfToken || this.csrfToken.length === 0) {
this.error('CSRF not fetched yet');
throw new DS.Error("CSRF Token not fetched yet.");
throw new Error("CSRF Token not fetched yet.");
}
data._csrf = this.csrfToken;
return data;
Expand Down
44 changes: 39 additions & 5 deletions addon/adapters/sails-rest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import DS from 'ember-data';
import SailsBaseAdapter from './sails-base';
import Ember from 'ember';


var computed = Ember.computed;

/**
* Adapter for SailsJS HTTP REST API
Expand All @@ -10,6 +14,35 @@ import SailsBaseAdapter from './sails-base';
* @constructor
*/
export default SailsBaseAdapter.extend({
/**
* The full URL to the CSRF token
* @since 0.0.15
* @property csrfTokenUrl
* @type String
*/
csrfTokenUrl: computed('host', 'namespace', 'csrfTokenPath', function (key, value) {
var csrfTokenUrl, csrfTokenPath;
if (arguments.length > 1) {
this._csrfTokenUrl = csrfTokenUrl = value;
}
else if (this._csrfTokenUrl !== undefined) {
csrfTokenUrl = this._csrfTokenUrl;
}
else {
csrfTokenPath = this.get('csrfTokenPath');
csrfTokenUrl = Ember.A([
this.get('host'),
csrfTokenPath.charAt(0) === '/' ? null : this.get('namespace'),
csrfTokenPath.replace(/^\/?/, '/')
]).filter(Boolean).join('/');
if (!/^https?:\/\//.test(csrfTokenUrl)) {
csrfTokenUrl = '/' + csrfTokenUrl;
}
}
return csrfTokenUrl;
}),


/**
* Sends a request over HTTP
*
Expand All @@ -22,7 +55,7 @@ export default SailsBaseAdapter.extend({
* @returns {Ember.RSVP.Promise}
* @private
*/
_request: function(out, url, method, options) {
_request: function (out, url, method, options) {
out.protocol = 'http';
return this._restAdapter_ajax.call(this, url, method, options);
},
Expand All @@ -36,13 +69,14 @@ export default SailsBaseAdapter.extend({
* @private
*/
_fetchCSRFToken: function () {
return this._restAdapter_ajax.call(this, '/csrfToken', 'get').then(function (tokenObject) {
return tokenObject._csrf;
});
return this._restAdapter_ajax.call(this, this.get('csrfTokenUrl'), 'get')
.then(function (tokenObject) {
return tokenObject._csrf;
});
},

/**
* We need to copy the original `ajax` method to be able ot use it inside our own `_request`
* We need to copy the original `ajax` method to be able to use it inside our own `_request`
*
* @since 0.0.8
* @method _restAdapter_ajax
Expand Down
9 changes: 5 additions & 4 deletions addon/adapters/sails-socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default SailsBaseAdapter.extend({
* @returns {Ember.RSVP.Promise}
* @private
*/
_request: function(out, url, method, options) {
_request: function (out, url, method, options) {
out.protocol = 'socket';
return this.sailsSocket.request(method, url, options.data);
},
Expand Down Expand Up @@ -103,9 +103,10 @@ export default SailsBaseAdapter.extend({
* @private
*/
_fetchCSRFToken: function () {
return this.sailsSocket.request('get', '/csrfToken').then(function (tokenObject) {
return tokenObject._csrf;
});
return this.sailsSocket.request('get', this.get('csrfTokenPath').replace(/^\/?/, '/'))
.then(function (tokenObject) {
return tokenObject._csrf;
});
},

/**
Expand Down
3 changes: 2 additions & 1 deletion tests/dummy/app/adapters/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import SailsSocketAdapter from 'ember-data-sails/adapters/sails-socket';

export default SailsSocketAdapter.extend({
defaultSerializer: '-rest',
namespace: 'api/v1'
namespace: 'api/v1',
useCSRF: true
});

0 comments on commit 23e6753

Please sign in to comment.