From f6d83b5492d0ae5db37e32fe6563ca6aa90f6750 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Tue, 14 Apr 2020 15:04:19 -0700 Subject: [PATCH 01/26] Add persistence layer: index db, in memory, and browser{local, session} --- packages-exp/auth-exp/src/core/persistence/browser.test.ts | 1 - packages-exp/auth-exp/src/core/persistence/in_memory.test.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 838b75d6af3..5cea05b4616 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -77,7 +77,6 @@ describe('core/persistence/browser', () => { describe('browserSessionPersistence', () => { const persistence = browserSessionPersistence; - it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; diff --git a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts index c6858d9bad1..767e458c738 100644 --- a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts @@ -36,7 +36,6 @@ describe('core/persistence/in_memory', () => { it('should work with user', async () => { const key = 'my-super-special-user'; const value = testUser('uid'); - expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); expect(await persistence.get(key)).to.eql(value); From efab6d0a3dad58884c17add742f03a52e54f070f Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Tue, 14 Apr 2020 15:04:35 -0700 Subject: [PATCH 02/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/persistence/browser.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 5cea05b4616..686ff5d181c 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -77,6 +77,10 @@ describe('core/persistence/browser', () => { describe('browserSessionPersistence', () => { const persistence = browserSessionPersistence; +<<<<<<< HEAD +======= + +>>>>>>> 3c4f7ca0... [AUTOMATED]: Prettier Code Styling it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; From b561823963170d268a49e0404dc2fd4bf69bd71f Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Wed, 15 Apr 2020 11:05:31 -0700 Subject: [PATCH 03/26] Add indexed_db isAvailable test --- packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts index f12989ec69e..c6528ab4c2d 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts @@ -69,3 +69,4 @@ describe('core/persistence/indexed_db', () => { }); }); }); + From 67e46a9e58a0c151a8816c56edafc4e66d487320 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Wed, 15 Apr 2020 11:08:44 -0700 Subject: [PATCH 04/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts index c6528ab4c2d..f12989ec69e 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts @@ -69,4 +69,3 @@ describe('core/persistence/indexed_db', () => { }); }); }); - From 7cc84c16ee43fbfd3c272a54d55e0b7223cb9d2f Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Tue, 14 Apr 2020 15:04:19 -0700 Subject: [PATCH 05/26] Add persistence layer: index db, in memory, and browser{local, session} --- .../src/core/persistence/browser.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 686ff5d181c..b4ef7a12cb8 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -1,6 +1,10 @@ /** * @license +<<<<<<< HEAD * Copyright 2019 Google LLC +======= + * Copyright 2019 Google Inc. +>>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,12 +51,19 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); +<<<<<<< HEAD expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`) ); +======= + + expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value); + const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); +>>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; @@ -78,9 +89,13 @@ describe('core/persistence/browser', () => { describe('browserSessionPersistence', () => { const persistence = browserSessionPersistence; <<<<<<< HEAD +<<<<<<< HEAD ======= >>>>>>> 3c4f7ca0... [AUTOMATED]: Prettier Code Styling +======= + +>>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; @@ -95,12 +110,19 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); +<<<<<<< HEAD expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`) ); +======= + + expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value); + const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); +>>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; From c9bbfe8a83eb5739c59ba51f09efa1070c1fd8a5 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Tue, 14 Apr 2020 15:04:35 -0700 Subject: [PATCH 06/26] [AUTOMATED]: Prettier Code Styling --- .../src/core/persistence/browser.test.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index b4ef7a12cb8..10595b65d7e 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -51,6 +51,7 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); +<<<<<<< HEAD <<<<<<< HEAD expect(await persistence.get(key)).to.be.null; @@ -64,6 +65,14 @@ describe('core/persistence/browser', () => { await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); >>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} +======= + + expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value); + const out = await persistence.get(key, blob => + testUser(`test-${blob.uid}`) + ); +>>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; @@ -90,12 +99,16 @@ describe('core/persistence/browser', () => { const persistence = browserSessionPersistence; <<<<<<< HEAD <<<<<<< HEAD +<<<<<<< HEAD ======= >>>>>>> 3c4f7ca0... [AUTOMATED]: Prettier Code Styling ======= >>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} +======= + +>>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; @@ -110,6 +123,7 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); +<<<<<<< HEAD <<<<<<< HEAD expect(await persistence.get(key)).to.be.null; @@ -123,6 +137,14 @@ describe('core/persistence/browser', () => { await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); >>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} +======= + + expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value); + const out = await persistence.get(key, blob => + testUser(`test-${blob.uid}`) + ); +>>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; From 67446ea77ead0d62f97602219003cbed881ca4cb Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Tue, 14 Apr 2020 15:04:35 -0700 Subject: [PATCH 07/26] [AUTOMATED]: License Headers --- .../src/core/persistence/browser.test.ts | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 10595b65d7e..5cea05b4616 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -1,10 +1,6 @@ /** * @license -<<<<<<< HEAD * Copyright 2019 Google LLC -======= - * Copyright 2019 Google Inc. ->>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,28 +47,12 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); -<<<<<<< HEAD -<<<<<<< HEAD expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`) ); -======= - - expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); ->>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} -======= - - expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => - testUser(`test-${blob.uid}`) - ); ->>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; @@ -97,18 +77,6 @@ describe('core/persistence/browser', () => { describe('browserSessionPersistence', () => { const persistence = browserSessionPersistence; -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -======= - ->>>>>>> 3c4f7ca0... [AUTOMATED]: Prettier Code Styling -======= - ->>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} -======= - ->>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; @@ -123,28 +91,12 @@ describe('core/persistence/browser', () => { it('should call instantiator function if provided', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); -<<<<<<< HEAD -<<<<<<< HEAD - - expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => - testUser(`test-${blob.uid}`) - ); -======= - - expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`)); ->>>>>>> 06bdd392... Add persistence layer: index db, in memory, and browser{local, session} -======= expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); const out = await persistence.get(key, blob => testUser(`test-${blob.uid}`) ); ->>>>>>> e6e88190... [AUTOMATED]: Prettier Code Styling expect(out?.uid).to.eql('test-some-uid'); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; From afdce7ea3dd7c2d96e2ff4b504c4e0ee67609181 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 13:46:13 -0700 Subject: [PATCH 08/26] Add persistence manager class --- .../persistence_user_manager.test.ts | 166 ++++++++++++++++++ .../persistence/persistence_user_manager.ts | 109 ++++++++++++ .../src/core/user/token_manager.test.ts | 28 +++ .../auth-exp/src/core/user/token_manager.ts | 33 ++++ .../auth-exp/src/core/user/user_impl.test.ts | 36 ++++ .../auth-exp/src/core/user/user_impl.ts | 42 +++++ 6 files changed, 414 insertions(+) create mode 100644 packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts create mode 100644 packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts new file mode 100644 index 00000000000..f2ed27fd772 --- /dev/null +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -0,0 +1,166 @@ +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as sinon from 'sinon'; +import * as chai from 'chai'; +import { inMemoryPersistence } from './in_memory'; +import { PersistenceType, Persistence } from '.'; +import { expect } from 'chai'; +import { testUser, mockAuth } from '../../../test/mock_auth'; +import { PersistenceUserManager } from './persistence_user_manager'; +import * as sinonChai from 'sinon-chai'; +import { UserImpl } from '../user/user_impl'; + +chai.use(sinonChai); + +function makePersistence( + type = PersistenceType.NONE +): { + persistence: Persistence; + stub: sinon.SinonStubbedInstance; +} { + const persistence: Persistence = { + type, + isAvailable: () => Promise.resolve(true), + set: async () => {}, + get() { + return Promise.resolve(null); + }, + remove: async () => {} + }; + + const stub = sinon.stub(persistence); + return { persistence, stub }; +} + +describe('core/persistence/persistence_user_manager', () => { + describe('create', () => { + it('defaults to inMemory if no list provided', async () => { + const manager = await PersistenceUserManager.create(mockAuth, []); + expect(manager.persistence).to.eq(inMemoryPersistence); + }); + + it('searches in order for a user', async () => { + const a = makePersistence(); + const b = makePersistence(); + const c = makePersistence(); + const search = [a.persistence, b.persistence, c.persistence]; + b.stub.get.returns(Promise.resolve(testUser('uid'))); + + const out = await PersistenceUserManager.create(mockAuth, search); + expect(out.persistence).to.eq(b.persistence); + expect(a.stub.get).to.have.been.calledOnce; + expect(b.stub.get).to.have.been.calledOnce; + expect(c.stub.get).not.to.have.been.called; + }); + + it('uses default user key if none provided', async () => { + const {stub, persistence} = makePersistence(); + await PersistenceUserManager.create(mockAuth, [persistence]); + expect(stub.get).to.have.been.calledWith('firebase:authUser:test-api-key:test-app'); + }); + + it('uses user key if provided', async () => { + const {stub, persistence} = makePersistence(); + await PersistenceUserManager.create(mockAuth, [persistence], 'redirectUser'); + expect(stub.get).to.have.been.calledWith('firebase:redirectUser:test-api-key:test-app'); + }); + + it('returns zeroth persistence if all else fails', async () => { + const a = makePersistence(); + const b = makePersistence(); + const c = makePersistence(); + const search = [a.persistence, b.persistence, c.persistence]; + const out = await PersistenceUserManager.create(mockAuth, search); + expect(out.persistence).to.eq(a.persistence); + expect(a.stub.get).to.have.been.calledOnce; + expect(b.stub.get).to.have.been.calledOnce; + expect(c.stub.get).to.have.been.called; + }); + }); + + describe('manager methods', () => { + let persistenceStub: sinon.SinonStubbedInstance; + let manager: PersistenceUserManager; + + beforeEach(async () => { + const {persistence, stub} = makePersistence(PersistenceType.SESSION); + persistenceStub = stub; + manager = await PersistenceUserManager.create(mockAuth, [persistence]); + }); + + it('#setCurrentUser calls underlying persistence w/ key', async () => { + const user = testUser('uid'); + await manager.setCurrentUser(user); + expect(persistenceStub.set).to.have.been.calledWith( + 'firebase:authUser:test-api-key:test-app', + user + ); + }); + + it('#removeCurrentUser calls underlying persistence', async () => { + await manager.removeCurrentUser(); + expect(persistenceStub.remove).to.have.been.calledWith( + 'firebase:authUser:test-api-key:test-app'); + }); + + it('#getCurrentUser calls with instantiator', async () => { + const rawObject = {}; + const userImplStub = sinon.stub(UserImpl, 'fromPlainObject'); + persistenceStub.get.callsFake((_: string, cb?: (o: { [key: string]: unknown }) => any) => { + return cb!(rawObject); + }); + + await manager.getCurrentUser(); + expect(userImplStub).to.have.been.calledWith(mockAuth, rawObject); + + userImplStub.restore(); + }); + + it('#savePersistenceForRedirect calls through', async () => { + await manager.savePersistenceForRedirect(); + expect(persistenceStub.set).to.have.been.calledWith( + 'firebase:persistence:test-api-key:test-app', + 'SESSION', + ); + }); + + describe('#setPersistence', () => { + it('returns immediately if types match', async () => { + const {persistence: nextPersistence} = makePersistence(PersistenceType.SESSION); + const spy = sinon.spy(manager, 'getCurrentUser'); + await manager.setPersistence(nextPersistence); + expect(spy).not.to.have.been.called; + spy.restore(); + }); + + it('removes current user & sets it in the new persistene', async () => { + const {persistence: nextPersistence, stub: nextStub} = makePersistence(); + const user = testUser('uid'); + persistenceStub.get.returns(Promise.resolve(user)); + + await manager.setPersistence(nextPersistence); + expect(persistenceStub.get).to.have.been.called; + expect(persistenceStub.remove).to.have.been.called; + expect(nextStub.set).to.have.been.calledWith( + 'firebase:authUser:test-api-key:test-app', + user + ); + }); + }); + }); +}); diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts new file mode 100644 index 00000000000..bb53458a7bf --- /dev/null +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -0,0 +1,109 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Persistence } from '../persistence'; +import { User } from '../../model/user'; +import { ApiKey, AppName, Auth } from '../../model/auth'; +import { inMemoryPersistence } from './in_memory'; +import { UserImpl } from '../user/user_impl'; + +export const AUTH_USER_KEY_NAME_ = 'authUser'; +export const PERSISTENCE_KEY_NAME_ = 'persistence'; +const PERSISTENCE_NAMESPACE_ = 'firebase'; + +export function persistenceKeyName_( + key: string, + apiKey: ApiKey, + appName: AppName +): string { + return `${PERSISTENCE_NAMESPACE_}:${key}:${apiKey}:${appName}`; +} + +export class PersistenceUserManager { + private constructor( + public persistence: Persistence, + private readonly auth: Auth, + private readonly userKey: string + ) {} + + fullKeyName_(key: string): string { + const { config, name } = this.auth; + return persistenceKeyName_(key, config.apiKey, name); + } + + setCurrentUser(user: User): Promise { + return this.persistence.set(this.fullKeyName_(this.userKey), user); + } + + getCurrentUser(): Promise { + return this.persistence.get( + this.fullKeyName_(this.userKey), + (o: { [key: string]: unknown }) => UserImpl.fromPlainObject(this.auth, o) + ); + } + + removeCurrentUser(): Promise { + return this.persistence.remove(this.fullKeyName_(this.userKey)); + } + + savePersistenceForRedirect(): Promise { + return this.persistence.set( + this.fullKeyName_(PERSISTENCE_KEY_NAME_), + this.persistence.type + ); + } + + async setPersistence(newPersistence: Persistence): Promise { + if (this.persistence.type === newPersistence.type) { + return; + } + + const currentUser = await this.getCurrentUser(); + await this.removeCurrentUser(); + + this.persistence = newPersistence; + + if (currentUser) { + return this.setCurrentUser(currentUser); + } + } + + static async create( + auth: Auth, + persistenceHierarchy: Persistence[], + userKey = AUTH_USER_KEY_NAME_ + ): Promise { + if (!persistenceHierarchy.length) { + return new PersistenceUserManager(inMemoryPersistence, auth, userKey); + } + + const key = persistenceKeyName_(userKey, auth.config.apiKey, auth.name); + for (const persistence of persistenceHierarchy) { + if (await persistence.get(key)) { + return new PersistenceUserManager(persistence, auth, userKey); + } + } + + // Check all the available storage options. + // TODO: Migrate from local storage to indexedDB + // TODO: Clear other forms once one is found + + // All else failed, fall back to zeroth persistence + // TODO: Modify this to support non-browser devices + return new PersistenceUserManager(persistenceHierarchy[0], auth, userKey); + } +} diff --git a/packages-exp/auth-exp/src/core/user/token_manager.test.ts b/packages-exp/auth-exp/src/core/user/token_manager.test.ts index d15420d99b1..136901bc882 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.test.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.test.ts @@ -20,6 +20,7 @@ import * as chaiAsPromised from 'chai-as-promised'; import { createSandbox } from 'sinon'; import { IdTokenResponse } from '../../model/id_token'; import { StsTokenManager, TOKEN_REFRESH_BUFFER_MS } from './token_manager'; +import { FirebaseError } from '@firebase/util'; use(chaiAsPromised); @@ -110,4 +111,31 @@ describe('core/user/token_manager', () => { expect(tokens.refreshToken).to.eq('refresh'); }); }); + + describe('fromPlainObject', () => { + const fpo = (obj: {[key: string]: unknown}) => StsTokenManager.fromPlainObject('app', obj); + const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; + + it('throws if refresh token is not a string', () => { + expect(() => fpo({refreshToken: 45, accessToken: 't', expirationTime: 3})) + .to.throw(FirebaseError, errorString); + }); + + it('throws if access token is not a string', () => { + expect(() => fpo({refreshToken: 't', accessToken: 45, expirationTime: 3})) + .to.throw(FirebaseError, errorString); + }); + + it('throws if expiration time is not a number', () => { + expect(() => fpo({refreshToken: 't', accessToken: 't', expirationTime: 'lol'})) + .to.throw(FirebaseError, errorString); + }); + + it('builds an object correctly', () => { + const manager = fpo({refreshToken: 'r', accessToken: 'a', expirationTime: 45}); + expect(manager.accessToken).to.eq('a'); + expect(manager.refreshToken).to.eq('r'); + expect(manager.expirationTime).to.eq(45); + }); + }); }); diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index 49bd349f03b..455e13fdb4d 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -16,6 +16,7 @@ */ import { IdTokenResponse } from '../../model/id_token'; +import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; /** * The number of milliseconds before the official expiration time of a token @@ -61,6 +62,38 @@ export class StsTokenManager { throw new Error('StsTokenManager: token refresh not implemented'); } + toPlainObject(): object { + return { + refreshToken: this.refreshToken, + accessToken: this.accessToken, + expirationTime: this.expirationTime + }; + } + + static fromPlainObject( + appName: string, + object: { [key: string]: unknown } + ): StsTokenManager { + const { refreshToken, accessToken, expirationTime } = object; + const internalError = AUTH_ERROR_FACTORY.create( + AuthErrorCode.INTERNAL_ERROR, + { appName } + ); + if (refreshToken && typeof refreshToken !== 'string') { + throw internalError; + } + if (accessToken && typeof accessToken !== 'string') { + throw internalError; + } + if (expirationTime && typeof expirationTime !== 'number') { + throw internalError; + } + + const manager = new StsTokenManager(); + Object.assign(manager, { refreshToken, accessToken, expirationTime }); + return manager; + } + // TODO: There are a few more methods in here that need implemented: // # toPlainObject // # fromPlainObject diff --git a/packages-exp/auth-exp/src/core/user/user_impl.test.ts b/packages-exp/auth-exp/src/core/user/user_impl.test.ts index 26fbe161dc6..062079927e7 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.test.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.test.ts @@ -21,6 +21,7 @@ import { mockAuth } from '../../../test/mock_auth'; import { IdTokenResponse } from '../../model/id_token'; import { StsTokenManager } from './token_manager'; import { UserImpl } from './user_impl'; +import { FirebaseError } from '@firebase/util'; use(chaiAsPromised); @@ -105,4 +106,39 @@ describe('core/user/user_impl', () => { expect(() => user.delete()).to.throw(); }); }); + + describe('fromPlainObject', () => { + const fpo = UserImpl.fromPlainObject; + const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; + + it('throws an error if uid is not present', () => { + expect(() => fpo(mockAuth, {name: 'foo'})).to.throw(FirebaseError, errorString); + }); + + it('throws if a key is not undefined or string', () => { + expect(() => fpo(mockAuth, {uid: 'foo', displayName: 3})).to.throw(FirebaseError, errorString); + }); + + it('fills out a user object properly', () => { + const params = { + uid: 'uid', + stsTokenManager: { + accessToken: 'access-token', + refreshToken: 'refresh-token', + expirationTime: 3, + }, + displayName: 'name', + email: 'email', + phoneNumber: 'number', + photoURL: 'photo', + }; + + const user = fpo(mockAuth, params); + expect(user.uid).to.eq(params.uid); + expect(user.displayName).to.eq(params.displayName); + expect(user.email).to.eq(params.email); + expect(user.phoneNumber).to.eq(params.phoneNumber); + expect(user.photoURL).to.eq(params.photoURL); + }); + }); }); diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index c3d676716e3..c28005b3ca4 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -20,6 +20,7 @@ import { IdTokenResult } from '../../model/id_token'; import { User } from '../../model/user'; import { ProviderId } from '../providers'; import { StsTokenManager } from './token_manager'; +import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; export interface UserParameters { uid: string; @@ -80,4 +81,45 @@ export class UserImpl implements User { delete(): Promise { throw new Error('Method not implemented.'); } + + static fromPlainObject(auth: Auth, object: { [key: string]: unknown }): User { + const { + uid, + stsTokenManager: plainObjectTokenManager, + displayName, + email, + phoneNumber, + photoURL + } = object; + + const internalError = AUTH_ERROR_FACTORY.create( + AuthErrorCode.INTERNAL_ERROR, + { appName: auth.name } + ); + function assertStringIfExists(value: unknown): string | undefined { + if (typeof value !== 'string' && typeof value !== 'undefined') { + throw internalError; + } + return value; + } + + if (typeof uid !== 'string' || !plainObjectTokenManager) { + throw internalError; + } + + const stsTokenManager = StsTokenManager.fromPlainObject( + auth.name, + plainObjectTokenManager as { [key: string]: unknown }, + ); + + return new UserImpl({ + uid, + auth, + stsTokenManager, + displayName: assertStringIfExists(displayName), + email: assertStringIfExists(email), + phoneNumber: assertStringIfExists(phoneNumber), + photoURL: assertStringIfExists(photoURL) + }); + } } From ef91d2bd0325ba641a4c6f09f416914948c91682 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 14:07:18 -0700 Subject: [PATCH 09/26] [AUTOMATED]: Prettier Code Styling --- .../persistence_user_manager.test.ts | 44 +++++++++++++------ .../src/core/user/token_manager.test.ts | 27 ++++++++---- .../auth-exp/src/core/user/user_impl.test.ts | 17 ++++--- .../auth-exp/src/core/user/user_impl.ts | 2 +- 4 files changed, 61 insertions(+), 29 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts index f2ed27fd772..c8bc4ec114d 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -69,15 +69,23 @@ describe('core/persistence/persistence_user_manager', () => { }); it('uses default user key if none provided', async () => { - const {stub, persistence} = makePersistence(); + const { stub, persistence } = makePersistence(); await PersistenceUserManager.create(mockAuth, [persistence]); - expect(stub.get).to.have.been.calledWith('firebase:authUser:test-api-key:test-app'); + expect(stub.get).to.have.been.calledWith( + 'firebase:authUser:test-api-key:test-app' + ); }); it('uses user key if provided', async () => { - const {stub, persistence} = makePersistence(); - await PersistenceUserManager.create(mockAuth, [persistence], 'redirectUser'); - expect(stub.get).to.have.been.calledWith('firebase:redirectUser:test-api-key:test-app'); + const { stub, persistence } = makePersistence(); + await PersistenceUserManager.create( + mockAuth, + [persistence], + 'redirectUser' + ); + expect(stub.get).to.have.been.calledWith( + 'firebase:redirectUser:test-api-key:test-app' + ); }); it('returns zeroth persistence if all else fails', async () => { @@ -98,7 +106,7 @@ describe('core/persistence/persistence_user_manager', () => { let manager: PersistenceUserManager; beforeEach(async () => { - const {persistence, stub} = makePersistence(PersistenceType.SESSION); + const { persistence, stub } = makePersistence(PersistenceType.SESSION); persistenceStub = stub; manager = await PersistenceUserManager.create(mockAuth, [persistence]); }); @@ -115,15 +123,18 @@ describe('core/persistence/persistence_user_manager', () => { it('#removeCurrentUser calls underlying persistence', async () => { await manager.removeCurrentUser(); expect(persistenceStub.remove).to.have.been.calledWith( - 'firebase:authUser:test-api-key:test-app'); + 'firebase:authUser:test-api-key:test-app' + ); }); it('#getCurrentUser calls with instantiator', async () => { const rawObject = {}; const userImplStub = sinon.stub(UserImpl, 'fromPlainObject'); - persistenceStub.get.callsFake((_: string, cb?: (o: { [key: string]: unknown }) => any) => { - return cb!(rawObject); - }); + persistenceStub.get.callsFake( + (_: string, cb?: (o: { [key: string]: unknown }) => any) => { + return cb!(rawObject); + } + ); await manager.getCurrentUser(); expect(userImplStub).to.have.been.calledWith(mockAuth, rawObject); @@ -135,13 +146,15 @@ describe('core/persistence/persistence_user_manager', () => { await manager.savePersistenceForRedirect(); expect(persistenceStub.set).to.have.been.calledWith( 'firebase:persistence:test-api-key:test-app', - 'SESSION', + 'SESSION' ); }); - + describe('#setPersistence', () => { it('returns immediately if types match', async () => { - const {persistence: nextPersistence} = makePersistence(PersistenceType.SESSION); + const { persistence: nextPersistence } = makePersistence( + PersistenceType.SESSION + ); const spy = sinon.spy(manager, 'getCurrentUser'); await manager.setPersistence(nextPersistence); expect(spy).not.to.have.been.called; @@ -149,7 +162,10 @@ describe('core/persistence/persistence_user_manager', () => { }); it('removes current user & sets it in the new persistene', async () => { - const {persistence: nextPersistence, stub: nextStub} = makePersistence(); + const { + persistence: nextPersistence, + stub: nextStub + } = makePersistence(); const user = testUser('uid'); persistenceStub.get.returns(Promise.resolve(user)); diff --git a/packages-exp/auth-exp/src/core/user/token_manager.test.ts b/packages-exp/auth-exp/src/core/user/token_manager.test.ts index 136901bc882..0a3204717e8 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.test.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.test.ts @@ -113,26 +113,35 @@ describe('core/user/token_manager', () => { }); describe('fromPlainObject', () => { - const fpo = (obj: {[key: string]: unknown}) => StsTokenManager.fromPlainObject('app', obj); - const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; + const fpo = (obj: { [key: string]: unknown }) => + StsTokenManager.fromPlainObject('app', obj); + const errorString = + 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; it('throws if refresh token is not a string', () => { - expect(() => fpo({refreshToken: 45, accessToken: 't', expirationTime: 3})) - .to.throw(FirebaseError, errorString); + expect(() => + fpo({ refreshToken: 45, accessToken: 't', expirationTime: 3 }) + ).to.throw(FirebaseError, errorString); }); it('throws if access token is not a string', () => { - expect(() => fpo({refreshToken: 't', accessToken: 45, expirationTime: 3})) - .to.throw(FirebaseError, errorString); + expect(() => + fpo({ refreshToken: 't', accessToken: 45, expirationTime: 3 }) + ).to.throw(FirebaseError, errorString); }); it('throws if expiration time is not a number', () => { - expect(() => fpo({refreshToken: 't', accessToken: 't', expirationTime: 'lol'})) - .to.throw(FirebaseError, errorString); + expect(() => + fpo({ refreshToken: 't', accessToken: 't', expirationTime: 'lol' }) + ).to.throw(FirebaseError, errorString); }); it('builds an object correctly', () => { - const manager = fpo({refreshToken: 'r', accessToken: 'a', expirationTime: 45}); + const manager = fpo({ + refreshToken: 'r', + accessToken: 'a', + expirationTime: 45 + }); expect(manager.accessToken).to.eq('a'); expect(manager.refreshToken).to.eq('r'); expect(manager.expirationTime).to.eq(45); diff --git a/packages-exp/auth-exp/src/core/user/user_impl.test.ts b/packages-exp/auth-exp/src/core/user/user_impl.test.ts index 062079927e7..16aaad52d97 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.test.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.test.ts @@ -109,14 +109,21 @@ describe('core/user/user_impl', () => { describe('fromPlainObject', () => { const fpo = UserImpl.fromPlainObject; - const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; + const errorString = + 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; it('throws an error if uid is not present', () => { - expect(() => fpo(mockAuth, {name: 'foo'})).to.throw(FirebaseError, errorString); + expect(() => fpo(mockAuth, { name: 'foo' })).to.throw( + FirebaseError, + errorString + ); }); it('throws if a key is not undefined or string', () => { - expect(() => fpo(mockAuth, {uid: 'foo', displayName: 3})).to.throw(FirebaseError, errorString); + expect(() => fpo(mockAuth, { uid: 'foo', displayName: 3 })).to.throw( + FirebaseError, + errorString + ); }); it('fills out a user object properly', () => { @@ -125,12 +132,12 @@ describe('core/user/user_impl', () => { stsTokenManager: { accessToken: 'access-token', refreshToken: 'refresh-token', - expirationTime: 3, + expirationTime: 3 }, displayName: 'name', email: 'email', phoneNumber: 'number', - photoURL: 'photo', + photoURL: 'photo' }; const user = fpo(mockAuth, params); diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index c28005b3ca4..d8a075eaf23 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -109,7 +109,7 @@ export class UserImpl implements User { const stsTokenManager = StsTokenManager.fromPlainObject( auth.name, - plainObjectTokenManager as { [key: string]: unknown }, + plainObjectTokenManager as { [key: string]: unknown } ); return new UserImpl({ From 0d8659db11dcb4ba570d747469ea96a3374bafdd Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 14:07:18 -0700 Subject: [PATCH 10/26] [AUTOMATED]: License Headers --- .../auth-exp/src/core/persistence/persistence_user_manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index bb53458a7bf..77f1ab64c8a 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -1,6 +1,6 @@ /** * @license - * Copyright 2019 Google Inc. + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From a15679c39ba8f7fcc3871c24eed38cde94ead6e1 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 14:10:47 -0700 Subject: [PATCH 11/26] Formatting --- packages-exp/auth-exp/src/core/persistence/browser.test.ts | 1 + packages-exp/auth-exp/src/core/persistence/in_memory.test.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 5cea05b4616..838b75d6af3 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -77,6 +77,7 @@ describe('core/persistence/browser', () => { describe('browserSessionPersistence', () => { const persistence = browserSessionPersistence; + it('should work with persistence type', async () => { const key = 'my-super-special-persistence-type'; const value = PersistenceType.SESSION; diff --git a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts index 767e458c738..109b6aa69bb 100644 --- a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts @@ -37,6 +37,7 @@ describe('core/persistence/in_memory', () => { const key = 'my-super-special-user'; const value = testUser('uid'); expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value); expect(await persistence.get(key)).to.eql(value); expect(await persistence.get('other-key')).to.be.null; From 4254fac30c434dd80a9ff5b570f43b3b90a80a9a Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 14:11:12 -0700 Subject: [PATCH 12/26] Formatting --- packages-exp/auth-exp/src/core/persistence/in_memory.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts index 109b6aa69bb..c6858d9bad1 100644 --- a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts @@ -36,8 +36,8 @@ describe('core/persistence/in_memory', () => { it('should work with user', async () => { const key = 'my-super-special-user'; const value = testUser('uid'); - expect(await persistence.get(key)).to.be.null; + expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); expect(await persistence.get(key)).to.eql(value); expect(await persistence.get('other-key')).to.be.null; From 2711c51b2727da688ba2fab0e5a808f035e674b4 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 15:26:13 -0700 Subject: [PATCH 13/26] Address review comments --- .../auth-exp/src/core/persistence/index.ts | 6 ++++- .../src/core/persistence/indexed_db.ts | 5 ++-- .../persistence_user_manager.test.ts | 6 +++-- .../persistence/persistence_user_manager.ts | 24 ++++++++++--------- .../src/core/user/token_manager.test.ts | 10 ++++---- .../auth-exp/src/core/user/token_manager.ts | 3 ++- .../auth-exp/src/core/user/user_impl.test.ts | 7 +++--- .../auth-exp/src/core/user/user_impl.ts | 3 ++- 8 files changed, 36 insertions(+), 28 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/index.ts b/packages-exp/auth-exp/src/core/persistence/index.ts index 29bb094a403..c3a3ce05e95 100644 --- a/packages-exp/auth-exp/src/core/persistence/index.ts +++ b/packages-exp/auth-exp/src/core/persistence/index.ts @@ -23,8 +23,12 @@ export enum PersistenceType { NONE = 'NONE' } +export interface PersistedBlob { + [key: string]: unknown; +} + export interface Instantiator { - (blob: { [key: string]: unknown }): T; + (blob: PersistedBlob): T; } export type PersistenceValue = PersistenceType | User; diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index 250531193a5..e0ad380c485 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -19,7 +19,8 @@ import { Persistence, PersistenceType, PersistenceValue, - Instantiator + Instantiator, + PersistedBlob } from '.'; const STORAGE_AVAILABLE_KEY_ = '__sak'; @@ -29,7 +30,7 @@ const DB_VERSION = 1; const DB_OBJECTSTORE_NAME = 'firebaseLocalStorage'; const DB_DATA_KEYPATH = 'fbase_key'; -type DBValue = { [key: string]: unknown } | string; +type DBValue = PersistedBlob | string; interface DBObject { [DB_DATA_KEYPATH]: string; diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts index c8bc4ec114d..b6a28c60556 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -18,7 +18,7 @@ import * as sinon from 'sinon'; import * as chai from 'chai'; import { inMemoryPersistence } from './in_memory'; -import { PersistenceType, Persistence } from '.'; +import { PersistenceType, Persistence, Instantiator } from '.'; import { expect } from 'chai'; import { testUser, mockAuth } from '../../../test/mock_auth'; import { PersistenceUserManager } from './persistence_user_manager'; @@ -131,7 +131,9 @@ describe('core/persistence/persistence_user_manager', () => { const rawObject = {}; const userImplStub = sinon.stub(UserImpl, 'fromPlainObject'); persistenceStub.get.callsFake( - (_: string, cb?: (o: { [key: string]: unknown }) => any) => { + (_: string, cb?: Instantiator) => { + // Call through to the callback, to exercise the instantiator + // provided in PersistenceUserManager return cb!(rawObject); } ); diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index 77f1ab64c8a..6c5dea88350 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Persistence } from '../persistence'; +import { Persistence, PersistedBlob } from '../persistence'; import { User } from '../../model/user'; import { ApiKey, AppName, Auth } from '../../model/auth'; import { inMemoryPersistence } from './in_memory'; @@ -34,35 +34,37 @@ export function persistenceKeyName_( } export class PersistenceUserManager { + private readonly fullUserKey: string; + private readonly fullPersistenceKey: string; private constructor( public persistence: Persistence, private readonly auth: Auth, private readonly userKey: string - ) {} - - fullKeyName_(key: string): string { - const { config, name } = this.auth; - return persistenceKeyName_(key, config.apiKey, name); + ) { + const {config, name} = this.auth; + this.fullUserKey = persistenceKeyName_(this.userKey, config.apiKey, name); + this.fullPersistenceKey = persistenceKeyName_(PERSISTENCE_KEY_NAME_, config.apiKey, name); } + setCurrentUser(user: User): Promise { - return this.persistence.set(this.fullKeyName_(this.userKey), user); + return this.persistence.set(this.fullUserKey, user); } getCurrentUser(): Promise { return this.persistence.get( - this.fullKeyName_(this.userKey), - (o: { [key: string]: unknown }) => UserImpl.fromPlainObject(this.auth, o) + this.fullUserKey, + (blob: PersistedBlob) => UserImpl.fromPlainObject(this.auth, blob) ); } removeCurrentUser(): Promise { - return this.persistence.remove(this.fullKeyName_(this.userKey)); + return this.persistence.remove(this.fullUserKey); } savePersistenceForRedirect(): Promise { return this.persistence.set( - this.fullKeyName_(PERSISTENCE_KEY_NAME_), + this.fullPersistenceKey, this.persistence.type ); } diff --git a/packages-exp/auth-exp/src/core/user/token_manager.test.ts b/packages-exp/auth-exp/src/core/user/token_manager.test.ts index 0a3204717e8..76ba1e35c32 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.test.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.test.ts @@ -113,31 +113,29 @@ describe('core/user/token_manager', () => { }); describe('fromPlainObject', () => { - const fpo = (obj: { [key: string]: unknown }) => - StsTokenManager.fromPlainObject('app', obj); const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; it('throws if refresh token is not a string', () => { expect(() => - fpo({ refreshToken: 45, accessToken: 't', expirationTime: 3 }) + StsTokenManager.fromPlainObject('app', { refreshToken: 45, accessToken: 't', expirationTime: 3 }) ).to.throw(FirebaseError, errorString); }); it('throws if access token is not a string', () => { expect(() => - fpo({ refreshToken: 't', accessToken: 45, expirationTime: 3 }) + StsTokenManager.fromPlainObject('app', { refreshToken: 't', accessToken: 45, expirationTime: 3 }) ).to.throw(FirebaseError, errorString); }); it('throws if expiration time is not a number', () => { expect(() => - fpo({ refreshToken: 't', accessToken: 't', expirationTime: 'lol' }) + StsTokenManager.fromPlainObject('app', { refreshToken: 't', accessToken: 't', expirationTime: 'lol' }) ).to.throw(FirebaseError, errorString); }); it('builds an object correctly', () => { - const manager = fpo({ + const manager = StsTokenManager.fromPlainObject('app', { refreshToken: 'r', accessToken: 'a', expirationTime: 45 diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index 455e13fdb4d..dca71a508a4 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -17,6 +17,7 @@ import { IdTokenResponse } from '../../model/id_token'; import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; +import { PersistedBlob } from '../persistence'; /** * The number of milliseconds before the official expiration time of a token @@ -72,7 +73,7 @@ export class StsTokenManager { static fromPlainObject( appName: string, - object: { [key: string]: unknown } + object: PersistedBlob, ): StsTokenManager { const { refreshToken, accessToken, expirationTime } = object; const internalError = AUTH_ERROR_FACTORY.create( diff --git a/packages-exp/auth-exp/src/core/user/user_impl.test.ts b/packages-exp/auth-exp/src/core/user/user_impl.test.ts index 16aaad52d97..7e95c059740 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.test.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.test.ts @@ -108,19 +108,18 @@ describe('core/user/user_impl', () => { }); describe('fromPlainObject', () => { - const fpo = UserImpl.fromPlainObject; const errorString = 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; it('throws an error if uid is not present', () => { - expect(() => fpo(mockAuth, { name: 'foo' })).to.throw( + expect(() => UserImpl.fromPlainObject(mockAuth, { name: 'foo' })).to.throw( FirebaseError, errorString ); }); it('throws if a key is not undefined or string', () => { - expect(() => fpo(mockAuth, { uid: 'foo', displayName: 3 })).to.throw( + expect(() => UserImpl.fromPlainObject(mockAuth, { uid: 'foo', displayName: 3 })).to.throw( FirebaseError, errorString ); @@ -140,7 +139,7 @@ describe('core/user/user_impl', () => { photoURL: 'photo' }; - const user = fpo(mockAuth, params); + const user = UserImpl.fromPlainObject(mockAuth, params); expect(user.uid).to.eq(params.uid); expect(user.displayName).to.eq(params.displayName); expect(user.email).to.eq(params.email); diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index d8a075eaf23..7f5c72fd3b0 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -21,6 +21,7 @@ import { User } from '../../model/user'; import { ProviderId } from '../providers'; import { StsTokenManager } from './token_manager'; import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; +import { PersistedBlob } from '../persistence'; export interface UserParameters { uid: string; @@ -82,7 +83,7 @@ export class UserImpl implements User { throw new Error('Method not implemented.'); } - static fromPlainObject(auth: Auth, object: { [key: string]: unknown }): User { + static fromPlainObject(auth: Auth, object: PersistedBlob): User { const { uid, stsTokenManager: plainObjectTokenManager, From ed0ff67dc33a63bc27e41c73ab67afba455a7de7 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 15:26:21 -0700 Subject: [PATCH 14/26] [AUTOMATED]: Prettier Code Styling --- .../persistence_user_manager.test.ts | 12 +++++------- .../persistence/persistence_user_manager.ts | 19 +++++++++---------- .../src/core/user/token_manager.test.ts | 18 +++++++++++++++--- .../auth-exp/src/core/user/token_manager.ts | 2 +- .../auth-exp/src/core/user/user_impl.test.ts | 14 ++++++-------- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts index b6a28c60556..239eb14f555 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -130,13 +130,11 @@ describe('core/persistence/persistence_user_manager', () => { it('#getCurrentUser calls with instantiator', async () => { const rawObject = {}; const userImplStub = sinon.stub(UserImpl, 'fromPlainObject'); - persistenceStub.get.callsFake( - (_: string, cb?: Instantiator) => { - // Call through to the callback, to exercise the instantiator - // provided in PersistenceUserManager - return cb!(rawObject); - } - ); + persistenceStub.get.callsFake((_: string, cb?: Instantiator) => { + // Call through to the callback, to exercise the instantiator + // provided in PersistenceUserManager + return cb!(rawObject); + }); await manager.getCurrentUser(); expect(userImplStub).to.have.been.calledWith(mockAuth, rawObject); diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index 6c5dea88350..9534afa42ff 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -41,20 +41,22 @@ export class PersistenceUserManager { private readonly auth: Auth, private readonly userKey: string ) { - const {config, name} = this.auth; + const { config, name } = this.auth; this.fullUserKey = persistenceKeyName_(this.userKey, config.apiKey, name); - this.fullPersistenceKey = persistenceKeyName_(PERSISTENCE_KEY_NAME_, config.apiKey, name); + this.fullPersistenceKey = persistenceKeyName_( + PERSISTENCE_KEY_NAME_, + config.apiKey, + name + ); } - setCurrentUser(user: User): Promise { return this.persistence.set(this.fullUserKey, user); } getCurrentUser(): Promise { - return this.persistence.get( - this.fullUserKey, - (blob: PersistedBlob) => UserImpl.fromPlainObject(this.auth, blob) + return this.persistence.get(this.fullUserKey, (blob: PersistedBlob) => + UserImpl.fromPlainObject(this.auth, blob) ); } @@ -63,10 +65,7 @@ export class PersistenceUserManager { } savePersistenceForRedirect(): Promise { - return this.persistence.set( - this.fullPersistenceKey, - this.persistence.type - ); + return this.persistence.set(this.fullPersistenceKey, this.persistence.type); } async setPersistence(newPersistence: Persistence): Promise { diff --git a/packages-exp/auth-exp/src/core/user/token_manager.test.ts b/packages-exp/auth-exp/src/core/user/token_manager.test.ts index 76ba1e35c32..24c13572825 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.test.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.test.ts @@ -118,19 +118,31 @@ describe('core/user/token_manager', () => { it('throws if refresh token is not a string', () => { expect(() => - StsTokenManager.fromPlainObject('app', { refreshToken: 45, accessToken: 't', expirationTime: 3 }) + StsTokenManager.fromPlainObject('app', { + refreshToken: 45, + accessToken: 't', + expirationTime: 3 + }) ).to.throw(FirebaseError, errorString); }); it('throws if access token is not a string', () => { expect(() => - StsTokenManager.fromPlainObject('app', { refreshToken: 't', accessToken: 45, expirationTime: 3 }) + StsTokenManager.fromPlainObject('app', { + refreshToken: 't', + accessToken: 45, + expirationTime: 3 + }) ).to.throw(FirebaseError, errorString); }); it('throws if expiration time is not a number', () => { expect(() => - StsTokenManager.fromPlainObject('app', { refreshToken: 't', accessToken: 't', expirationTime: 'lol' }) + StsTokenManager.fromPlainObject('app', { + refreshToken: 't', + accessToken: 't', + expirationTime: 'lol' + }) ).to.throw(FirebaseError, errorString); }); diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index dca71a508a4..e129bb01e86 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -73,7 +73,7 @@ export class StsTokenManager { static fromPlainObject( appName: string, - object: PersistedBlob, + object: PersistedBlob ): StsTokenManager { const { refreshToken, accessToken, expirationTime } = object; const internalError = AUTH_ERROR_FACTORY.create( diff --git a/packages-exp/auth-exp/src/core/user/user_impl.test.ts b/packages-exp/auth-exp/src/core/user/user_impl.test.ts index 7e95c059740..4edbd37043c 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.test.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.test.ts @@ -112,17 +112,15 @@ describe('core/user/user_impl', () => { 'Firebase: An internal AuthError has occurred. (auth/internal-error).'; it('throws an error if uid is not present', () => { - expect(() => UserImpl.fromPlainObject(mockAuth, { name: 'foo' })).to.throw( - FirebaseError, - errorString - ); + expect(() => + UserImpl.fromPlainObject(mockAuth, { name: 'foo' }) + ).to.throw(FirebaseError, errorString); }); it('throws if a key is not undefined or string', () => { - expect(() => UserImpl.fromPlainObject(mockAuth, { uid: 'foo', displayName: 3 })).to.throw( - FirebaseError, - errorString - ); + expect(() => + UserImpl.fromPlainObject(mockAuth, { uid: 'foo', displayName: 3 }) + ).to.throw(FirebaseError, errorString); }); it('fills out a user object properly', () => { From a1cbef80d8ad2fbea9bd48943a2d642d27ca085e Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 16:21:03 -0700 Subject: [PATCH 15/26] Add util/assert --- .../auth-exp/src/core/user/token_manager.ts | 21 ++++--------- .../auth-exp/src/core/user/user_impl.ts | 20 ++++-------- packages-exp/auth-exp/src/core/util/assert.ts | 31 +++++++++++++++++++ 3 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 packages-exp/auth-exp/src/core/util/assert.ts diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index e129bb01e86..53119b6c756 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -16,8 +16,8 @@ */ import { IdTokenResponse } from '../../model/id_token'; -import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; import { PersistedBlob } from '../persistence'; +import { assertType } from '../util/assert'; /** * The number of milliseconds before the official expiration time of a token @@ -76,22 +76,13 @@ export class StsTokenManager { object: PersistedBlob ): StsTokenManager { const { refreshToken, accessToken, expirationTime } = object; - const internalError = AUTH_ERROR_FACTORY.create( - AuthErrorCode.INTERNAL_ERROR, - { appName } - ); - if (refreshToken && typeof refreshToken !== 'string') { - throw internalError; - } - if (accessToken && typeof accessToken !== 'string') { - throw internalError; - } - if (expirationTime && typeof expirationTime !== 'number') { - throw internalError; - } const manager = new StsTokenManager(); - Object.assign(manager, { refreshToken, accessToken, expirationTime }); + Object.assign>(manager, { + refreshToken: assertType(refreshToken, 'string', appName), + accessToken: assertType(accessToken, 'string', appName), + expirationTime: assertType(expirationTime, 'number', appName), + }); return manager; } diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index 7f5c72fd3b0..d1426de5d8d 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -20,8 +20,8 @@ import { IdTokenResult } from '../../model/id_token'; import { User } from '../../model/user'; import { ProviderId } from '../providers'; import { StsTokenManager } from './token_manager'; -import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; import { PersistedBlob } from '../persistence'; +import { assert, assertType } from '../util/assert'; export interface UserParameters { uid: string; @@ -93,28 +93,20 @@ export class UserImpl implements User { photoURL } = object; - const internalError = AUTH_ERROR_FACTORY.create( - AuthErrorCode.INTERNAL_ERROR, - { appName: auth.name } - ); function assertStringIfExists(value: unknown): string | undefined { - if (typeof value !== 'string' && typeof value !== 'undefined') { - throw internalError; - } - return value; + assert(typeof value === 'string' || typeof value === 'undefined', auth.name); + return value as string | undefined; } - if (typeof uid !== 'string' || !plainObjectTokenManager) { - throw internalError; - } + assert(uid && plainObjectTokenManager, auth.name); const stsTokenManager = StsTokenManager.fromPlainObject( auth.name, - plainObjectTokenManager as { [key: string]: unknown } + plainObjectTokenManager as PersistedBlob, ); return new UserImpl({ - uid, + uid: assertType(uid, 'string', auth.name), auth, stsTokenManager, displayName: assertStringIfExists(displayName), diff --git a/packages-exp/auth-exp/src/core/util/assert.ts b/packages-exp/auth-exp/src/core/util/assert.ts new file mode 100644 index 00000000000..58e21eae0a6 --- /dev/null +++ b/packages-exp/auth-exp/src/core/util/assert.ts @@ -0,0 +1,31 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {AUTH_ERROR_FACTORY, AuthErrorCode} from '../errors'; + +export function assert(expression: T|null|undefined, appName: string): T { + if (!expression) { + throw AUTH_ERROR_FACTORY.create(AuthErrorCode.INTERNAL_ERROR, {appName}); + } + + return expression; +} + +export function assertType(expression: unknown, expected: string, appName: string): T { + assert(typeof expression === expected, appName); + return expression as T; +} From f1cfec280bc78f4474589a73e68759766d035df3 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Thu, 16 Apr 2020 16:21:11 -0700 Subject: [PATCH 16/26] [AUTOMATED]: Prettier Code Styling --- .../auth-exp/src/core/user/token_manager.ts | 4 ++-- packages-exp/auth-exp/src/core/user/user_impl.ts | 7 +++++-- packages-exp/auth-exp/src/core/util/assert.ts | 15 +++++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index 53119b6c756..b464bba92b6 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -78,10 +78,10 @@ export class StsTokenManager { const { refreshToken, accessToken, expirationTime } = object; const manager = new StsTokenManager(); - Object.assign>(manager, { + Object.assign>(manager, { refreshToken: assertType(refreshToken, 'string', appName), accessToken: assertType(accessToken, 'string', appName), - expirationTime: assertType(expirationTime, 'number', appName), + expirationTime: assertType(expirationTime, 'number', appName) }); return manager; } diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index d1426de5d8d..a82c1e27f64 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -94,7 +94,10 @@ export class UserImpl implements User { } = object; function assertStringIfExists(value: unknown): string | undefined { - assert(typeof value === 'string' || typeof value === 'undefined', auth.name); + assert( + typeof value === 'string' || typeof value === 'undefined', + auth.name + ); return value as string | undefined; } @@ -102,7 +105,7 @@ export class UserImpl implements User { const stsTokenManager = StsTokenManager.fromPlainObject( auth.name, - plainObjectTokenManager as PersistedBlob, + plainObjectTokenManager as PersistedBlob ); return new UserImpl({ diff --git a/packages-exp/auth-exp/src/core/util/assert.ts b/packages-exp/auth-exp/src/core/util/assert.ts index 58e21eae0a6..30bad5081a2 100644 --- a/packages-exp/auth-exp/src/core/util/assert.ts +++ b/packages-exp/auth-exp/src/core/util/assert.ts @@ -15,17 +15,24 @@ * limitations under the License. */ -import {AUTH_ERROR_FACTORY, AuthErrorCode} from '../errors'; +import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors'; -export function assert(expression: T|null|undefined, appName: string): T { +export function assert( + expression: T | null | undefined, + appName: string +): T { if (!expression) { - throw AUTH_ERROR_FACTORY.create(AuthErrorCode.INTERNAL_ERROR, {appName}); + throw AUTH_ERROR_FACTORY.create(AuthErrorCode.INTERNAL_ERROR, { appName }); } return expression; } -export function assertType(expression: unknown, expected: string, appName: string): T { +export function assertType( + expression: unknown, + expected: string, + appName: string +): T { assert(typeof expression === expected, appName); return expression as T; } From eebc8852ccf83b57e38300afe63b8b02498a03d0 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 10:02:24 -0700 Subject: [PATCH 17/26] Update assertType to allow multiple types --- .../auth-exp/src/core/user/user_impl.ts | 18 ++++++------------ packages-exp/auth-exp/src/core/util/assert.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index a82c1e27f64..b2db22218f8 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -93,14 +93,6 @@ export class UserImpl implements User { photoURL } = object; - function assertStringIfExists(value: unknown): string | undefined { - assert( - typeof value === 'string' || typeof value === 'undefined', - auth.name - ); - return value as string | undefined; - } - assert(uid && plainObjectTokenManager, auth.name); const stsTokenManager = StsTokenManager.fromPlainObject( @@ -108,14 +100,16 @@ export class UserImpl implements User { plainObjectTokenManager as PersistedBlob ); + const stringOrUndef = ['string', 'undefined']; + return new UserImpl({ uid: assertType(uid, 'string', auth.name), auth, stsTokenManager, - displayName: assertStringIfExists(displayName), - email: assertStringIfExists(email), - phoneNumber: assertStringIfExists(phoneNumber), - photoURL: assertStringIfExists(photoURL) + displayName: assertType(displayName, stringOrUndef, auth.name), + email: assertType(email, stringOrUndef, auth.name), + phoneNumber: assertType(phoneNumber, stringOrUndef, auth.name), + photoURL: assertType(photoURL, stringOrUndef, auth.name) }); } } diff --git a/packages-exp/auth-exp/src/core/util/assert.ts b/packages-exp/auth-exp/src/core/util/assert.ts index 30bad5081a2..5933479de8e 100644 --- a/packages-exp/auth-exp/src/core/util/assert.ts +++ b/packages-exp/auth-exp/src/core/util/assert.ts @@ -30,9 +30,13 @@ export function assert( export function assertType( expression: unknown, - expected: string, + expected: string|string[], appName: string ): T { - assert(typeof expression === expected, appName); + if (typeof expected === 'string') { + expected = [expected]; + } + + assert(expected.includes(typeof expression), appName); return expression as T; } From 1d93a6d319bbb301a9569eabc10dc99cc7b2a469 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 10:02:33 -0700 Subject: [PATCH 18/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/util/assert.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages-exp/auth-exp/src/core/util/assert.ts b/packages-exp/auth-exp/src/core/util/assert.ts index 5933479de8e..47290324534 100644 --- a/packages-exp/auth-exp/src/core/util/assert.ts +++ b/packages-exp/auth-exp/src/core/util/assert.ts @@ -30,7 +30,7 @@ export function assert( export function assertType( expression: unknown, - expected: string|string[], + expected: string | string[], appName: string ): T { if (typeof expected === 'string') { From a6338ece0c5c0f3f906633a48cc9b4febe6bc78b Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 12:52:23 -0700 Subject: [PATCH 19/26] UserImpl toPlainObject --- .../src/core/persistence/indexed_db.test.ts | 21 ++++++++++--------- .../auth-exp/src/core/user/user_impl.ts | 15 +++++++++++-- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts index f12989ec69e..20ad557aae8 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts @@ -15,12 +15,13 @@ * limitations under the License. */ -import * as sinon from 'sinon'; -import { PersistenceType } from '.'; import { expect } from 'chai'; -import { indexedDBLocalPersistence as persistence } from './indexed_db'; -import { User } from '../../model/user'; +import * as sinon from 'sinon'; + import { testUser } from '../../../test/mock_auth'; +import { User } from '../../model/user'; +import { PersistenceType } from './'; +import { indexedDBLocalPersistence as persistence } from './indexed_db'; describe('core/persistence/indexed_db', () => { afterEach(sinon.restore); @@ -42,12 +43,12 @@ describe('core/persistence/indexed_db', () => { expect(await persistence.get(key)).to.be.null; await persistence.set(key, value); - const out = await persistence.get(key, blob => - testUser(`test-${blob.uid}`) - ); - expect(out?.uid).to.eql('test-some-uid'); - await persistence.remove(key); - expect(await persistence.get(key)).to.be.null; + // await persistence.get(key, blob => + // testUser(`test-${blob.uid}`) + // ); + // expect(out?.uid).to.eql('test-some-uid'); + // await persistence.remove(key); + // expect(await persistence.get(key)).to.be.null; }); describe('#isAvaliable', () => { diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index b2db22218f8..e8a5e3af7be 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -18,10 +18,10 @@ import { Auth } from '../../model/auth'; import { IdTokenResult } from '../../model/id_token'; import { User } from '../../model/user'; -import { ProviderId } from '../providers'; -import { StsTokenManager } from './token_manager'; import { PersistedBlob } from '../persistence'; +import { ProviderId } from '../providers'; import { assert, assertType } from '../util/assert'; +import { StsTokenManager } from './token_manager'; export interface UserParameters { uid: string; @@ -83,6 +83,17 @@ export class UserImpl implements User { throw new Error('Method not implemented.'); } + toPlainObject(): PersistedBlob { + return { + uid: this.uid, + stsTokenManager: this.stsTokenManager.toPlainObject(), + displayName: this.displayName, + email: this.email, + phoneNumber: this.phoneNumber, + photoURL: this.phoneNumber, + }; + } + static fromPlainObject(auth: Auth, object: PersistedBlob): User { const { uid, From ede366c08e280d4dd2d05fc062341bb6c4197214 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 13:37:58 -0700 Subject: [PATCH 20/26] Move instantiation into persistence manager, add a toPlainObject as well --- .../src/core/persistence/browser.test.ts | 28 ++++++++----------- .../auth-exp/src/core/persistence/browser.ts | 11 ++------ .../src/core/persistence/in_memory.test.ts | 10 +++---- .../auth-exp/src/core/persistence/index.ts | 9 ++---- .../src/core/persistence/indexed_db.test.ts | 15 ++++------ .../src/core/persistence/indexed_db.ts | 12 +------- .../persistence_user_manager.test.ts | 25 ++++++++--------- .../persistence/persistence_user_manager.ts | 17 ++++++----- .../auth-exp/src/core/user/token_manager.ts | 14 ++++++---- .../auth-exp/src/core/user/user_impl.ts | 8 +++--- packages-exp/auth-exp/src/model/user.d.ts | 2 ++ 11 files changed, 63 insertions(+), 88 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.test.ts b/packages-exp/auth-exp/src/core/persistence/browser.test.ts index 838b75d6af3..cf88cddd5f9 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.test.ts @@ -15,12 +15,12 @@ * limitations under the License. */ -import * as sinon from 'sinon'; -import { PersistenceType } from '.'; import { expect } from 'chai'; -import { browserLocalPersistence, browserSessionPersistence } from './browser'; -import { User } from '../../model/user'; +import * as sinon from 'sinon'; + import { testUser } from '../../../test/mock_auth'; +import { PersistedBlob, PersistenceType } from './'; +import { browserLocalPersistence, browserSessionPersistence } from './browser'; describe('core/persistence/browser', () => { beforeEach(() => { @@ -44,16 +44,14 @@ describe('core/persistence/browser', () => { expect(await persistence.get(key)).to.be.null; }); - it('should call instantiator function if provided', async () => { + it('should return persistedblob from user', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => - testUser(`test-${blob.uid}`) - ); - expect(out?.uid).to.eql('test-some-uid'); + await persistence.set(key, value.toPlainObject()); + const out = await persistence.get(key); + expect(out!['uid']).to.eql(value.uid); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; }); @@ -89,16 +87,14 @@ describe('core/persistence/browser', () => { expect(await persistence.get(key)).to.be.null; }); - it('should call instantiator function if provided', async () => { + it('should emit blobified persisted user', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - const out = await persistence.get(key, blob => - testUser(`test-${blob.uid}`) - ); - expect(out?.uid).to.eql('test-some-uid'); + await persistence.set(key, value.toPlainObject()); + const out = await persistence.get(key); + expect(out!['uid']).to.eql(value.uid); await persistence.remove(key); expect(await persistence.get(key)).to.be.null; }); diff --git a/packages-exp/auth-exp/src/core/persistence/browser.ts b/packages-exp/auth-exp/src/core/persistence/browser.ts index f16a2343697..7ddeacda442 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.ts @@ -15,12 +15,7 @@ * limitations under the License. */ -import { - Persistence, - PersistenceType, - PersistenceValue, - Instantiator -} from '.'; +import { Persistence, PersistenceType, PersistenceValue } from './'; const STORAGE_AVAILABLE_KEY_ = '__sak'; @@ -48,11 +43,9 @@ class BrowserPersistence implements Persistence { async get( key: string, - instantiator?: Instantiator ): Promise { const json = this.storage.getItem(key); - const obj = json ? JSON.parse(json) : null; - return instantiator && obj ? instantiator(obj) : obj; + return json ? JSON.parse(json) : null; } async remove(key: string): Promise { diff --git a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts index c6858d9bad1..4941a142acc 100644 --- a/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/in_memory.test.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { inMemoryPersistence as persistence } from './in_memory'; -import { PersistenceType } from '.'; import { expect } from 'chai'; -import { User } from '../../model/user'; + import { testUser } from '../../../test/mock_auth'; +import { PersistenceType } from './'; +import { inMemoryPersistence as persistence } from './in_memory'; describe('core/persistence/in_memory', () => { it('should work with persistence type', async () => { @@ -38,8 +38,8 @@ describe('core/persistence/in_memory', () => { const value = testUser('uid'); expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - expect(await persistence.get(key)).to.eql(value); + await persistence.set(key, value.toPlainObject()); + expect(await persistence.get(key)).to.eql(value.toPlainObject()); expect(await persistence.get('other-key')).to.be.null; await persistence.remove(key); expect(await persistence.get(key)).to.be.null; diff --git a/packages-exp/auth-exp/src/core/persistence/index.ts b/packages-exp/auth-exp/src/core/persistence/index.ts index c3a3ce05e95..6d5fed957f1 100644 --- a/packages-exp/auth-exp/src/core/persistence/index.ts +++ b/packages-exp/auth-exp/src/core/persistence/index.ts @@ -15,8 +15,6 @@ * limitations under the License. */ -import { User } from '../../model/user'; - export enum PersistenceType { SESSION = 'SESSION', LOCAL = 'LOCAL', @@ -31,15 +29,14 @@ export interface Instantiator { (blob: PersistedBlob): T; } -export type PersistenceValue = PersistenceType | User; +export type PersistenceValue = PersistedBlob | string; export interface Persistence { type: PersistenceType; isAvailable(): Promise; set(key: string, value: PersistenceValue): Promise; get( - key: string, - instantiator?: Instantiator - ): Promise; + key: string + ): Promise; remove(key: string): Promise; } diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts index 20ad557aae8..879f42d2790 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.test.ts @@ -19,7 +19,6 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { testUser } from '../../../test/mock_auth'; -import { User } from '../../model/user'; import { PersistenceType } from './'; import { indexedDBLocalPersistence as persistence } from './indexed_db'; @@ -37,18 +36,16 @@ describe('core/persistence/indexed_db', () => { expect(await persistence.get(key)).to.be.null; }); - it('should call instantiator function if provided', async () => { + it('should return blobified user value', async () => { const key = 'my-super-special-user'; const value = testUser('some-uid'); expect(await persistence.get(key)).to.be.null; - await persistence.set(key, value); - // await persistence.get(key, blob => - // testUser(`test-${blob.uid}`) - // ); - // expect(out?.uid).to.eql('test-some-uid'); - // await persistence.remove(key); - // expect(await persistence.get(key)).to.be.null; + await persistence.set(key, value.toPlainObject()); + const out = await persistence.get(key); + expect(out).to.eql(value.toPlainObject()); + await persistence.remove(key); + expect(await persistence.get(key)).to.be.null; }); describe('#isAvaliable', () => { diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index e0ad380c485..11b8aaf8301 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -15,13 +15,7 @@ * limitations under the License. */ -import { - Persistence, - PersistenceType, - PersistenceValue, - Instantiator, - PersistedBlob -} from '.'; +import { PersistedBlob, Persistence, PersistenceType, PersistenceValue } from './'; const STORAGE_AVAILABLE_KEY_ = '__sak'; @@ -169,13 +163,9 @@ class IndexedDBLocalPersistence implements Persistence { async get( key: string, - instantiator?: Instantiator ): Promise { const db = await this.initialize(); const obj = await getObject(db, key); - if (instantiator && obj && typeof obj !== 'string') { - return instantiator(obj); - } return obj as T; } diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts index 239eb14f555..1f4eb9522b3 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -15,15 +15,16 @@ * limitations under the License. */ -import * as sinon from 'sinon'; import * as chai from 'chai'; -import { inMemoryPersistence } from './in_memory'; -import { PersistenceType, Persistence, Instantiator } from '.'; import { expect } from 'chai'; -import { testUser, mockAuth } from '../../../test/mock_auth'; -import { PersistenceUserManager } from './persistence_user_manager'; +import * as sinon from 'sinon'; import * as sinonChai from 'sinon-chai'; + +import { mockAuth, testUser } from '../../../test/mock_auth'; import { UserImpl } from '../user/user_impl'; +import { Persistence, PersistenceType } from './'; +import { inMemoryPersistence } from './in_memory'; +import { PersistenceUserManager } from './persistence_user_manager'; chai.use(sinonChai); @@ -59,7 +60,7 @@ describe('core/persistence/persistence_user_manager', () => { const b = makePersistence(); const c = makePersistence(); const search = [a.persistence, b.persistence, c.persistence]; - b.stub.get.returns(Promise.resolve(testUser('uid'))); + b.stub.get.returns(Promise.resolve(testUser('uid').toPlainObject())); const out = await PersistenceUserManager.create(mockAuth, search); expect(out.persistence).to.eq(b.persistence); @@ -116,7 +117,7 @@ describe('core/persistence/persistence_user_manager', () => { await manager.setCurrentUser(user); expect(persistenceStub.set).to.have.been.calledWith( 'firebase:authUser:test-api-key:test-app', - user + user.toPlainObject(), ); }); @@ -130,11 +131,7 @@ describe('core/persistence/persistence_user_manager', () => { it('#getCurrentUser calls with instantiator', async () => { const rawObject = {}; const userImplStub = sinon.stub(UserImpl, 'fromPlainObject'); - persistenceStub.get.callsFake((_: string, cb?: Instantiator) => { - // Call through to the callback, to exercise the instantiator - // provided in PersistenceUserManager - return cb!(rawObject); - }); + persistenceStub.get.returns(Promise.resolve(rawObject)); await manager.getCurrentUser(); expect(userImplStub).to.have.been.calledWith(mockAuth, rawObject); @@ -167,14 +164,14 @@ describe('core/persistence/persistence_user_manager', () => { stub: nextStub } = makePersistence(); const user = testUser('uid'); - persistenceStub.get.returns(Promise.resolve(user)); + persistenceStub.get.returns(Promise.resolve(user.toPlainObject())); await manager.setPersistence(nextPersistence); expect(persistenceStub.get).to.have.been.called; expect(persistenceStub.remove).to.have.been.called; expect(nextStub.set).to.have.been.calledWith( 'firebase:authUser:test-api-key:test-app', - user + user.toPlainObject(), ); }); }); diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index 9534afa42ff..be42f5e4f2b 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { Persistence, PersistedBlob } from '../persistence'; -import { User } from '../../model/user'; import { ApiKey, AppName, Auth } from '../../model/auth'; -import { inMemoryPersistence } from './in_memory'; +import { User } from '../../model/user'; +import { PersistedBlob, Persistence } from '../persistence'; import { UserImpl } from '../user/user_impl'; +import { inMemoryPersistence } from './in_memory'; export const AUTH_USER_KEY_NAME_ = 'authUser'; export const PERSISTENCE_KEY_NAME_ = 'persistence'; @@ -51,13 +51,12 @@ export class PersistenceUserManager { } setCurrentUser(user: User): Promise { - return this.persistence.set(this.fullUserKey, user); + return this.persistence.set(this.fullUserKey, user.toPlainObject()); } - getCurrentUser(): Promise { - return this.persistence.get(this.fullUserKey, (blob: PersistedBlob) => - UserImpl.fromPlainObject(this.auth, blob) - ); + async getCurrentUser(): Promise { + const blob = await this.persistence.get(this.fullUserKey); + return blob ? UserImpl.fromPlainObject(this.auth, blob) : null; } removeCurrentUser(): Promise { @@ -94,7 +93,7 @@ export class PersistenceUserManager { const key = persistenceKeyName_(userKey, auth.config.apiKey, auth.name); for (const persistence of persistenceHierarchy) { - if (await persistence.get(key)) { + if (await persistence.get(key)) { return new PersistenceUserManager(persistence, auth, userKey); } } diff --git a/packages-exp/auth-exp/src/core/user/token_manager.ts b/packages-exp/auth-exp/src/core/user/token_manager.ts index b464bba92b6..1566bab2341 100644 --- a/packages-exp/auth-exp/src/core/user/token_manager.ts +++ b/packages-exp/auth-exp/src/core/user/token_manager.ts @@ -78,11 +78,15 @@ export class StsTokenManager { const { refreshToken, accessToken, expirationTime } = object; const manager = new StsTokenManager(); - Object.assign>(manager, { - refreshToken: assertType(refreshToken, 'string', appName), - accessToken: assertType(accessToken, 'string', appName), - expirationTime: assertType(expirationTime, 'number', appName) - }); + if (refreshToken) { + manager.refreshToken = assertType(refreshToken, 'string', appName); + } + if (accessToken) { + manager.accessToken = assertType(accessToken, 'string', appName); + } + if (expirationTime) { + manager.expirationTime = assertType(expirationTime, 'number', appName); + } return manager; } diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index e8a5e3af7be..ba903b18154 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -87,10 +87,10 @@ export class UserImpl implements User { return { uid: this.uid, stsTokenManager: this.stsTokenManager.toPlainObject(), - displayName: this.displayName, - email: this.email, - phoneNumber: this.phoneNumber, - photoURL: this.phoneNumber, + displayName: this.displayName || undefined, + email: this.email || undefined, + phoneNumber: this.phoneNumber || undefined, + photoURL: this.phoneNumber || undefined, }; } diff --git a/packages-exp/auth-exp/src/model/user.d.ts b/packages-exp/auth-exp/src/model/user.d.ts index 75820154392..72994a5b9ca 100644 --- a/packages-exp/auth-exp/src/model/user.d.ts +++ b/packages-exp/auth-exp/src/model/user.d.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { PersistedBlob } from '../core/persistence'; import { ProviderId } from '../core/providers'; import { IdTokenResult } from './id_token'; @@ -35,4 +36,5 @@ export interface User extends UserInfo { getIdTokenResult(forceRefresh?: boolean): Promise; reload(): Promise; delete(): Promise; + toPlainObject(): PersistedBlob; } From 8ccb75e2046955f2d89fe3bf41d6d5954b612713 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 13:38:05 -0700 Subject: [PATCH 21/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/persistence/browser.ts | 4 +--- packages-exp/auth-exp/src/core/persistence/index.ts | 4 +--- .../auth-exp/src/core/persistence/indexed_db.ts | 11 +++++++---- .../core/persistence/persistence_user_manager.test.ts | 4 ++-- packages-exp/auth-exp/src/core/user/user_impl.ts | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.ts b/packages-exp/auth-exp/src/core/persistence/browser.ts index 7ddeacda442..e3e9477037e 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.ts @@ -41,9 +41,7 @@ class BrowserPersistence implements Persistence { this.storage.setItem(key, JSON.stringify(value)); } - async get( - key: string, - ): Promise { + async get(key: string): Promise { const json = this.storage.getItem(key); return json ? JSON.parse(json) : null; } diff --git a/packages-exp/auth-exp/src/core/persistence/index.ts b/packages-exp/auth-exp/src/core/persistence/index.ts index 6d5fed957f1..203bb9d94ac 100644 --- a/packages-exp/auth-exp/src/core/persistence/index.ts +++ b/packages-exp/auth-exp/src/core/persistence/index.ts @@ -35,8 +35,6 @@ export interface Persistence { type: PersistenceType; isAvailable(): Promise; set(key: string, value: PersistenceValue): Promise; - get( - key: string - ): Promise; + get(key: string): Promise; remove(key: string): Promise; } diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index 11b8aaf8301..662f4627e91 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { PersistedBlob, Persistence, PersistenceType, PersistenceValue } from './'; +import { + PersistedBlob, + Persistence, + PersistenceType, + PersistenceValue +} from './'; const STORAGE_AVAILABLE_KEY_ = '__sak'; @@ -161,9 +166,7 @@ class IndexedDBLocalPersistence implements Persistence { return putObject(db, key, value); } - async get( - key: string, - ): Promise { + async get(key: string): Promise { const db = await this.initialize(); const obj = await getObject(db, key); return obj as T; diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts index 1f4eb9522b3..12ffa8e8fa9 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.test.ts @@ -117,7 +117,7 @@ describe('core/persistence/persistence_user_manager', () => { await manager.setCurrentUser(user); expect(persistenceStub.set).to.have.been.calledWith( 'firebase:authUser:test-api-key:test-app', - user.toPlainObject(), + user.toPlainObject() ); }); @@ -171,7 +171,7 @@ describe('core/persistence/persistence_user_manager', () => { expect(persistenceStub.remove).to.have.been.called; expect(nextStub.set).to.have.been.calledWith( 'firebase:authUser:test-api-key:test-app', - user.toPlainObject(), + user.toPlainObject() ); }); }); diff --git a/packages-exp/auth-exp/src/core/user/user_impl.ts b/packages-exp/auth-exp/src/core/user/user_impl.ts index ba903b18154..ce2d85ac18a 100644 --- a/packages-exp/auth-exp/src/core/user/user_impl.ts +++ b/packages-exp/auth-exp/src/core/user/user_impl.ts @@ -90,7 +90,7 @@ export class UserImpl implements User { displayName: this.displayName || undefined, email: this.email || undefined, phoneNumber: this.phoneNumber || undefined, - photoURL: this.phoneNumber || undefined, + photoURL: this.phoneNumber || undefined }; } From 1fce8ba393cad843a4ba3d90adfeccff7cc0e3b2 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 13:40:23 -0700 Subject: [PATCH 22/26] Move CONST_ to _CONST --- .../auth-exp/src/core/persistence/browser.ts | 6 +++--- .../auth-exp/src/core/persistence/indexed_db.ts | 13 ++++--------- .../core/persistence/persistence_user_manager.ts | 12 ++++++------ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.ts b/packages-exp/auth-exp/src/core/persistence/browser.ts index e3e9477037e..357a328c1fd 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.ts @@ -17,7 +17,7 @@ import { Persistence, PersistenceType, PersistenceValue } from './'; -const STORAGE_AVAILABLE_KEY_ = '__sak'; +const _STORAGE_AVAILABLE_KEY = '__sak'; class BrowserPersistence implements Persistence { type: PersistenceType = PersistenceType.LOCAL; @@ -29,8 +29,8 @@ class BrowserPersistence implements Persistence { if (!this.storage) { return false; } - this.storage.setItem(STORAGE_AVAILABLE_KEY_, '1'); - this.storage.removeItem(STORAGE_AVAILABLE_KEY_); + this.storage.setItem(_STORAGE_AVAILABLE_KEY, '1'); + this.storage.removeItem(_STORAGE_AVAILABLE_KEY); return true; } catch { return false; diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index 662f4627e91..dd33dfb233f 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -15,14 +15,9 @@ * limitations under the License. */ -import { - PersistedBlob, - Persistence, - PersistenceType, - PersistenceValue -} from './'; +import { PersistedBlob, Persistence, PersistenceType, PersistenceValue } from './'; -const STORAGE_AVAILABLE_KEY_ = '__sak'; +const _STORAGE_AVAILABLE_KEY = '__sak'; export const DB_NAME = 'firebaseLocalStorageDb'; const DB_VERSION = 1; @@ -154,8 +149,8 @@ class IndexedDBLocalPersistence implements Persistence { return false; } const db = await openDatabase(); - await putObject(db, STORAGE_AVAILABLE_KEY_, '1'); - await deleteObject(db, STORAGE_AVAILABLE_KEY_); + await putObject(db, _STORAGE_AVAILABLE_KEY, '1'); + await deleteObject(db, _STORAGE_AVAILABLE_KEY); return true; } catch {} return false; diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index be42f5e4f2b..605075dc6ff 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -21,16 +21,16 @@ import { PersistedBlob, Persistence } from '../persistence'; import { UserImpl } from '../user/user_impl'; import { inMemoryPersistence } from './in_memory'; -export const AUTH_USER_KEY_NAME_ = 'authUser'; -export const PERSISTENCE_KEY_NAME_ = 'persistence'; -const PERSISTENCE_NAMESPACE_ = 'firebase'; +export const _AUTH_USER_KEY_NAME = 'authUser'; +export const _PERSISTENCE_KEY_NAME = 'persistence'; +const _PERSISTENCE_NAMESPACE = 'firebase'; export function persistenceKeyName_( key: string, apiKey: ApiKey, appName: AppName ): string { - return `${PERSISTENCE_NAMESPACE_}:${key}:${apiKey}:${appName}`; + return `${_PERSISTENCE_NAMESPACE}:${key}:${apiKey}:${appName}`; } export class PersistenceUserManager { @@ -44,7 +44,7 @@ export class PersistenceUserManager { const { config, name } = this.auth; this.fullUserKey = persistenceKeyName_(this.userKey, config.apiKey, name); this.fullPersistenceKey = persistenceKeyName_( - PERSISTENCE_KEY_NAME_, + _PERSISTENCE_KEY_NAME, config.apiKey, name ); @@ -85,7 +85,7 @@ export class PersistenceUserManager { static async create( auth: Auth, persistenceHierarchy: Persistence[], - userKey = AUTH_USER_KEY_NAME_ + userKey = _AUTH_USER_KEY_NAME ): Promise { if (!persistenceHierarchy.length) { return new PersistenceUserManager(inMemoryPersistence, auth, userKey); From df6c1d06d9a3e2475311e3ae82367df7d5d0cc0e Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 13:40:28 -0700 Subject: [PATCH 23/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/persistence/indexed_db.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index dd33dfb233f..1a79eca0f34 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { PersistedBlob, Persistence, PersistenceType, PersistenceValue } from './'; +import { + PersistedBlob, + Persistence, + PersistenceType, + PersistenceValue +} from './'; const _STORAGE_AVAILABLE_KEY = '__sak'; From cd255dacbf7e6fb70423203f3d6adae3e3a90857 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 15:33:11 -0700 Subject: [PATCH 24/26] PR feedback --- .../auth-exp/src/core/persistence/browser.ts | 8 +++----- .../auth-exp/src/core/persistence/index.ts | 2 ++ .../src/core/persistence/indexed_db.ts | 19 ++++++------------- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.ts b/packages-exp/auth-exp/src/core/persistence/browser.ts index 357a328c1fd..dadb910a343 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.ts @@ -15,9 +15,7 @@ * limitations under the License. */ -import { Persistence, PersistenceType, PersistenceValue } from './'; - -const _STORAGE_AVAILABLE_KEY = '__sak'; +import { Persistence, PersistenceType, PersistenceValue, STORAGE_AVAILABLE_KEY } from './'; class BrowserPersistence implements Persistence { type: PersistenceType = PersistenceType.LOCAL; @@ -29,8 +27,8 @@ class BrowserPersistence implements Persistence { if (!this.storage) { return false; } - this.storage.setItem(_STORAGE_AVAILABLE_KEY, '1'); - this.storage.removeItem(_STORAGE_AVAILABLE_KEY); + this.storage.setItem(STORAGE_AVAILABLE_KEY, '1'); + this.storage.removeItem(STORAGE_AVAILABLE_KEY); return true; } catch { return false; diff --git a/packages-exp/auth-exp/src/core/persistence/index.ts b/packages-exp/auth-exp/src/core/persistence/index.ts index 203bb9d94ac..938f2371a17 100644 --- a/packages-exp/auth-exp/src/core/persistence/index.ts +++ b/packages-exp/auth-exp/src/core/persistence/index.ts @@ -31,6 +31,8 @@ export interface Instantiator { export type PersistenceValue = PersistedBlob | string; +export const STORAGE_AVAILABLE_KEY = '__sak'; + export interface Persistence { type: PersistenceType; isAvailable(): Promise; diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index 1a79eca0f34..c79139695fb 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -16,24 +16,17 @@ */ import { - PersistedBlob, - Persistence, - PersistenceType, - PersistenceValue + PersistedBlob, Persistence, PersistenceType, PersistenceValue, STORAGE_AVAILABLE_KEY } from './'; -const _STORAGE_AVAILABLE_KEY = '__sak'; - export const DB_NAME = 'firebaseLocalStorageDb'; const DB_VERSION = 1; const DB_OBJECTSTORE_NAME = 'firebaseLocalStorage'; const DB_DATA_KEYPATH = 'fbase_key'; -type DBValue = PersistedBlob | string; - interface DBObject { [DB_DATA_KEYPATH]: string; - value: DBValue; + value: PersistedBlob; } /** @@ -110,7 +103,7 @@ async function putObject( const data = await new DBPromise(getRequest).toPromise(); if (data) { // Force an index signature on the user object - data.value = value as DBValue; + data.value = value as PersistedBlob; const request = getObjectStore(db, true).put(data); return new DBPromise(request).toPromise(); } else { @@ -125,7 +118,7 @@ async function putObject( async function getObject( db: IDBDatabase, key: string -): Promise { +): Promise { const request = getObjectStore(db, false).get(key); const data = await new DBPromise(request).toPromise(); return data === undefined ? null : data.value; @@ -154,8 +147,8 @@ class IndexedDBLocalPersistence implements Persistence { return false; } const db = await openDatabase(); - await putObject(db, _STORAGE_AVAILABLE_KEY, '1'); - await deleteObject(db, _STORAGE_AVAILABLE_KEY); + await putObject(db, STORAGE_AVAILABLE_KEY, '1'); + await deleteObject(db, STORAGE_AVAILABLE_KEY); return true; } catch {} return false; From ea70a8aa027762802b23a371c270adb1236c9cd8 Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 15:33:59 -0700 Subject: [PATCH 25/26] [AUTOMATED]: Prettier Code Styling --- packages-exp/auth-exp/src/core/persistence/browser.ts | 7 ++++++- packages-exp/auth-exp/src/core/persistence/indexed_db.ts | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/browser.ts b/packages-exp/auth-exp/src/core/persistence/browser.ts index dadb910a343..471482c2142 100644 --- a/packages-exp/auth-exp/src/core/persistence/browser.ts +++ b/packages-exp/auth-exp/src/core/persistence/browser.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { Persistence, PersistenceType, PersistenceValue, STORAGE_AVAILABLE_KEY } from './'; +import { + Persistence, + PersistenceType, + PersistenceValue, + STORAGE_AVAILABLE_KEY +} from './'; class BrowserPersistence implements Persistence { type: PersistenceType = PersistenceType.LOCAL; diff --git a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts index c79139695fb..fa6ee9775ad 100644 --- a/packages-exp/auth-exp/src/core/persistence/indexed_db.ts +++ b/packages-exp/auth-exp/src/core/persistence/indexed_db.ts @@ -16,7 +16,11 @@ */ import { - PersistedBlob, Persistence, PersistenceType, PersistenceValue, STORAGE_AVAILABLE_KEY + PersistedBlob, + Persistence, + PersistenceType, + PersistenceValue, + STORAGE_AVAILABLE_KEY } from './'; export const DB_NAME = 'firebaseLocalStorageDb'; From 2749d1e1cc663185d40b8970fee7d0e42a8a348d Mon Sep 17 00:00:00 2001 From: Sam Olsen Date: Fri, 17 Apr 2020 16:01:00 -0700 Subject: [PATCH 26/26] Addressing PR feedback --- .../src/core/persistence/persistence_user_manager.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts index 605075dc6ff..d67349281f6 100644 --- a/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts +++ b/packages-exp/auth-exp/src/core/persistence/persistence_user_manager.ts @@ -25,7 +25,7 @@ export const _AUTH_USER_KEY_NAME = 'authUser'; export const _PERSISTENCE_KEY_NAME = 'persistence'; const _PERSISTENCE_NAMESPACE = 'firebase'; -export function persistenceKeyName_( +function _persistenceKeyName( key: string, apiKey: ApiKey, appName: AppName @@ -42,8 +42,8 @@ export class PersistenceUserManager { private readonly userKey: string ) { const { config, name } = this.auth; - this.fullUserKey = persistenceKeyName_(this.userKey, config.apiKey, name); - this.fullPersistenceKey = persistenceKeyName_( + this.fullUserKey = _persistenceKeyName(this.userKey, config.apiKey, name); + this.fullPersistenceKey = _persistenceKeyName( _PERSISTENCE_KEY_NAME, config.apiKey, name @@ -91,7 +91,7 @@ export class PersistenceUserManager { return new PersistenceUserManager(inMemoryPersistence, auth, userKey); } - const key = persistenceKeyName_(userKey, auth.config.apiKey, auth.name); + const key = _persistenceKeyName(userKey, auth.config.apiKey, auth.name); for (const persistence of persistenceHierarchy) { if (await persistence.get(key)) { return new PersistenceUserManager(persistence, auth, userKey);