Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2308] Refactor Adaptive store to use DI #2312

Merged
merged 7 commits into from
Aug 13, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions packages/ember-simple-auth/addon/session-stores/adaptive.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
import { getOwner } from '@ember/application';
import Base from 'ember-simple-auth/session-stores/base';
import LocalStorage from 'ember-simple-auth/session-stores/local-storage';
import Cookie from 'ember-simple-auth/session-stores/cookie';

const LOCAL_STORAGE_TEST_KEY = '_ember_simple_auth_test_key';

const injectStore = (store) => {
return computed(function() {
return getOwner(this).lookup(`session-store:${store}`);
});
};

const proxyToInternalStore = function() {
return computed({
get(key) {
Expand Down Expand Up @@ -53,6 +57,8 @@ export default Base.extend({
*/
localStorageKey: 'ember_simple_auth-session',

localStorage: injectStore('local-storage'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be set in init instead?

this.localStorage = getOwner(this).lookup(`session-store:local-storage`);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, yes 👍


/**
The domain to use for the cookie if `localStorage` is not available, e.g.,
"example.com", ".example.com" (which includes all subdomains) or
Expand Down Expand Up @@ -102,7 +108,21 @@ export default Base.extend({
_cookieExpirationTime: null,
cookieExpirationTime: proxyToInternalStore(),

_sameSite: null,
sameSite: proxyToInternalStore(),

_cookies: service('cookies'),
cookie: injectStore('cookie'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above


_isLocalStorageAvailable: computed({
marcoow marked this conversation as resolved.
Show resolved Hide resolved
get() {
return testLocalStorageAvailable();
},

set(key, value) {
return value;
}
}),

init() {
this._super(...arguments);
Expand All @@ -112,28 +132,25 @@ export default Base.extend({
this._fastboot = owner.lookup('service:fastboot');
}

this._isLocalStorageAvailable = this.hasOwnProperty('_isLocalStorageAvailable') ? this._isLocalStorageAvailable : testLocalStorageAvailable();

let store;
if (this.get('_isLocalStorageAvailable')) {
store = this.get('localStorage');
const options = { key: this.get('localStorageKey') };
options._isFastBoot = false;
store = this._createStore(LocalStorage, options);
store.setProperties(options);
} else {
const options = this.getProperties('cookieDomain', 'cookieName', 'cookieExpirationTime', 'cookiePath');
options._fastboot = this.get('_fastboot');
options._cookies = this.get('_cookies');
store = this.get('cookie');
const options = this.getProperties('sameSite', 'cookieDomain', 'cookieName', 'cookieExpirationTime', 'cookiePath');

store = this._createStore(Cookie, options);
store._initialize(options);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does

Suggested change
store._initialize(options);
store.setProperties(options);

not work here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could check that out, although _initalize currently needs to treat the cookieName property in a special way.

The proxy properties that were receiving some default values on initialization weren't causing any issues before, but right now since we can't really pass any properties during init, but we set them after instead - its causing e.g cookieName to be cached with a wrong value.

this.set('cookieExpirationTime', store.get('cookieExpirationTime'));
}

this.set('_store', store);
this._setupStoreEvents(store);
},

_createStore(storeType, options) {
let owner = getOwner(this);
const store = storeType.create(owner.ownerInjection(), options);

_setupStoreEvents(store) {
store.on('sessionDataUpdated', (data) => {
this.trigger('sessionDataUpdated', data);
});
Expand Down
11 changes: 10 additions & 1 deletion packages/ember-simple-auth/addon/session-stores/cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,20 @@ export default BaseStore.extend({

init() {
this._super(...arguments);

let owner = getOwner(this);
if (owner && !this.hasOwnProperty('_fastboot')) {
this._fastboot = owner.lookup('service:fastboot');
}
},

_initialize(options) {
const clonedOptions = Object.assign({}, options);
if (clonedOptions.cookieName) {
this.set('_cookieName', clonedOptions.cookieName);
}

delete clonedOptions.cookieName;
this.setProperties(clonedOptions);
marcoow marked this conversation as resolved.
Show resolved Hide resolved

let cachedExpirationTime = this._read(`${this.get('cookieName')}-expiration_time`);
if (cachedExpirationTime) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import Configuration from 'ember-simple-auth/configuration';
import setupSession from 'ember-simple-auth/initializers/setup-session';
import setupSessionService from 'ember-simple-auth/initializers/setup-session-service';
import setupSessionRestoration from 'ember-simple-auth/initializers/setup-session-restoration';
import Adaptive from 'ember-simple-auth/session-stores/adaptive';
import LocalStorage from 'ember-simple-auth/session-stores/local-storage';
import Cookie from 'ember-simple-auth/session-stores/cookie';

export default {
name: 'ember-simple-auth',
Expand All @@ -12,6 +15,10 @@ export default {
config.rootURL = ENV.rootURL || ENV.baseURL;
Configuration.load(config);

registry.register('session-store:adaptive', Adaptive);
registry.register('session-store:cookie', Cookie);
registry.register('session-store:local-storage', LocalStorage);

setupSession(registry);
setupSessionService(registry);
setupSessionRestoration(registry);
Expand Down
22 changes: 5 additions & 17 deletions packages/ember-simple-auth/tests/helpers/create-adaptive-store.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import Adaptive from 'ember-simple-auth/session-stores/adaptive';
import createCookieStore from './create-cookie-store';
import { merge, assign as emberAssign } from '@ember/polyfills';

const assign = emberAssign || merge;

export default function createAdaptiveStore(
cookiesService,
options = {},
props = {}
owner
) {
let cookieStore = createCookieStore(
cookiesService,
assign({}, options, { _isFastboot: false })
);
props._createStore = function() {
cookieStore.on('sessionDataUpdated', data => {
this.trigger('sessionDataUpdated', data);
});

return cookieStore;
};
owner.register('session-store:adaptive', Adaptive.extend(Object.assign({
_isLocalStorageAvailable: false,
}, options)));

return Adaptive.extend(props).create(options);
return owner.lookup('session-store:adaptive');
}
marcoow marked this conversation as resolved.
Show resolved Hide resolved

This file was deleted.

134 changes: 70 additions & 64 deletions packages/ember-simple-auth/tests/unit/session-stores/adaptive-test.js
Original file line number Diff line number Diff line change
@@ -1,98 +1,104 @@
import { run } from '@ember/runloop';
import {
describe,
beforeEach,
afterEach,
it
} from 'mocha';
import { describe, it } from 'mocha';
import { expect } from 'chai';
import sinonjs from 'sinon';
import Adaptive from 'ember-simple-auth/session-stores/adaptive';
import LocalStorage from 'ember-simple-auth/session-stores/local-storage';
import itBehavesLikeAStore from './shared/store-behavior';
import itBehavesLikeACookieStore from './shared/cookie-store-behavior';
import FakeCookieService from '../../helpers/fake-cookie-service';
import createAdaptiveStore from '../../helpers/create-adaptive-store';
import { setupTest } from 'ember-mocha';

describe('AdaptiveStore', () => {
let sinon;
let store;

beforeEach(function() {
sinon = sinonjs.createSandbox();
});

afterEach(function() {
store.clear();
sinon.restore();
});

setupTest();
describe('when localStorage is available', function() {
beforeEach(function() {
store = Adaptive.extend({
_createStore(storeType, options) {
return LocalStorage.create({ _isFastBoot: false }, options);
}
}).create({
_isLocalStorageAvailable: true
});
});

itBehavesLikeAStore({
store() {
store(sinon, owner) {
let store;
let cookieService;
owner.register('service:cookies', FakeCookieService);
cookieService = owner.lookup('service:cookies');
sinon.spy(cookieService, 'read');
sinon.spy(cookieService, 'write');
store = createAdaptiveStore(cookieService, {
_isLocal: false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to exist anywhere actually? 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's true, I will remove it, also noticed that some of the _isFastBoot properties were miswritten, we have _isFastBoot and _isFastboot currently somewhere i believe.

_isLocalStorageAvailable: true,
}, owner);
return store;
}
});
});

describe('when localStorage is not available', function() {
let cookieService;
beforeEach(function() {
cookieService = FakeCookieService.create();
sinon.spy(cookieService, 'read');
sinon.spy(cookieService, 'write');
store = createAdaptiveStore(cookieService, {
_isLocal: false,
_cookies: cookieService,
});
});

itBehavesLikeAStore({
store() {
store(sinon, owner) {
let store;
let cookieService;
owner.register('service:cookies', FakeCookieService);
cookieService = owner.lookup('service:cookies');
sinon.spy(cookieService, 'read');
sinon.spy(cookieService, 'write');
store = createAdaptiveStore(cookieService, {
_isLocal: false,
_isLocalStorageAvailable: false,
_cookieName: 'test:session',
}, owner);
return store;
}
});
});

itBehavesLikeACookieStore({
createStore(cookieService, options = {}) {
options._isLocalStorageAvailable = false;
return createAdaptiveStore(cookieService, options, {
_cookies: cookieService,
_fastboot: { isFastBoot: false },
});
},
renew(store, data) {
return store.get('_store')._renew(data);
},
sync(store) {
store.get('_store')._syncData();
},
spyRewriteCookieMethod(store) {
sinon.spy(store.get('_store'), 'rewriteCookie');
return store.get('_store').rewriteCookie;
}
describe('CookieStore', function() {
describe('Behaviour', function() {
itBehavesLikeACookieStore({
store(sinon, owner, storeOptions) {
owner.register('service:cookies', FakeCookieService);
let cookieService = owner.lookup('service:cookies');
sinon.spy(cookieService, 'read');
sinon.spy(cookieService, 'write');
let store = createAdaptiveStore(cookieService, Object.assign({
_isLocal: false,
_isLocalStorageAvailable: false,
_cookieName: 'test:session',
}, storeOptions), owner);
return store;
},
renew(store, data) {
return store.get('_store')._renew(data);
},
sync(store) {
store.get('_store')._syncData();
},
spyRewriteCookieMethod(sinon, store) {
sinon.spy(store.get('_store'), 'rewriteCookie');
return store.get('_store').rewriteCookie;
}
});
});

it('persists to cookie when cookie attributes change', function() {
let now = new Date();
it('persists to cookie when cookie attributes change', async function() {
let sinon = sinonjs.createSandbox();
let store;
let cookieService;
let now;

this.owner.register('service:cookies', FakeCookieService);
cookieService = this.owner.lookup('service:cookies');
sinon.spy(cookieService, 'read');
sinon.spy(cookieService, 'write');
run(() => {
store.persist({ key: 'value' });
now = new Date();
store = createAdaptiveStore(cookieService, {
_isLocal: false,
_isLocalStorageAvailable: false,
_cookieName: 'test:session',
}, this.owner);

store.setProperties({
cookieName: 'test:session',
cookieExpirationTime: 60
});
});
await store.persist({ key: 'value' });

expect(cookieService.write).to.have.been.calledWith(
'test:session-expiration_time',
Expand Down
Loading