mirror of
https://github.com/vector-im/element-call.git
synced 2026-11-07 00:52:28 +00:00
115 lines
4.0 KiB
TypeScript
115 lines
4.0 KiB
TypeScript
/*
|
|
Copyright 2023, 2024 New Vector Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { useEffect, useMemo } from "react";
|
|
import { logger } from "matrix-js-sdk/lib/logger";
|
|
|
|
import {
|
|
setLocalStorageItemReactive,
|
|
useLocalStorage,
|
|
} from "../useLocalStorage";
|
|
import { getUrlParams, useUrlParams } from "../UrlParams";
|
|
import { E2eeType, type EncryptionSystem } from "@element-hq/matrixrtc-sdk";
|
|
import { useClient } from "../ClientContext";
|
|
|
|
/**
|
|
* This setter will update the state for all `useRoomSharedKey` hooks
|
|
* if the password is different from the one in local storage or if its not yet in the local storage.
|
|
*/
|
|
export function saveKeyForRoom(roomId: string, password: string): void {
|
|
if (
|
|
localStorage.getItem(getRoomSharedKeyLocalStorageKey(roomId)) !== password
|
|
)
|
|
setLocalStorageItemReactive(
|
|
getRoomSharedKeyLocalStorageKey(roomId),
|
|
password,
|
|
);
|
|
}
|
|
|
|
const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
|
|
`room-shared-key-${roomId}`;
|
|
|
|
/**
|
|
* An up-to-date shared key for the room. Either from local storage or the value from `setInitialValue`.
|
|
* @param roomId The room ID we want the shared key for.
|
|
* @param setInitialValue The value we get from the URL. The hook will overwrite the local storage value with this.
|
|
* @returns [roomSharedKey, setRoomSharedKey] like a react useState hook.
|
|
*/
|
|
const useRoomSharedKey = (
|
|
roomId: string,
|
|
setInitialValue?: string,
|
|
): [string | null, setKey: (key: string) => void] => {
|
|
const [roomSharedKey, setRoomSharedKey] = useLocalStorage(
|
|
getRoomSharedKeyLocalStorageKey(roomId),
|
|
);
|
|
useEffect(() => {
|
|
// If setInitialValue is available, update the local storage (usually the password from the url).
|
|
// This will update roomSharedKey but wont update the returned value since
|
|
// that already defaults to setInitialValue.
|
|
if (setInitialValue) setRoomSharedKey(setInitialValue);
|
|
}, [setInitialValue, setRoomSharedKey]);
|
|
|
|
// make sure we never return the initial null value from `useLocalStorage`
|
|
return [setInitialValue ?? roomSharedKey, setRoomSharedKey];
|
|
};
|
|
|
|
/**
|
|
* The shared key for a room, preferring one supplied in the parameters Element
|
|
* Call was started with over whatever is in local storage.
|
|
*/
|
|
function keyForRoom(
|
|
roomId: string,
|
|
paramsRoomId: string | null,
|
|
password: string | null,
|
|
): string | null {
|
|
if (roomId !== paramsRoomId)
|
|
logger.warn(
|
|
"requested key for a roomId which is not the current call room id (from the URL)",
|
|
roomId,
|
|
paramsRoomId,
|
|
);
|
|
return (
|
|
password ?? localStorage.getItem(getRoomSharedKeyLocalStorageKey(roomId))
|
|
);
|
|
}
|
|
|
|
export function getKeyForRoom(roomId: string): string | null {
|
|
const { roomId: paramsRoomId, password } = getUrlParams();
|
|
return keyForRoom(roomId, paramsRoomId, password);
|
|
}
|
|
|
|
export { type EncryptionSystem } from "@element-hq/matrixrtc-sdk";
|
|
|
|
export function useRoomEncryptionSystem(roomId: string): EncryptionSystem {
|
|
const { client } = useClient();
|
|
const { roomId: paramsRoomId, password } = useUrlParams();
|
|
|
|
const [storedPassword] = useRoomSharedKey(
|
|
// TODO: this passes an already-prefixed key where a room ID is expected, so
|
|
// the local storage key ends up prefixed twice and never matches what
|
|
// saveKeyForRoom writes. Preserved as-is here to keep this commit a pure
|
|
// refactor; the reactive read is effectively dead until it is fixed.
|
|
getRoomSharedKeyLocalStorageKey(roomId),
|
|
keyForRoom(roomId, paramsRoomId, password) ?? undefined,
|
|
);
|
|
|
|
const room = client?.getRoom(roomId);
|
|
const e2eeSystem = <EncryptionSystem>useMemo(() => {
|
|
if (!room) return { kind: E2eeType.NONE };
|
|
if (storedPassword)
|
|
return {
|
|
kind: E2eeType.SHARED_KEY,
|
|
secret: storedPassword,
|
|
};
|
|
if (room.hasEncryptionStateEvent()) {
|
|
return { kind: E2eeType.PER_PARTICIPANT };
|
|
}
|
|
return { kind: E2eeType.NONE };
|
|
}, [room, storedPassword]);
|
|
return e2eeSystem;
|
|
}
|