Don't rely on auth exemption for /api/version

It's really not necessary - the only visible change is absense of
Fuel version on the login screen.

Also, working with cookies logic was removed from Keystone client
and moved to User model - it has nothing to do with the client.

Change-Id: I0f75b0fdac022c39cbf6f5d4fdeac2d0749b466f
Partial-Bug: #1585137
This commit is contained in:
Vitaly Kramskikh 2016-06-08 18:41:43 +03:00
parent fe8a4b307d
commit 71738018b0
4 changed files with 86 additions and 77 deletions

View File

@ -75,10 +75,7 @@ function($, _, i18n, Backbone, React, utils, layoutComponents, Coccyx, models, K
// this is needed for IE, which caches requests resulting in wrong results (e.g /ostf/testruns/last/1)
$.ajaxSetup({cache: false});
var keystoneClient = this.keystoneClient = new KeystoneClient('/keystone', {
cacheTokenFor: 10 * 60 * 1000,
tenant: 'admin'
});
this.overrideBackboneSyncMethod();
this.version = new models.FuelVersion();
this.settings = new models.FuelSettings();
@ -86,66 +83,26 @@ function($, _, i18n, Backbone, React, utils, layoutComponents, Coccyx, models, K
this.statistics = new models.NodesStatistics();
this.notifications = new models.Notifications();
this.version.fetch().then(_.bind(function() {
var keystoneClient = this.keystoneClient = new KeystoneClient('/keystone', {
cacheTokenFor: 10 * 60 * 1000,
token: this.user.get('token'),
tenant: 'admin'
});
this.version.fetch().then(null, _.bind(function(response) {
if (response.status == 401) {
this.version.set({auth_required: true});
return $.Deferred().resolve();
}
}, this)).then(_.bind(function() {
this.user.set({authenticated: !this.version.get('auth_required')});
var originalSync = Backbone.sync;
Backbone.sync = function(method, model, options) {
// our server doesn't support PATCH, so use PUT instead
if (method == 'patch') {
method = 'update';
}
if (app.version.get('auth_required') && !this.authExempt) {
// FIXME(vkramskikh): manually moving success/error callbacks
// to deferred-style callbacks. Everywhere in the code we use
// deferreds, but backbone uses success/error callbacks. It
// seems there is a bug somewhere: sometimes in long deferred
// chains with .then() success/error callbacks are called when
// deferred object is not resolved, so 'sync' event is
// triggered but dfd.state() still returns 'pending'. This
// leads to various bugs here and there.
var callbacks = {};
return keystoneClient.authenticate()
.fail(function() {
app.logout();
})
.then(_.bind(function() {
options = options || {};
options.headers = options.headers || {};
options.headers['X-Auth-Token'] = keystoneClient.token;
_.each(['success', 'error'], function(callback) {
if (options[callback]) {
callbacks[callback] = options[callback];
delete options[callback];
}
});
return originalSync.call(this, method, model, options);
}, this))
.done(function() {
if (callbacks.success) {
callbacks.success.apply(callbacks.success, arguments);
}
})
.fail(function() {
if (callbacks.error) {
callbacks.error.apply(callbacks.error, arguments);
}
})
.fail(function(response) {
if (response && response.status == 401) {
app.logout();
}
});
}
return originalSync.call(this, method, model, options);
};
if (app.version.get('auth_required')) {
_.extend(keystoneClient, this.user.pick('token'));
return keystoneClient.authenticate()
.done(function() {
.then(function() {
app.user.set({authenticated: true});
return app.version.fetch({cache: true});
});
}
return $.Deferred().resolve();
@ -156,6 +113,62 @@ function($, _, i18n, Backbone, React, utils, layoutComponents, Coccyx, models, K
Backbone.history.start();
}, this));
},
overrideBackboneSyncMethod: function() {
var originalSync = Backbone.sync;
if (originalSync.patched) return;
Backbone.sync = function(method, model, options) {
// our server doesn't support PATCH, so use PUT instead
if (method == 'patch') {
method = 'update';
}
if (app.version && app.version.get('auth_required')) {
// FIXME(vkramskikh): manually moving success/error callbacks
// to deferred-style callbacks. Everywhere in the code we use
// deferreds, but backbone uses success/error callbacks. It
// seems there is a bug somewhere: sometimes in long deferred
// chains with .then() success/error callbacks are called when
// deferred object is not resolved, so 'sync' event is
// triggered but dfd.state() still returns 'pending'. This
// leads to various bugs here and there.
var callbacks = {};
return app.keystoneClient.authenticate()
.fail(function() {
app.logout();
})
.then(_.bind(function() {
app.user.set('token', app.keystoneClient.token);
options = options || {};
options.headers = options.headers || {};
options.headers['X-Auth-Token'] = app.keystoneClient.token;
_.each(['success', 'error'], function(callback) {
if (options[callback]) {
callbacks[callback] = options[callback];
delete options[callback];
}
});
return originalSync.call(this, method, model, options);
}, this))
.done(function() {
if (callbacks.success) {
callbacks.success.apply(callbacks.success, arguments);
}
})
.fail(function() {
if (callbacks.error) {
callbacks.error.apply(callbacks.error, arguments);
}
})
.fail(function(response) {
if (response && response.status == 401) {
app.logout();
}
});
}
return originalSync.call(this, method, model, options);
};
Backbone.sync.patched = true;
},
renderLayout: function() {
this.rootComponent = utils.universalMount(RootComponent, _.pick(this, 'version', 'user', 'statistics', 'notifications'), $('#main-container'));
},

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
**/
define(['jquery', 'underscore', 'jquery-cookie'], function($, _) {
define(['jquery', 'underscore'], function($, _) {
'use strict';
function KeystoneClient(url, options) {
@ -56,9 +56,6 @@ define(['jquery', 'underscore', 'jquery-cookie'], function($, _) {
this.userId = result.access.user.id;
this.token = result.access.token.id;
this.tokenUpdateTime = new Date();
$.cookie('token', result.access.token.id);
return deferred;
} catch(e) {
return $.Deferred().reject();
@ -87,9 +84,6 @@ define(['jquery', 'underscore', 'jquery-cookie'], function($, _) {
try {
this.token = result.access.token.id;
this.tokenUpdateTime = new Date();
$.cookie('token', result.access.token.id);
return deferred;
} catch(e) {
return $.Deferred().reject();
@ -110,8 +104,6 @@ define(['jquery', 'underscore', 'jquery-cookie'], function($, _) {
delete this.token;
delete this.tokenUpdateTime;
$.removeCookie('token');
this.tokenRemoveRequest = $.ajax(this.url + '/v2.0/tokens/' + token, {
type: 'DELETE',
dataType: 'json',

View File

@ -22,6 +22,7 @@ define([
'expression',
'expression/objects',
'jsx!views/custom_controls',
'jquery-cookie',
'deepModel'
], function($, _, i18n, Backbone, utils, Expression, expressionObjects, customControls) {
'use strict';
@ -48,6 +49,7 @@ define([
if (this.cacheFor && options && options.cache && this.lastSyncTime && (this.cacheFor > (new Date() - this.lastSyncTime))) {
return $.Deferred().resolve();
}
if (options) delete options.cache;
return this._super('fetch', arguments);
},
sync: function() {
@ -901,10 +903,10 @@ define([
urlRoot: '/api/ostf'
});
models.FuelVersion = BaseModel.extend({
models.FuelVersion = BaseModel.extend(cacheMixin).extend({
cacheFor: 60 * 1000,
constructorName: 'FuelVersion',
urlRoot: '/api/version',
authExempt: true
urlRoot: '/api/version'
});
models.User = BaseModel.extend({
@ -924,6 +926,14 @@ define([
}
});
}, this);
this.on('change:token', function() {
var token = this.get('token');
if (_.isUndefined(token)) {
$.removeCookie('token');
} else {
$.cookie('token', token);
}
}, this);
}
});

View File

@ -38,12 +38,6 @@ function($, _, i18n, React) {
<LoginForm />
</div>
</div>
<div className='login-copyrights'>
{_.contains(app.version.get('feature_groups'), 'mirantis') &&
<p className='text-center'>{i18n('common.copyright')}</p>
}
<p className='text-center'>{i18n('common.version')}: {app.version.get('release')}</p>
</div>
</div>
);
}
@ -64,7 +58,7 @@ function($, _, i18n, React) {
username: username,
token: keystoneClient.token
});
return app.settings.fetch({cache: true});
return $.when(app.version.fetch({cache: true}), app.settings.fetch({cache: true}));
}, this))
.done(_.bind(function() {
app.navigate('', {trigger: true});