Fixes user authentication when registering via the module API (#10257)

* Fixes authentication when user is registered via module API
* Remove "on_logging_in" action

---------

Signed-off-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net>
Co-authored-by: Mikhail Aheichyk <mikhail.aheichyk@nordeck.net>
pull/28217/head
maheichyk 2023-03-07 18:24:44 +03:00 committed by GitHub
parent af1ec76149
commit 3e340d5906
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 10 deletions

View File

@ -568,7 +568,7 @@ export async function hydrateSession(credentials: IMatrixClientCreds): Promise<M
} }
/** /**
* fires on_logging_in, optionally clears localstorage, persists new credentials * optionally clears localstorage, persists new credentials
* to localstorage, starts the new client. * to localstorage, starts the new client.
* *
* @param {IMatrixClientCreds} credentials * @param {IMatrixClientCreds} credentials
@ -595,15 +595,6 @@ async function doSetLoggedIn(credentials: IMatrixClientCreds, clearStorageEnable
" freshLogin: " + credentials.freshLogin, " freshLogin: " + credentials.freshLogin,
); );
// This is dispatched to indicate that the user is still in the process of logging in
// because async code may take some time to resolve, breaking the assumption that
// `setLoggedIn` takes an "instant" to complete, and dispatch `on_logged_in` a few ms
// later than MatrixChat might assume.
//
// we fire it *synchronously* to make sure it fires before on_logged_in.
// (dis.dispatch uses `window.setTimeout`, which does not guarantee ordering.)
dis.dispatch({ action: "on_logging_in" }, true);
if (clearStorageEnabled) { if (clearStorageEnabled) {
await clearStorage(); await clearStorage();
} }

View File

@ -36,6 +36,7 @@ import { MatrixClientPeg } from "../MatrixClientPeg";
import { getCachedRoomIDForAlias } from "../RoomAliasCache"; import { getCachedRoomIDForAlias } from "../RoomAliasCache";
import { Action } from "../dispatcher/actions"; import { Action } from "../dispatcher/actions";
import { OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayload"; import { OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayload";
import { ActionPayload } from "../dispatcher/payloads";
/** /**
* Glue between the `ModuleApi` interface and the react-sdk. Anticipates one instance * Glue between the `ModuleApi` interface and the react-sdk. Anticipates one instance
@ -44,6 +45,18 @@ import { OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayl
export class ProxiedModuleApi implements ModuleApi { export class ProxiedModuleApi implements ModuleApi {
private cachedTranslations: Optional<TranslationStringsObject>; private cachedTranslations: Optional<TranslationStringsObject>;
private overrideLoginResolve?: () => void;
public constructor() {
dispatcher.register(this.onAction);
}
private onAction = (payload: ActionPayload): void => {
if (payload.action === Action.OnLoggedIn) {
this.overrideLoginResolve?.();
}
};
/** /**
* All custom translations used by the associated module. * All custom translations used by the associated module.
*/ */
@ -155,6 +168,11 @@ export class ProxiedModuleApi implements ModuleApi {
}, },
true, true,
); // require to be sync to match inherited interface behaviour ); // require to be sync to match inherited interface behaviour
// wait for login to complete
await new Promise<void>((resolve) => {
this.overrideLoginResolve = resolve;
});
} }
/** /**

View File

@ -15,12 +15,15 @@ limitations under the License.
*/ */
import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations";
import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo";
import { ProxiedModuleApi } from "../../src/modules/ProxiedModuleApi"; import { ProxiedModuleApi } from "../../src/modules/ProxiedModuleApi";
import { stubClient } from "../test-utils"; import { stubClient } from "../test-utils";
import { setLanguage } from "../../src/languageHandler"; import { setLanguage } from "../../src/languageHandler";
import { ModuleRunner } from "../../src/modules/ModuleRunner"; import { ModuleRunner } from "../../src/modules/ModuleRunner";
import { registerMockModule } from "./MockModule"; import { registerMockModule } from "./MockModule";
import defaultDispatcher from "../../src/dispatcher/dispatcher";
import { Action } from "../../src/dispatcher/actions";
describe("ProxiedApiModule", () => { describe("ProxiedApiModule", () => {
afterEach(() => { afterEach(() => {
@ -44,6 +47,29 @@ describe("ProxiedApiModule", () => {
expect(api.translations).toBe(translations); expect(api.translations).toBe(translations);
}); });
it("should overwriteAccountAuth", async () => {
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");
const api = new ProxiedModuleApi();
const accountInfo = {} as unknown as AccountAuthInfo;
const promise = api.overwriteAccountAuth(accountInfo);
expect(dispatchSpy).toHaveBeenCalledWith(
expect.objectContaining({
action: Action.OverwriteLogin,
credentials: {
...accountInfo,
guest: false,
},
}),
expect.anything(),
);
defaultDispatcher.fire(Action.OnLoggedIn);
await expect(promise).resolves.toBeUndefined();
});
describe("integration", () => { describe("integration", () => {
it("should translate strings using translation system", async () => { it("should translate strings using translation system", async () => {
// Test setup // Test setup