From 73b35104ba914a66ed590b8b9686ea4c4b459880 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 23 Oct 2024 15:24:38 +0200 Subject: [PATCH] Replace `MatrixClient.isRoomEncrypted` by `MatrixClient.CryptoApi.isEncryptionEnabledInRoom` in RoomView --- src/components/structures/RoomView.tsx | 27 ++++++++++++++----- test/test-utils/test-utils.ts | 2 +- .../components/structures/RoomView-test.tsx | 11 ++++---- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 470b73de7c..e418230316 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -233,6 +233,10 @@ export interface IRoomState { liveTimeline?: EventTimeline; narrow: boolean; msc3946ProcessDynamicPredecessor: boolean; + /** + * Wether the room is encrypted or not. + */ + isRoomEncrypted: boolean; canAskToJoin: boolean; promptAskToJoin: boolean; @@ -417,6 +421,7 @@ export class RoomView extends React.Component { canAskToJoin: this.askToJoinEnabled, promptAskToJoin: false, viewRoomOpts: { buttons: [] }, + isRoomEncrypted: false, }; } @@ -847,7 +852,7 @@ export class RoomView extends React.Component { return isManuallyShown && widgets.length > 0; } - public componentDidMount(): void { + public async componentDidMount(): Promise { this.unmounted = false; this.dispatcherRef = defaultDispatcher.register(this.onAction); @@ -914,6 +919,7 @@ export class RoomView extends React.Component { const callState = call?.state; this.setState({ callState, + isRoomEncrypted: await this.getIsRoomEncrypted(), }); this.context.legacyCallHandler.on(LegacyCallHandlerEvent.CallState, this.onCallState); @@ -1377,6 +1383,13 @@ export class RoomView extends React.Component { return room?.currentState.getStateEvents(EventType.RoomTombstone, "") ?? undefined; } + private async getIsRoomEncrypted(roomId = this.state.roomId): Promise { + const crypto = this.context.client?.getCrypto(); + if (!crypto || !roomId) return false; + + return await crypto.isEncryptionEnabledInRoom(roomId); + } + private async calculateRecommendedVersion(room: Room): Promise { const upgradeRecommendation = await room.getRecommendedVersion(); if (this.unmounted) return; @@ -1411,7 +1424,7 @@ export class RoomView extends React.Component { private updatePreviewUrlVisibility({ roomId }: Room): void { // URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit - const key = this.context.client?.isRoomEncrypted(roomId) ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled"; + const key = this.state.isRoomEncrypted ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled"; this.setState({ showUrlPreview: SettingsStore.getValue(key, roomId), }); @@ -1456,7 +1469,7 @@ export class RoomView extends React.Component { }; private async updateE2EStatus(room: Room): Promise { - if (!this.context.client?.isRoomEncrypted(room.roomId)) return; + if (!this.context.client || !this.state.isRoomEncrypted) return; // If crypto is not currently enabled, we aren't tracking devices at all, // so we don't know what the answer is. Let's error on the safe side and show @@ -1480,7 +1493,7 @@ export class RoomView extends React.Component { } }; - private onRoomStateEvents = (ev: MatrixEvent, state: RoomState): void => { + private onRoomStateEvents = async (ev: MatrixEvent, state: RoomState): Promise => { // ignore if we don't have a room yet if (!this.state.room || this.state.room.roomId !== state.roomId) return; @@ -1488,7 +1501,9 @@ export class RoomView extends React.Component { case EventType.RoomTombstone: this.setState({ tombstone: this.getRoomTombstone() }); break; - + case EventType.RoomEncryption: + this.setState({ isRoomEncrypted: await this.getIsRoomEncrypted() }); + break; default: this.updatePermissions(this.state.room); } @@ -2247,7 +2262,7 @@ export class RoomView extends React.Component { searchInfo={this.state.search} onCancelClick={this.onCancelSearchClick} onSearchScopeChange={this.onSearchScopeChange} - isRoomEncrypted={this.context.client.isRoomEncrypted(this.state.room.roomId)} + isRoomEncrypted={this.state.isRoomEncrypted} /> ); } else if (showRoomUpgradeBar) { diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 78481c2fd0..e5fff8caf7 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -117,7 +117,7 @@ export function createTestClient(): MatrixClient { getCrypto: jest.fn().mockReturnValue({ getOwnDeviceKeys: jest.fn(), - getUserDeviceInfo: jest.fn(), + getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()), getUserVerificationStatus: jest.fn(), getDeviceVerificationStatus: jest.fn(), resetKeyBackup: jest.fn(), diff --git a/test/unit-tests/components/structures/RoomView-test.tsx b/test/unit-tests/components/structures/RoomView-test.tsx index b6fbd2e850..18bc221beb 100644 --- a/test/unit-tests/components/structures/RoomView-test.tsx +++ b/test/unit-tests/components/structures/RoomView-test.tsx @@ -87,8 +87,7 @@ describe("RoomView", () => { beforeEach(() => { mockPlatformPeg({ reload: () => {} }); - stubClient(); - cli = mocked(MatrixClientPeg.safeGet()); + cli = mocked(stubClient()); room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org"); jest.spyOn(room, "findPredecessor"); @@ -247,8 +246,9 @@ describe("RoomView", () => { it("updates url preview visibility on encryption state change", async () => { room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Join); + jest.spyOn(cli, "getCrypto").mockReturnValue(crypto); // we should be starting unencrypted - expect(cli.isRoomEncrypted(room.roomId)).toEqual(false); + expect(await cli.getCrypto()?.isEncryptionEnabledInRoom(room.roomId)).toEqual(false); const roomViewInstance = await getRoomViewInstance(); @@ -263,7 +263,7 @@ describe("RoomView", () => { expect(roomViewInstance.state.showUrlPreview).toBe(true); // now enable encryption - cli.isRoomEncrypted.mockReturnValue(true); + jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true); // and fake an encryption event into the room to prompt it to re-check await act(() => @@ -427,7 +427,8 @@ describe("RoomView", () => { ]); jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(cli.getSafeUserId()); jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId])); - mocked(cli).isRoomEncrypted.mockReturnValue(true); + jest.spyOn(cli, "getCrypto").mockReturnValue(crypto); + jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true); await renderRoomView(); });