Skip to content

Commit

Permalink
Wrapping async store methods + adding sync store deprecations + impro…
Browse files Browse the repository at this point in the history
…ving async store tests
  • Loading branch information
rmachielse committed Dec 12, 2015
1 parent aa3ffda commit 53451a5
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 183 deletions.
115 changes: 68 additions & 47 deletions addon/internal-session.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Ember from 'ember';
import getOwner from 'ember-getowner-polyfill';

const { on } = Ember;
const { RSVP, on } = Ember;

export default Ember.ObjectProxy.extend(Ember.Evented, {
authenticator: null,
Expand All @@ -17,25 +17,26 @@ export default Ember.ObjectProxy.extend(Ember.Evented, {
Ember.assert(`Session#authenticate requires the authenticator to be specified, was "${authenticator}"!`, !Ember.isEmpty(authenticator));
let theAuthenticator = getOwner(this).lookup(authenticator);
Ember.assert(`No authenticator for factory "${authenticator}" could be found!`, !Ember.isNone(theAuthenticator));
return new Ember.RSVP.Promise((resolve, reject) => {
return new RSVP.Promise((resolve, reject) => {
theAuthenticator.authenticate.apply(theAuthenticator, args).then((content) => {
this._setup(authenticator, content, true);
resolve();
this._setup(authenticator, content, true).then(resolve, reject);
}, (error) => {
this._clear();
reject(error);
this._clear().then(() => {
reject(error);
}, () => {
reject(error);
});
});
});
},

invalidate() {
Ember.assert('Session#invalidate requires the session to be authenticated!', this.get('isAuthenticated'));
return new Ember.RSVP.Promise((resolve, reject) => {
return new RSVP.Promise((resolve, reject) => {
let authenticator = getOwner(this).lookup(this.authenticator);
authenticator.invalidate(this.content.authenticated).then(() => {
authenticator.off('sessionDataUpdated');
this._clear(true);
resolve();
this._clear(true).then(resolve, reject);
}, (error) => {
this.trigger('sessionInvalidationFailed', error);
reject(error);
Expand All @@ -44,67 +45,87 @@ export default Ember.ObjectProxy.extend(Ember.Evented, {
},

restore() {
return new Ember.RSVP.Promise((resolve, reject) => {
let restored = this.store.restore();
if (typeof restored === 'undefined' || typeof restored.then === 'undefined') {
restored = Ember.RSVP.Promise.resolve(restored || {});
}
restored.then((restoredContent) => {
return new RSVP.Promise((resolve, reject) => {
this._callStoreAsync('restore').then((restoredContent) => {
let { authenticator } = (restoredContent.authenticated || {});
if (!!authenticator) {
delete restoredContent.authenticated.authenticator;
getOwner(this).lookup(authenticator).restore(restoredContent.authenticated).then((content) => {
this.set('content', restoredContent);
this._setup(authenticator, content);
resolve();
this._setup(authenticator, content).then(resolve, reject);
}, () => {
Ember.Logger.debug(`The authenticator "${authenticator}" rejected to restore the session - invalidating…`);
this.set('content', restoredContent);
this._clear();
reject();
this._clear().then(reject, reject);
});
} else {
delete (restoredContent || {}).authenticated;
this.set('content', restoredContent);
this._clear();
reject();
this._clear().then(reject, reject);
}
}, () => {
this._clear();
reject();
this._clear().then(reject, reject);
});
});
},

_callStoreAsync(method, ...params) {
let result = this.store[method].apply(this.store, params);
if (typeof result === 'undefined' || typeof result.then === 'undefined') {
Ember.deprecate(`Ember Simple Auth: Synchronous stores have been deprecated. Make sure your custom store's ${method} method returns a promise.`, false, {
id: `ember-simple-auth.session-store.synchronous-${method}`,
until: '2.0.0'
});
return RSVP.Promise.resolve(result);
} else {
return result;
}
},

_setup(authenticator, authenticatedContent, trigger) {
trigger = !!trigger && !this.get('isAuthenticated');
this.beginPropertyChanges();
this.setProperties({
isAuthenticated: true,
authenticator
return new RSVP.Promise((resolve, reject) => {
trigger = !!trigger && !this.get('isAuthenticated');
this.beginPropertyChanges();
this.setProperties({
isAuthenticated: true,
authenticator
});
Ember.set(this.content, 'authenticated', authenticatedContent);
this._bindToAuthenticatorEvents();
this._updateStore().then(() => {
this.endPropertyChanges();
if (trigger) {
this.trigger('authenticationSucceeded');
}
resolve();
}, () => {
this.setProperties({
isAuthenticated: false,
authenticator: null
});
Ember.set(this.content, 'authenticated', {});
reject();
});
});
Ember.set(this.content, 'authenticated', authenticatedContent);
this._bindToAuthenticatorEvents();
this._updateStore();
this.endPropertyChanges();
if (trigger) {
this.trigger('authenticationSucceeded');
}
},

_clear(trigger) {
trigger = !!trigger && this.get('isAuthenticated');
this.beginPropertyChanges();
this.setProperties({
isAuthenticated: false,
authenticator: null
return new RSVP.Promise((resolve, reject) => {
trigger = !!trigger && this.get('isAuthenticated');
this.beginPropertyChanges();
this.setProperties({
isAuthenticated: false,
authenticator: null
});
Ember.set(this.content, 'authenticated', {});
this._updateStore().then(() => {
this.endPropertyChanges();
if (trigger) {
this.trigger('invalidationSucceeded');
}
resolve();
}, reject);
});
Ember.set(this.content, 'authenticated', {});
this._updateStore();
this.endPropertyChanges();
if (trigger) {
this.trigger('invalidationSucceeded');
}
},

setUnknownProperty(key, value) {
Expand All @@ -119,7 +140,7 @@ export default Ember.ObjectProxy.extend(Ember.Evented, {
if (!Ember.isEmpty(this.authenticator)) {
Ember.set(data, 'authenticated', Ember.merge({ authenticator: this.authenticator }, data.authenticated || {}));
}
this.store.persist(data);
return this._callStoreAsync('persist', data);
},

_bindToAuthenticatorEvents() {
Expand Down
6 changes: 3 additions & 3 deletions addon/session-stores/adaptive.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export default Base.extend({
@method persist
@param {Object} data The data to persist
@return {Ember.RSVP.Promise} The promise object persisting the data in the store.
@return {Ember.RSVP.Promise} A promise that resolves when the data has been persisted and rejects otherwise.
@public
*/
persist() {
Expand All @@ -116,7 +116,7 @@ export default Base.extend({
available - or if it is not, in the cookie - as a plain object.
@method restore
@return {Ember.RSVP.Promise} The promise object resolving the data currently persisted in the `localStorage`.
@return {Ember.RSVP.Promise} A promise that resolves with the data currently persisted in the store when the data has been restored and rejects otherwise.
@public
*/
restore() {
Expand All @@ -129,7 +129,7 @@ export default Base.extend({
`localStorage` if that is available or by deleting the cookie if it is not.
@method clear
@return {Ember.RSVP.Promise} The promise object clearing the store.
@return {Ember.RSVP.Promise} A promise that resolves when the store has been cleared and rejects otherwise.
@public
*/
clear() {
Expand Down
14 changes: 8 additions & 6 deletions addon/session-stores/base.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Ember from 'ember';

const { RSVP } = Ember;

/**
The base class for all session stores. __This serves as a starting point for
implementing custom session stores and must not be used directly.__
Expand Down Expand Up @@ -34,11 +36,11 @@ export default Ember.Object.extend(Ember.Evented, {
@method persist
@param {Object} data The data to persist
@return {Ember.RSVP.Promise} The promise object persisting the data in the store.
@return {Ember.RSVP.Promise} A promise that always rejects.
@public
*/
persist() {
return Ember.RSVP.Promise.reject();
return RSVP.reject();
},

/**
Expand All @@ -48,11 +50,11 @@ export default Ember.Object.extend(Ember.Evented, {
be overridden in subclasses__.
@method restore
@return {Ember.RSVP.Promise} The promise object resolving the data currently persisted in the store.
@return {Ember.RSVP.Promise} A promise that always rejects.
@public
*/
restore() {
return Ember.RSVP.Promise.reject();
return RSVP.reject();
},

/**
Expand All @@ -62,10 +64,10 @@ export default Ember.Object.extend(Ember.Evented, {
overridden in subclasses__.
@method clear
@return {Ember.RSVP.Promise} The promise object clearing the store.
@return {Ember.RSVP.Promise} A promise that always rejects.
@public
*/
clear() {
return Ember.RSVP.Promise.reject();
return RSVP.reject();
}
});
58 changes: 24 additions & 34 deletions addon/session-stores/cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import Ember from 'ember';
import BaseStore from './base';
import objectsAreEqual from '../utils/objects-are-equal';

const { computed } = Ember;

const { on } = Ember;
const { RSVP, computed, on } = Ember;

/**
Session store that persists data in a cookie.
Expand Down Expand Up @@ -100,52 +98,44 @@ export default BaseStore.extend({
@method persist
@param {Object} data The data to persist
@return {Ember.RSVP.Promise} The promise object persisting the data in the store.
@return {Ember.RSVP.Promise} A promise that resolves when the data has been persisted and rejects otherwise.
@public
*/
persist(data) {
return new Ember.RSVP.Promise((resolve, reject) => {
data = JSON.stringify(data || {});
let expiration = this._calculateExpirationTime();
this._write(data, expiration);
this.restore().then((restoredContent) => {
this._lastData = restoredContent;
resolve();
}, reject);
});
this._lastData = data;
data = JSON.stringify(data || {});
let expiration = this._calculateExpirationTime();
this._write(data, expiration);
return RSVP.resolve();
},

/**
Returns all data currently stored in the cookie as a plain object.
@method restore
@return {Ember.RSVP.Promise} The promise object resolving the data currently persisted in the cookie.
@return {Ember.RSVP.Promise} A promise that resolves with the data currently persisted in the cookie when the data has been restored and rejects otherwise.
@public
*/
restore() {
return new Ember.RSVP.Promise((resolve) => {
let data = this._read(this.cookieName);
if (Ember.isEmpty(data)) {
resolve({});
} else {
resolve(JSON.parse(data));
}
});
let data = this._read(this.cookieName);
if (Ember.isEmpty(data)) {
return RSVP.resolve({});
} else {
return RSVP.resolve(JSON.parse(data));
}
},

/**
Clears the store by deleting the cookie.
@method clear
@return {Ember.RSVP.Promise} The promise object clearing the store.
@return {Ember.RSVP.Promise} A promise that resolves when the store has been cleared and rejects otherwise.
@public
*/
clear() {
return new Ember.RSVP.Promise((resolve) => {
this._write(null, 0);
this._lastData = {};
resolve();
});
this._write(null, 0);
this._lastData = {};
return RSVP.resolve();
},

_read(name) {
Expand All @@ -172,7 +162,7 @@ export default BaseStore.extend({
},

_syncData() {
return new Ember.RSVP.Promise((resolve) => {
return new RSVP.Promise((resolve, reject) => {
this.restore().then((data) => {
if (!objectsAreEqual(data, this._lastData)) {
this._lastData = data;
Expand All @@ -183,27 +173,27 @@ export default BaseStore.extend({
this._syncDataTimeout = Ember.run.later(this, this._syncData, 500);
}
resolve();
});
}, reject);
});
},

_renew() {
return new Ember.RSVP.Promise((resolve) => {
return new RSVP.Promise((resolve, reject) => {
this.restore().then((data) => {
if (!Ember.isEmpty(data) && data !== {}) {
data = Ember.typeOf(data) === 'string' ? data : JSON.stringify(data || {});
let expiration = this._calculateExpirationTime();
this._write(data, expiration);
}
resolve();
});
}, reject);
});
},

_renewExpiration() {
return new Ember.RSVP.Promise((resolve) => {
return new RSVP.Promise((resolve, reject) => {
if (this.get('_isPageVisible')) {
this._renew().then(resolve);
this._renew().then(resolve, reject);
}
if (!Ember.testing) {
Ember.run.cancel(this._renewExpirationTimeout);
Expand Down
Loading

0 comments on commit 53451a5

Please sign in to comment.