diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts index 38852c68fba..0575d2163f8 100644 --- a/src/Lifecycle.ts +++ b/src/Lifecycle.ts @@ -211,7 +211,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise false, ).then(() => true); } - const success = await restoreFromLocalStorage({ + const success = await restoreSessionFromStorage({ ignoreGuest: Boolean(opts.ignoreGuest), }); if (success) { @@ -556,17 +556,19 @@ async function abortLogin(): Promise { } } -// returns a promise which resolves to true if a session is found in -// localstorage -// -// N.B. Lifecycle.js should not maintain any further localStorage state, we -// are moving towards using SessionStore to keep track of state related -// to the current session (which is typically backed by localStorage). -// -// The plan is to gradually move the localStorage access done here into -// SessionStore to avoid bugs where the view becomes out-of-sync with -// localStorage (e.g. isGuest etc.) -export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }): Promise { +/** Attempt to restore the session from localStorage or indexeddb. + * + * @returns true if a session was found; false if no existing session was found. + * + * N.B. Lifecycle.js should not maintain any further localStorage state, we + * are moving towards using SessionStore to keep track of state related + * to the current session (which is typically backed by localStorage). + * + * The plan is to gradually move the localStorage access done here into + * SessionStore to avoid bugs where the view becomes out-of-sync with + * localStorage (e.g. isGuest etc.) + */ +export async function restoreSessionFromStorage(opts?: { ignoreGuest?: boolean }): Promise { const ignoreGuest = opts?.ignoreGuest; if (!localStorage) { diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 53514ab817b..53d4c96acaf 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -375,7 +375,7 @@ export default class MatrixChat extends React.PureComponent { // Create and start the client // accesses the new credentials just set in storage during attemptDelegatedAuthLogin // and sets logged in state - await Lifecycle.restoreFromLocalStorage({ ignoreGuest: true }); + await Lifecycle.restoreSessionFromStorage({ ignoreGuest: true }); await this.postLoginSetup(); return; } diff --git a/src/utils/tokens/tokens.ts b/src/utils/tokens/tokens.ts index b5cb8d95cba..b6634171e07 100644 --- a/src/utils/tokens/tokens.ts +++ b/src/utils/tokens/tokens.ts @@ -30,7 +30,7 @@ export const ACCESS_TOKEN_STORAGE_KEY = "mx_access_token"; export const REFRESH_TOKEN_STORAGE_KEY = "mx_refresh_token"; /* * Names of the tokens. Used as part of the calculation to derive AES keys during encryption in persistTokenInStorage, - * and decryption in restoreFromLocalStorage. + * and decryption in restoreSessionFromStorage. */ export const ACCESS_TOKEN_IV = "access_token"; export const REFRESH_TOKEN_IV = "refresh_token"; diff --git a/test/Lifecycle-test.ts b/test/Lifecycle-test.ts index f9146630f9b..b0d044c10e0 100644 --- a/test/Lifecycle-test.ts +++ b/test/Lifecycle-test.ts @@ -23,7 +23,7 @@ import { mocked, MockedObject } from "jest-mock"; import fetchMock from "fetch-mock-jest"; import StorageEvictedDialog from "../src/components/views/dialogs/StorageEvictedDialog"; -import { logout, restoreFromLocalStorage, setLoggedIn } from "../src/Lifecycle"; +import { logout, restoreSessionFromStorage, setLoggedIn } from "../src/Lifecycle"; import { MatrixClientPeg } from "../src/MatrixClientPeg"; import Modal from "../src/Modal"; import * as StorageAccess from "../src/utils/StorageAccess"; @@ -180,7 +180,7 @@ describe("Lifecycle", () => { mac: expect.any(String), }; - describe("restoreFromLocalStorage()", () => { + describe("restoreSessionFromStorage()", () => { beforeEach(() => { initLocalStorageMock(); initSessionStorageMock(); @@ -204,18 +204,18 @@ describe("Lifecycle", () => { // @ts-ignore dirty mocking global.localStorage = undefined; - expect(await restoreFromLocalStorage()).toEqual(false); + expect(await restoreSessionFromStorage()).toEqual(false); }); it("should return false when no session data is found in local storage", async () => { - expect(await restoreFromLocalStorage()).toEqual(false); + expect(await restoreSessionFromStorage()).toEqual(false); expect(logger.log).toHaveBeenCalledWith("No previous session found."); }); it("should abort login when we expect to find an access token but don't", async () => { initLocalStorageMock({ mx_has_access_token: "true" }); - await expect(() => restoreFromLocalStorage()).rejects.toThrow(); + await expect(() => restoreSessionFromStorage()).rejects.toThrow(); expect(Modal.createDialog).toHaveBeenCalledWith(StorageEvictedDialog); expect(mockClient.clearStores).toHaveBeenCalled(); }); @@ -228,12 +228,12 @@ describe("Lifecycle", () => { }); it("should ignore guest accounts when ignoreGuest is true", async () => { - expect(await restoreFromLocalStorage({ ignoreGuest: true })).toEqual(false); + expect(await restoreSessionFromStorage({ ignoreGuest: true })).toEqual(false); expect(logger.log).toHaveBeenCalledWith(`Ignoring stored guest account: ${userId}`); }); it("should restore guest accounts when ignoreGuest is false", async () => { - expect(await restoreFromLocalStorage({ ignoreGuest: false })).toEqual(true); + expect(await restoreSessionFromStorage({ ignoreGuest: false })).toEqual(true); expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( expect.objectContaining({ @@ -253,7 +253,7 @@ describe("Lifecycle", () => { }); it("should persist credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(localStorage.setItem).toHaveBeenCalledWith("mx_user_id", userId); expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true"); @@ -267,7 +267,7 @@ describe("Lifecycle", () => { it("should persist access token when idb is not available", async () => { jest.spyOn(StorageAccess, "idbSave").mockRejectedValue("oups"); - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken); // put accessToken in localstorage as fallback @@ -275,7 +275,7 @@ describe("Lifecycle", () => { }); it("should create and start new matrix client with credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( { @@ -295,13 +295,13 @@ describe("Lifecycle", () => { }); it("should remove fresh login flag from session storage", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(sessionStorage.removeItem).toHaveBeenCalledWith("mx_fresh_login"); }); it("should start matrix client", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(MatrixClientPeg.start).toHaveBeenCalled(); }); @@ -316,7 +316,7 @@ describe("Lifecycle", () => { }); it("should persist credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); // refresh token from storage is re-persisted expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_refresh_token", "true"); @@ -324,7 +324,7 @@ describe("Lifecycle", () => { }); it("should create new matrix client with credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( { @@ -362,7 +362,7 @@ describe("Lifecycle", () => { }); it("should persist credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_access_token", "true"); @@ -384,7 +384,7 @@ describe("Lifecycle", () => { }, ); - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(StorageAccess.idbSave).toHaveBeenCalledWith( "account", @@ -403,7 +403,7 @@ describe("Lifecycle", () => { }); // Perform the restore - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); // Ensure that the expected calls were made expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( @@ -430,7 +430,7 @@ describe("Lifecycle", () => { }); it("should persist credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); // refresh token from storage is re-persisted expect(localStorage.setItem).toHaveBeenCalledWith("mx_has_refresh_token", "true"); @@ -442,7 +442,7 @@ describe("Lifecycle", () => { }); it("should create new matrix client with credentials", async () => { - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( { @@ -492,7 +492,7 @@ describe("Lifecycle", () => { it("should create and start new matrix client with credentials", async () => { // Perform the restore - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); // Ensure that the expected calls were made expect(MatrixClientPeg.replaceUsingCreds).toHaveBeenCalledWith( @@ -519,7 +519,7 @@ describe("Lifecycle", () => { initIdbMock(idbStorageSession); mockClient.isVersionSupported.mockRejectedValue(new Error("Oh, noes, the server is down!")); - expect(await restoreFromLocalStorage()).toEqual(true); + expect(await restoreSessionFromStorage()).toEqual(true); }); }); });