Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix overwrite login action not stopping client
Browse files Browse the repository at this point in the history
  • Loading branch information
BillCarsonFr committed Feb 21, 2024
1 parent d9a20b0 commit 908150b
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
2 changes: 1 addition & 1 deletion playwright/e2e/crypto/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export async function logIntoElement(
// select homeserver
await page.getByRole("button", { name: "Edit" }).click();
await page.getByRole("textbox", { name: "Other homeserver" }).fill(homeserver.config.baseUrl);
await page.getByRole("button", { name: "Continue" }).click();
await page.getByRole("button", { name: "Continue", exact: true }).click();

// wait for the dialog to go away
await expect(page.locator(".mx_ServerPickerDialog")).not.toBeVisible();
Expand Down
69 changes: 69 additions & 0 deletions playwright/e2e/login/overwrite_login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2024 The Matrix.org Foundation C.I.C.
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 { test, expect } from "../../element-web-test";
import { logIntoElement } from "../crypto/utils";
import { IMatrixClientCreds } from "../../../src/MatrixClientPeg";

test.describe("Overwrite login action", () => {
test.use({
config: ({ homeserver }, use) =>
use({
default_server_config: {
"m.homeserver": {
base_url: homeserver.config.baseUrl,
},
"m.identity_server": {
base_url: "https://server.invalid",
},
},
}),
});

test("Try replace existing login with new one", async ({ page, app, credentials, homeserver }) => {
// await page.pause();
await logIntoElement(page, homeserver, credentials);

const userMenu = await app.openUserMenu();
await expect(userMenu.getByText(credentials.userId)).toBeVisible();

const bobRegister = await homeserver.registerUser("BobOverwrite", "p@ssword1!", "BOB");

// just assert that it's a different user
expect(credentials.userId).not.toBe(bobRegister.userId);

const clientCredentials: IMatrixClientCreds = {
homeserverUrl: homeserver.config.baseUrl,
...bobRegister,
};

// Trigger the overwrite login action
await app.client.evaluate(async (cli, clientCredentials) => {
// @ts-ignore - raw access to the dispatcher to simulate the action
window.mxDispatcher.dispatch(
{
action: "overwrite_login",
credentials: clientCredentials,
},
true,
);
}, clientCredentials);

// It should be now another user!!
const newUserMenu = await app.openUserMenu();
await expect(newUserMenu.getByText("@boboverwrite:localhost")).toBeVisible();
});
});
18 changes: 15 additions & 3 deletions src/Lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,20 @@ dis.register((payload) => {
onLoggedOut();
} else if (payload.action === Action.OverwriteLogin) {
const typed = <OverwriteLoginPayload>payload;
// noinspection JSIgnoredPromiseFromCall - we don't care if it fails
doSetLoggedIn(typed.credentials, true);
// Stop the current client before overwriting the login.
// If not done it might be impossible to clear the storage, as the
// rust crypto backend might be holding an open connection to the indexeddb store.
// We also use the `unsetClient` flag to false, because at this point we are
// already in the logged in flows of the `MatrixChat` component, and it will
// always expect to have a client (calls to `MatrixClientPeg.safeGet()`).
// If we unset the client and the component is updated, the render will fail and unmount everything.
// (The module dialog closes and fires a `aria_unhide_main_app` that will trigger a re-render)
stopMatrixClient(false);
doSetLoggedIn(typed.credentials, true).catch((e) => {
// XXX we might want to fire a new event here to let the app know that the login failed ?
// The module api could use it to display a message to the user.
logger.warn("Failed to overwrite login", e);
});
}
});

Expand Down Expand Up @@ -877,8 +889,8 @@ async function doSetLoggedIn(credentials: IMatrixClientCreds, clearStorageEnable
}
checkSessionLock();

dis.fire(Action.OnLoggedIn);
await startMatrixClient(client, /*startSyncing=*/ !softLogout);
dis.fire(Action.OnLoggedIn);

return client;
}
Expand Down
10 changes: 7 additions & 3 deletions src/modules/ProxiedModuleApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ export class ProxiedModuleApi implements ModuleApi {
* @override
*/
public async overwriteAccountAuth(accountInfo: AccountAuthInfo): Promise<void> {
// We want to wait for the new login to complete before returning.
// See `Action.OnLoggedIn` in dispatcher.
const awaitNewLogin = new Promise<void>((resolve) => {
this.overrideLoginResolve = resolve;
});

dispatcher.dispatch<OverwriteLoginPayload>(
{
action: Action.OverwriteLogin,
Expand All @@ -172,9 +178,7 @@ export class ProxiedModuleApi implements ModuleApi {
); // require to be sync to match inherited interface behaviour

// wait for login to complete
await new Promise<void>((resolve) => {
this.overrideLoginResolve = resolve;
});
await awaitNewLogin;
}

/**
Expand Down

0 comments on commit 908150b

Please sign in to comment.