From 0ca49aa2cfbed6be9bc0b9ed2bc6bbb758c9a311 Mon Sep 17 00:00:00 2001 From: Michael Keirnan Date: Mon, 10 Jul 2017 06:34:19 -0400 Subject: [PATCH] add session store that uses sessionStorage (#1392) * add session store that uses sessionStorage * describe sessionStorage Store in README --- README.md | 8 ++ addon/session-stores/session-storage.js | 105 ++++++++++++++++++ .../session-stores/session-storage-test.js | 23 ++++ 3 files changed, 136 insertions(+) create mode 100644 addon/session-stores/session-storage.js create mode 100644 tests/unit/session-stores/session-storage-test.js diff --git a/README.md b/README.md index 124bbadc9c..998481f17d 100644 --- a/README.md +++ b/README.md @@ -545,6 +545,14 @@ stores its data in a cookie. This is used by the adaptive store if application uses [FastBoot](https://github.com/ember-fastboot/ember-cli-fastboot).__ +#### `sessionStorage` Store + +[The `sessionStorage` store](http://ember-simple-auth.com/api/classes/SessionStorageStore.html) +stores its data in the browser's `sessionStorage`. See [the Web Storage docs] +(https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) for details on +`sessionStorage` and `localStorage`. [caniuse](http://caniuse.com/#feat=namevalue-storage) +has up-to-date information on browser support of `sessionStorage` and `localStorage`. + #### Ephemeral Store [The ephemeral store](http://ember-simple-auth.com/api/classes/EphemeralStore.html) diff --git a/addon/session-stores/session-storage.js b/addon/session-stores/session-storage.js new file mode 100644 index 0000000000..4493c576c2 --- /dev/null +++ b/addon/session-stores/session-storage.js @@ -0,0 +1,105 @@ +/* global sessionStorage */ +import Ember from 'ember'; +import BaseStore from './base'; +import objectsAreEqual from '../utils/objects-are-equal'; + +const { RSVP, $: jQuery, computed, getOwner } = Ember; + +/** + Session store that persists data in the browser's `sessionStorage`. + + __`sessionStorage` is not available in Safari when running in private mode.__ + + __This session store does not work with FastBoot. In order to use Ember + Simple Auth with FastBoot, configure the + {{#crossLink "CookieStore"}}{{/crossLink}} as the application's session + store.__ + + @class SessionStorageStore + @module ember-simple-auth/session-stores/session-storage + @extends BaseStore + @public +*/ +export default BaseStore.extend({ + _isFastBoot: computed(function() { + const fastboot = getOwner(this).lookup('service:fastboot'); + + return fastboot ? fastboot.get('isFastBoot') : false; + }), + + /** + The `sessionStorage` key the store persists data in. + + @property key + @type String + @default 'ember_simple_auth-session' + @public + */ + key: 'ember_simple_auth-session', + + init() { + this._super(...arguments); + + if (!this.get('_isFastBoot')) { + this._bindToStorageEvents(); + } + }, + + /** + Persists the `data` in the `sessionStorage`. + + @method persist + @param {Object} data The data to persist + @return {Ember.RSVP.Promise} A promise that resolves when the data has successfully been persisted and rejects otherwise. + @public + */ + persist(data) { + this._lastData = data; + data = JSON.stringify(data || {}); + sessionStorage.setItem(this.key, data); + + return RSVP.resolve(); + }, + + /** + Returns all data currently stored in the `sessionStorage` as a plain object. + + @method restore + @return {Ember.RSVP.Promise} A promise that resolves with the data currently persisted in the store when the data has been restored successfully and rejects otherwise. + @public + */ + restore() { + let data = sessionStorage.getItem(this.key); + + return RSVP.resolve(JSON.parse(data) || {}); + }, + + /** + Clears the store by deleting the + {{#crossLink "sessionStorageStore/key:property"}}{{/crossLink}} from + `sessionStorage`. + + @method clear + @return {Ember.RSVP.Promise} A promise that resolves when the store has been cleared successfully and rejects otherwise. + @public + */ + clear() { + sessionStorage.removeItem(this.key); + this._lastData = {}; + + return RSVP.resolve(); + }, + + _bindToStorageEvents() { + jQuery(window).on('storage', (e) => { + if (e.originalEvent.key === this.key) { + this.restore().then((data) => { + if (!objectsAreEqual(data, this._lastData)) { + this._lastData = data; + this.trigger('sessionDataUpdated', data); + } + }); + } + }); + } +}); diff --git a/tests/unit/session-stores/session-storage-test.js b/tests/unit/session-stores/session-storage-test.js new file mode 100644 index 0000000000..3701be31cb --- /dev/null +++ b/tests/unit/session-stores/session-storage-test.js @@ -0,0 +1,23 @@ +import { describe, beforeEach, afterEach } from 'mocha'; +import SessionStorage from 'ember-simple-auth/session-stores/session-storage'; +import itBehavesLikeAStore from './shared/store-behavior'; + +describe('SessionStorageStore', () => { + let store; + + beforeEach(function() { + store = SessionStorage.create({ + _isFastBoot: false + }); + }); + + afterEach(function() { + store.clear(); + }); + + itBehavesLikeAStore({ + store() { + return store; + } + }); +});