Store shared keys in local storage

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
Šimon Brandner
2023-08-08 13:46:51 +02:00
parent 59653fea07
commit 8fdc1e3684
4 changed files with 54 additions and 62 deletions

View File

@@ -0,0 +1,20 @@
/*
Copyright 2023 New Vector Ltd
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 { useSetting } from "../settings/useSetting";
export const useRoomSharedKey = (roomId: string, initialValue?: string) =>
useSetting(`room-shared-key-${roomId}`, initialValue);

View File

@@ -32,13 +32,14 @@ import { CallEndedView } from "./CallEndedView";
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { useProfile } from "../profile/useProfile";
import { E2EEConfig } from "../livekit/useLiveKit";
import { findDeviceByName } from "../media-utils";
import { OpenIDLoader } from "../livekit/OpenIDLoader";
import { ActiveCall } from "./InCallView";
import { Config } from "../config/Config";
import { MuteStates, useMuteStates } from "./MuteStates";
import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext";
import { useRoomSharedKey } from "../e2ee/sharedKeyManagement";
import { useUrlParams } from "../UrlParams";
declare global {
interface Window {
@@ -73,6 +74,8 @@ export function GroupCallView({
otelGroupCallMembership,
} = useGroupCall(groupCall, client);
const { password } = useUrlParams();
const { t } = useTranslation();
useEffect(() => {
@@ -241,8 +244,31 @@ export function GroupCallView({
}
}, [groupCall, state, leave]);
const [e2eeConfig, setE2EEConfig] = useState<E2EEConfig | undefined>(
undefined
const [e2eeSharedKey, setE2EESharedKey] = useRoomSharedKey(
groupCall.room.roomId,
password ?? undefined
);
useEffect(() => {
if (!password || password === e2eeSharedKey) return;
setE2EESharedKey(password);
}, [password, e2eeSharedKey, setE2EESharedKey]);
useEffect(() => {
const originalHash = location.hash;
let hash = originalHash === "" ? "#" : originalHash;
hash = hash.split("?password=")[0];
hash += `?password=${e2eeSharedKey ?? ""}`;
if (originalHash !== hash) {
location.replace(hash);
}
}, [e2eeSharedKey]);
const e2eeConfig = useMemo(
() => (e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined),
[e2eeSharedKey]
);
const onReconnect = useCallback(() => {
@@ -319,10 +345,7 @@ export function GroupCallView({
<LobbyView
matrixInfo={matrixInfo}
muteStates={muteStates}
onEnter={(e2eeConfig?: E2EEConfig) => {
setE2EEConfig(e2eeConfig);
enter();
}}
onEnter={() => enter()}
isEmbedded={isEmbedded}
hideHeader={hideHeader}
/>

View File

@@ -14,14 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {
useRef,
useEffect,
useState,
useCallback,
ChangeEvent,
FC,
} from "react";
import { useRef, useEffect, FC } from "react";
import { Trans, useTranslation } from "react-i18next";
import styles from "./LobbyView.module.css";
@@ -32,16 +25,12 @@ import { UserMenuContainer } from "../UserMenuContainer";
import { Body, Link } from "../typography/Typography";
import { useLocationNavigation } from "../useLocationNavigation";
import { MatrixInfo, VideoPreview } from "./VideoPreview";
import { E2EEConfig } from "../livekit/useLiveKit";
import { InputField } from "../input/Input";
import { useEnableE2EE } from "../settings/useSetting";
import { MuteStates } from "./MuteStates";
import { useUrlParams } from "../UrlParams";
interface Props {
matrixInfo: MatrixInfo;
muteStates: MuteStates;
onEnter: (e2eeConfig?: E2EEConfig) => void;
onEnter: () => void;
isEmbedded: boolean;
hideHeader: boolean;
}
@@ -53,13 +42,9 @@ export const LobbyView: FC<Props> = ({
isEmbedded,
hideHeader,
}) => {
const { password } = useUrlParams();
const { t } = useTranslation();
useLocationNavigation();
const [enableE2EE] = useEnableE2EE();
const joinCallButtonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
if (joinCallButtonRef.current) {
@@ -67,29 +52,6 @@ export const LobbyView: FC<Props> = ({
}
}, [joinCallButtonRef]);
const [e2eeSharedKey, setE2EESharedKey] = useState<string | undefined>(
password ?? undefined
);
const onE2EESharedKeyChanged = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
setE2EESharedKey(value === "" ? undefined : value);
},
[setE2EESharedKey]
);
useEffect(() => {
const originalHash = location.hash;
let hash = originalHash === "" ? "#" : originalHash;
hash = hash.split("?password=")[0];
hash += `?password=${e2eeSharedKey ?? ""}`;
if (originalHash !== hash) {
location.replace(hash);
}
}, [e2eeSharedKey]);
return (
<div className={styles.room}>
{!hideHeader && (
@@ -105,25 +67,12 @@ export const LobbyView: FC<Props> = ({
<div className={styles.joinRoom}>
<div className={styles.joinRoomContent}>
<VideoPreview matrixInfo={matrixInfo} muteStates={muteStates} />
{enableE2EE && (
<InputField
className={styles.passwordField}
label={t("Password (if none, E2EE is disabled)")}
type="text"
onChange={onE2EESharedKeyChanged}
value={e2eeSharedKey}
/>
)}
<Trans>
<Button
ref={joinCallButtonRef}
className={styles.copyButton}
size="lg"
onPress={() =>
onEnter(
e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined
)
}
onPress={() => onEnter()}
data-testid="lobby_joinCall"
>
Join call now

View File

@@ -30,7 +30,7 @@ const getSettingKey = (name: string): string => {
return `matrix-setting-${name}`;
};
// Like useState, but reads from and persists the value to localStorage
const useSetting = <T>(name: string, defaultValue: T): Setting<T> => {
export const useSetting = <T>(name: string, defaultValue: T): Setting<T> => {
const key = useMemo(() => getSettingKey(name), [name]);
const [value, setValue] = useState<T>(() => {