Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide rooms we don't have the key for in recents list #1902

Merged
merged 2 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion src/UrlParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface RoomIdentifier {
// the situations that call for this behavior ('isEmbedded'). This makes it
// clearer what each flag means, and helps us avoid coupling Element Call's
// behavior to the needs of specific consumers.
interface UrlParams {
export interface UrlParams {
// Widget api related params
widgetId: string | null;
parentUrl: string | null;
Expand Down
52 changes: 32 additions & 20 deletions src/e2ee/sharedKeyManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ limitations under the License.
*/

import { useEffect, useMemo } from "react";
import { Room } from "matrix-js-sdk";

import { setLocalStorageItem, useLocalStorage } from "../useLocalStorage";
import { useClient } from "../ClientContext";
import { useUrlParams } from "../UrlParams";
import { UrlParams, getUrlParams, useUrlParams } from "../UrlParams";
import { widget } from "../widget";

export const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
export function saveKeyForRoom(roomId: string, password: string): void {
setLocalStorageItem(getRoomSharedKeyLocalStorageKey(roomId), password);
}

const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
`room-shared-key-${roomId}`;

const useInternalRoomSharedKey = (roomId: string): string | null => {
Expand All @@ -31,6 +36,22 @@ const useInternalRoomSharedKey = (roomId: string): string | null => {
return roomSharedKey;
};

export function getKeyForRoom(roomId: string): string | null {
saveKeyFromUrlParams(getUrlParams());
const key = getRoomSharedKeyLocalStorageKey(roomId);
return localStorage.getItem(key);
}

function saveKeyFromUrlParams(urlParams: UrlParams): void {
if (!urlParams.password || !urlParams.roomId) return;

// Take the key from the URL and save it.
// It's important to always use the room ID specified in the URL
// when saving keys rather than whatever the current room ID might be,
// in case we've moved to a different room but the URL hasn't changed.
saveKeyForRoom(urlParams.roomId, urlParams.password);
}

/**
* Extracts the room password from the URL if one is present, saving it in localstorage
* and returning it in a tuple with the corresponding room ID from the URL.
Expand All @@ -40,18 +61,7 @@ const useInternalRoomSharedKey = (roomId: string): string | null => {
const useKeyFromUrl = (): [string, string] | [undefined, undefined] => {
const urlParams = useUrlParams();

useEffect(() => {
if (!urlParams.password || !urlParams.roomId) return;
if (!urlParams.roomId) return;

setLocalStorageItem(
// We set the Item by only using data from the url. This way we
// make sure, we always have matching pairs in the LocalStorage,
// as they occur in the call links.
getRoomSharedKeyLocalStorageKey(urlParams.roomId),
urlParams.password,
);
}, [urlParams]);
useEffect(() => saveKeyFromUrlParams(urlParams), [urlParams]);

return urlParams.roomId && urlParams.password
? [urlParams.roomId, urlParams.password]
Expand All @@ -74,12 +84,14 @@ export const useRoomSharedKey = (roomId: string): string | undefined => {

export const useIsRoomE2EE = (roomId: string): boolean | null => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing | null on this return type makes me wonder what we were ever returning null for, and why we aren't doing that now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we used to return null if we couldn't find the room: https://github.com/vector-im/element-call/blame/535712d108a3257501457ae24f497dc7d52ed671/src/e2ee/sharedKeyManagement.ts#L76 - unsure why that changed though.

const { client } = useClient();
const room = useMemo(() => client?.getRoom(roomId) ?? null, [roomId, client]);
const room = useMemo(() => client?.getRoom(roomId), [roomId, client]);

return useMemo(() => !room || isRoomE2EE(room), [room]);
};

export function isRoomE2EE(room: Room): boolean {
// For now, rooms in widget mode are never considered encrypted.
// In the future, when widget mode gains encryption support, then perhaps we
// should inspect the e2eEnabled URL parameter here?
return useMemo(
() => widget === null && (room === null || !room.getCanonicalAlias()),
[room],
);
};
return widget === null && !room.getCanonicalAlias();
}
14 changes: 13 additions & 1 deletion src/home/useGroupCallRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler";
import { useState, useEffect } from "react";

import { getKeyForRoom, isRoomE2EE } from "../e2ee/sharedKeyManagement";

export interface GroupCallRoom {
roomAlias?: string;
roomName: string;
Expand Down Expand Up @@ -78,6 +80,14 @@ function sortRooms(client: MatrixClient, rooms: Room[]): Room[] {
});
}

function roomIsJoinable(room: Room): boolean {
if (isRoomE2EE(room)) {
return Boolean(getKeyForRoom(room.roomId));
} else {
return true;
}
}

export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
const [rooms, setRooms] = useState<GroupCallRoom[]>([]);

Expand All @@ -88,7 +98,9 @@ export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
}

const groupCalls = client.groupCallEventHandler.groupCalls.values();
const rooms = Array.from(groupCalls).map((groupCall) => groupCall.room);
const rooms = Array.from(groupCalls)
.map((groupCall) => groupCall.room)
.filter(roomIsJoinable);
const sortedRooms = sortRooms(client, rooms);
const items = sortedRooms.map((room) => {
const groupCall = client.getGroupCallForRoom(room.roomId)!;
Expand Down
8 changes: 2 additions & 6 deletions src/matrix-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ import IndexedDBWorker from "./IndexedDBWorker?worker";
import { getUrlParams, PASSWORD_STRING } from "./UrlParams";
import { loadOlm } from "./olm";
import { Config } from "./config/Config";
import { setLocalStorageItem } from "./useLocalStorage";
import { getRoomSharedKeyLocalStorageKey } from "./e2ee/sharedKeyManagement";
import { E2eeType } from "./e2ee/e2eeType";
import { saveKeyForRoom } from "./e2ee/sharedKeyManagement";

export const fallbackICEServerAllowed =
import.meta.env.VITE_FALLBACK_STUN_ALLOWED === "true";
Expand Down Expand Up @@ -359,10 +358,7 @@ export async function createRoom(
let password;
if (e2ee == E2eeType.SHARED_KEY) {
password = secureRandomBase64Url(16);
setLocalStorageItem(
getRoomSharedKeyLocalStorageKey(result.room_id),
password,
);
saveKeyForRoom(result.room_id, password);
}

return {
Expand Down