Skip to content

Commit 35e97ad

Browse files
Jujureflorianduros
authored andcommitted
Revert deletion of hydrateSession (element-hq#29703)
* Revert deletion of hydrateSession * remove line break to make prettier happy :-) * add tests for hydrateSession on soft logout * fix coding style --------- Co-authored-by: Florian Duros <[email protected]>
1 parent ebe748a commit 35e97ad

3 files changed

Lines changed: 78 additions & 8 deletions

File tree

src/Lifecycle.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,43 @@ export async function setLoggedIn(credentials: IMatrixClientCreds): Promise<Matr
701701
return doSetLoggedIn(credentials, true, true);
702702
}
703703

704+
/**
705+
* Hydrates an existing session by using the credentials provided. This will
706+
* not clear any local storage, unlike setLoggedIn().
707+
*
708+
* Stops the existing Matrix client (without clearing its data) and starts a
709+
* new one in its place. This additionally starts all other react-sdk services
710+
* which use the new Matrix client.
711+
*
712+
* If the credentials belong to a different user from the session already stored,
713+
* the old session will be cleared automatically.
714+
*
715+
* @param {IMatrixClientCreds} credentials The credentials to use
716+
*
717+
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
718+
*/
719+
export async function hydrateSession(credentials: IMatrixClientCreds): Promise<MatrixClient> {
720+
const oldUserId = MatrixClientPeg.safeGet().getUserId();
721+
const oldDeviceId = MatrixClientPeg.safeGet().getDeviceId();
722+
723+
stopMatrixClient(); // unsets MatrixClientPeg.get()
724+
localStorage.removeItem("mx_soft_logout");
725+
_isLoggingOut = false;
726+
727+
const overwrite = credentials.userId !== oldUserId || credentials.deviceId !== oldDeviceId;
728+
if (overwrite) {
729+
logger.warn("Clearing all data: Old session belongs to a different user/session");
730+
}
731+
732+
if (!credentials.pickleKey && credentials.deviceId !== undefined) {
733+
logger.info("Lifecycle#hydrateSession: Pickle key not provided - trying to get one");
734+
credentials.pickleKey =
735+
(await PlatformPeg.get()?.getPickleKey(credentials.userId, credentials.deviceId)) ?? undefined;
736+
}
737+
738+
return doSetLoggedIn(credentials, overwrite, false);
739+
}
740+
704741
/**
705742
* When we have a authenticated via OIDC-native flow and have a refresh token
706743
* try to create a token refresher.

src/components/structures/auth/SoftLogout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
168168
return;
169169
}
170170

171-
Lifecycle.setLoggedIn(credentials).catch((e) => {
171+
Lifecycle.hydrateSession(credentials).catch((e) => {
172172
logger.error(e);
173173
this.setState({ busy: false, errorText: _t("auth|failed_soft_logout_auth") });
174174
});
@@ -204,7 +204,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
204204
return false;
205205
}
206206

207-
return Lifecycle.setLoggedIn(credentials)
207+
return Lifecycle.hydrateSession(credentials)
208208
.then(() => {
209209
if (this.props.onTokenLoginCompleted) {
210210
this.props.onTokenLoginCompleted();

test/unit-tests/Lifecycle-test.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ const webCrypto = new Crypto();
3838
const windowCrypto = window.crypto;
3939

4040
describe("Lifecycle", () => {
41+
const homeserverUrl = "https://domain";
42+
const identityServerUrl = "https://is.org";
43+
const userId = "@alice:domain";
44+
const deviceId = "abc123";
45+
const accessToken = "test-access-token";
46+
4147
let mockPlatform: MockedObject<BasePlatform>;
4248

4349
const realLocalStorage = global.localStorage;
@@ -53,7 +59,7 @@ describe("Lifecycle", () => {
5359
removeAllListeners: jest.fn(),
5460
clearStores: jest.fn(),
5561
getAccountData: jest.fn(),
56-
getDeviceId: jest.fn(),
62+
getDeviceId: jest.fn().mockReturnValue(deviceId),
5763
isVersionSupported: jest.fn().mockResolvedValue(true),
5864
getCrypto: jest.fn(),
5965
getClientWellKnown: jest.fn(),
@@ -156,11 +162,6 @@ describe("Lifecycle", () => {
156162
});
157163
};
158164

159-
const homeserverUrl = "https://server.org";
160-
const identityServerUrl = "https://is.org";
161-
const userId = "@alice:server.org";
162-
const deviceId = "abc123";
163-
const accessToken = "test-access-token";
164165
const localStorageSession = {
165166
mx_hs_url: homeserverUrl,
166167
mx_is_url: identityServerUrl,
@@ -605,6 +606,38 @@ describe("Lifecycle", () => {
605606
expect(MatrixClientPeg.start).toHaveBeenCalled();
606607
});
607608

609+
describe("after a soft-logout", () => {
610+
beforeEach(async () => {
611+
await setLoggedIn(credentials);
612+
localStorage.setItem("mx_soft_logout", "true");
613+
});
614+
615+
it("should not clear the storage if device is the same", async () => {
616+
await Lifecycle.hydrateSession(credentials);
617+
618+
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_soft_logout");
619+
expect(mockClient.getUserId).toHaveReturnedWith(userId);
620+
expect(mockClient.getDeviceId).toHaveReturnedWith(deviceId);
621+
expect(mockClient.clearStores).toHaveBeenCalledTimes(1);
622+
});
623+
624+
it("should clear the storage if device is not the same", async () => {
625+
const fakeCredentials = {
626+
homeserverUrl,
627+
identityServerUrl,
628+
userId: "@bob:domain",
629+
deviceId,
630+
accessToken,
631+
};
632+
await Lifecycle.hydrateSession(fakeCredentials);
633+
634+
expect(localStorage.removeItem).toHaveBeenCalledWith("mx_soft_logout");
635+
expect(mockClient.getUserId).toHaveReturnedWith(userId);
636+
expect(mockClient.getDeviceId).toHaveReturnedWith(deviceId);
637+
expect(mockClient.clearStores).toHaveBeenCalledTimes(2);
638+
});
639+
});
640+
608641
describe("without a pickle key", () => {
609642
beforeEach(() => {
610643
jest.spyOn(mockPlatform, "createPickleKey").mockResolvedValue(null);

0 commit comments

Comments
 (0)