Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,34 @@ export async function hydrateSession(credentials: IMatrixClientCreds): Promise<M
return doSetLoggedIn(credentials, overwrite);
}

/**
* Similar to hydrateSession(), this will update the credentials used by the current
* session in-place. Services will not be restarted, and storage will not be deleted.
* @param {IMatrixClientCreds} credentials The credentials to use
* @returns {Promise} promise which resolves to the new MatrixClient once it has been started
*/
export async function hydrateSessionInPlace(credentials: IMatrixClientCreds): Promise<MatrixClient> {
const oldUserId = MatrixClientPeg.get().getUserId();
const oldDeviceId = MatrixClientPeg.get().getDeviceId();
if (credentials.userId !== oldUserId || credentials.deviceId !== oldDeviceId) {
throw new Error("Attempted to hydrate in-place with a different session");
}

const cli = MatrixClientPeg.get();
if (!cli) {
throw new Error("Attempted to hydrate a non-existent MatrixClient");
}

logger.info("Lifecycle#hydrateInPlace: Persisting credentials and updating access token");
await persistCredentials(credentials);
MatrixClientPeg.updateUsingCreds(credentials);

// reset the token timers
TokenLifecycle.instance.startTimers(credentials);

return cli;
}

/**
* fires on_logging_in, optionally clears localstorage, persists new credentials
* to localstorage, starts the new client.
Expand Down
13 changes: 13 additions & 0 deletions src/MatrixClientPeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ export interface IMatrixClientPeg {
* @param {IMatrixClientCreds} creds The new credentials to use.
*/
replaceUsingCreds(creds: IMatrixClientCreds): void;

/**
* Similar to replaceUsingCreds(), but without the replacement operation.
* Credentials that can be updated in-place will be updated. All others
* will be ignored.
* @param {IMatrixClientCreds} creds The new credentials to use.
*/
updateUsingCreds(creds: IMatrixClientCreds): void;
}

/**
Expand Down Expand Up @@ -166,6 +174,11 @@ class MatrixClientPegClass implements IMatrixClientPeg {
this.createClient(creds);
}

public updateUsingCreds(creds: IMatrixClientCreds): void {
this.currentClientCreds = creds;
this.matrixClient.setAccessToken(creds.accessToken);
}

public async assign(): Promise<any> {
for (const dbType of ['indexeddb', 'memory']) {
try {
Expand Down
6 changes: 3 additions & 3 deletions src/TokenLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src";

import { IMatrixClientCreds, MatrixClientPeg } from "./MatrixClientPeg";
import { hydrateSession } from "./Lifecycle";
import { hydrateSessionInPlace } from "./Lifecycle";

export interface IRenewedMatrixClientCreds extends Pick<IMatrixClientCreds,
"accessToken" | "accessTokenExpiryTs" | "accessTokenRefreshToken"> {}
Expand Down Expand Up @@ -144,11 +144,11 @@ export class TokenLifecycle {
this.startTimers(credentials);
} else {
logger.info("TokenLifecycle#expireExchange: Updating client credentials using rehydration");
await hydrateSession({
await hydrateSessionInPlace({
...credentials,
...result, // override from credentials
});
// hydrateSession will ultimately call back to startTimers() for us, so no need to do it here.
// hydrateSessionInPlace will ultimately call back to startTimers() for us, so no need to do it here.
}
} catch (e) {
logger.error("TokenLifecycle#expireExchange: Error getting new credentials. Rescheduling.", e);
Expand Down