diff --git a/app/authenticators/oauth2.js b/app/authenticators/oauth2.js index c5c9221..8af289b 100644 --- a/app/authenticators/oauth2.js +++ b/app/authenticators/oauth2.js @@ -1,6 +1,69 @@ import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant'; import config from '../config/environment'; +import parseBase64 from '../utils/parse-base64'; +const { RSVP: { Promise }, isEmpty, run, Logger: { warn } } = Ember; export default OAuth2PasswordGrant.extend({ serverTokenEndpoint: `${config.apiURL}/api/authenticate`, + serverTokenRefreshEndpoint: `${config.apiURL}/api/refresh`, + + authenticate: function(identification, password, scope = []) { + return new Promise((resolve, reject) => { + const data = { username: identification, password }; + const serverTokenEndpoint = this.get('serverTokenEndpoint'); + this.makeRequest(serverTokenEndpoint, data).then((response) => { + run(() => { + const token = parseBase64(response['access_token']); + const expiresAt = this._absolutizeExpirationTime(token['exp']); + this._scheduleAccessTokenRefresh(expiresAt, response['access_token']); + if (!isEmpty(expiresAt)) { + response = Ember.merge(response, { 'expires_at': expiresAt }); + } + resolve(response); + }); + }, (xhr) => { + run(null, reject, xhr.responseJSON || xhr.responseText); + }); + }); + }, + + _scheduleAccessTokenRefresh: function(expiresAt, accessToken) { + if (this.get('refreshAccessTokens')) { + const now = (new Date()).getTime(); + const offset = (Math.floor(Math.random() * 5) + 5) * 1000; + if (!isEmpty(accessToken) && !isEmpty(expiresAt) && expiresAt > now - offset) { + run.cancel(this._refreshTokenTimeout); + delete this._refreshTokenTimeout; + if (!Ember.testing) { + this._refreshTokenTimeout = run.later(this, this._refreshAccessToken, expiresAt, accessToken, expiresAt - now - offset); + } + } + } + }, + + _refreshAccessToken: function(expiresAt, accessToken) { + const data = { 'token': accessToken }; + const serverTokenRefreshEndpoint = this.get('serverTokenRefreshEndpoint'); + return new Promise((resolve, reject) => { + this.makeRequest(serverTokenRefreshEndpoint, data).then((response) => { + run(() => { + const token = parseBase64(response['access_token']); + const expiresAt = this._absolutizeExpirationTime(token['exp']); + const data = Ember.merge(response, { 'expires_at': expiresAt }); + this._scheduleAccessTokenRefresh(expiresAt, response['access_token']); + this.trigger('sessionDataUpdated', data); + resolve(data); + }); + }, (xhr, status, error) => { + warn(`Access token could not be refreshed - server responded with ${error}.`); + reject(); + }); + }); + }, + + _absolutizeExpirationTime: function(expiresAt) { + if (!isEmpty(expiresAt)) { + return new Date(expiresAt * 1000).getTime(); + } + } }); diff --git a/app/models/strain.js b/app/models/strain.js index ef5e41c..8643017 100644 --- a/app/models/strain.js +++ b/app/models/strain.js @@ -2,7 +2,7 @@ import DS from 'ember-data'; import Ember from 'ember'; const { Model, hasMany, belongsTo, attr } = DS; -const { computed } = Ember; +const { computed, String: { htmlSafe } } = Ember; export default Model.extend({ measurements : hasMany('measurements', { async: false }), @@ -28,9 +28,7 @@ export default Model.extend({ return `${this.get('species.speciesName')} ${this.get('strainNameMU')}`; }), - // TODO: move this to component/helper - // Can't move until Select2 refactor - fullNameMU: function() { - return Ember.String.htmlSafe(`${this.get('species.speciesName')} ${this.get('strainName')}`); - }.property('species', 'strainNameMU').readOnly(), + fullNameMU: computed('species', 'strainName', function() { + return htmlSafe(`${this.get('species.speciesName')} ${this.get('strainName')}`); + }), }); diff --git a/bower.json b/bower.json index a72a8e1..72fccfa 100644 --- a/bower.json +++ b/bower.json @@ -8,7 +8,7 @@ "ember-data": "1.13.15", "ember-load-initializers": "0.1.7", "ember-qunit": "0.4.16", - "ember-qunit-notifications": "0.1.0", + "ember-qunit-notifications": "~0.1.0", "ember-resolver": "~0.1.20", "loader.js": "ember-cli/loader.js#3.2.1", "qunit": "~1.20.0", diff --git a/config/environment.js b/config/environment.js index 23168bc..8174088 100644 --- a/config/environment.js +++ b/config/environment.js @@ -61,7 +61,7 @@ module.exports = function(environment) { } ENV.apiURL = apiURL; - ENV.contentSecurityPolicy['connect-src'] = `'self' ${apiURL}`; + ENV.contentSecurityPolicy['connect-src'] = "'self' " + apiURL; return ENV; };