From f0c9a2624245b0a281327b0b9fc08f1a021b546b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 14:03:29 +0200 Subject: [PATCH 01/21] Add `jest-mock` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- package.json | 1 + yarn.lock | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/package.json b/package.json index 39f930af..e3ef048e 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.2.2", "jest-environment-jsdom": "^29.3.1", + "jest-mock": "^29.5.0", "prettier": "^2.6.2", "sass": "^1.42.1", "storybook-builder-vite": "^0.1.12", diff --git a/yarn.lock b/yarn.lock index 0051059e..2324d1e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2014,6 +2014,13 @@ dependencies: "@sinclair/typebox" "^0.24.1" +"@jest/schemas@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" + integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== + dependencies: + "@sinclair/typebox" "^0.25.16" + "@jest/source-map@^29.2.0": version "29.2.0" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" @@ -2088,6 +2095,18 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jest/types@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" + integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== + dependencies: + "@jest/schemas" "^29.4.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@joshwooding/vite-plugin-react-docgen-typescript@0.0.2": version "0.0.2" resolved "https://registry.yarnpkg.com/@joshwooding/vite-plugin-react-docgen-typescript/-/vite-plugin-react-docgen-typescript-0.0.2.tgz#e0ae8c94f468da3a273a7b0acf23ba3565f86cbc" @@ -3098,6 +3117,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== +"@sinclair/typebox@^0.25.16": + version "0.25.24" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" + integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== + "@sinonjs/commons@^1.7.0": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -10269,6 +10293,15 @@ jest-mock@^29.3.1: "@types/node" "*" jest-util "^29.3.1" +jest-mock@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.5.0.tgz#26e2172bcc71d8b0195081ff1f146ac7e1518aed" + integrity sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + jest-util "^29.5.0" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -10411,6 +10444,18 @@ jest-util@^29.3.1: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" + integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^29.2.2: version "29.2.2" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.2.2.tgz#e43ce1931292dfc052562a11bc681af3805eadce" From 11785fc243c7fab7b6c997111b6b932c785afd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 14:59:26 +0200 Subject: [PATCH 02/21] Avoid redirects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/App.tsx | 3 +- src/UrlParams.ts | 64 ++++++++++++----- src/initializer.tsx | 4 +- src/room/RoomRedirect.tsx | 44 ------------ test/UrlParams-test.ts | 146 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 197 insertions(+), 64 deletions(-) delete mode 100644 src/room/RoomRedirect.tsx create mode 100644 test/UrlParams-test.ts diff --git a/src/App.tsx b/src/App.tsx index d020655d..0822849d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,7 +23,6 @@ import { HomePage } from "./home/HomePage"; import { LoginPage } from "./auth/LoginPage"; import { RegisterPage } from "./auth/RegisterPage"; import { RoomPage } from "./room/RoomPage"; -import { RoomRedirect } from "./room/RoomRedirect"; import { ClientProvider } from "./ClientContext"; import { usePageFocusStyle } from "./usePageFocusStyle"; import { SequenceDiagramViewerPage } from "./SequenceDiagramViewerPage"; @@ -75,7 +74,7 @@ export default function App({ history }: AppProps) { - + diff --git a/src/UrlParams.ts b/src/UrlParams.ts index eb2b1795..55d8ee10 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 New Vector Ltd +Copyright 2022 - 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. @@ -14,9 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useMemo } from "react"; +import { useCallback, useEffect, useState } from "react"; import { useLocation } from "react-router-dom"; +import { Config } from "./config/Config"; + interface UrlParams { roomAlias: string | null; roomId: string | null; @@ -93,14 +95,38 @@ interface UrlParams { * @returns The app parameters encoded in the URL */ export const getUrlParams = ( - query: string = window.location.search, - fragment: string = window.location.hash + ignoreRoomAlias?: boolean, + location: Location = window.location ): UrlParams => { - const fragmentQueryStart = fragment.indexOf("?"); + const { href, origin, search, hash } = location; + + let roomAlias: string | undefined; + if (!ignoreRoomAlias) { + roomAlias = href.substring(origin.length + 1); + + // If we have none, we throw + if (!roomAlias) { + throw Error("No pathname"); + } + // Delete "/room/" and "?", if present + if (roomAlias.startsWith("room/")) { + roomAlias = roomAlias.substring("room/".length).split("?")[0]; + } + // Add "#", if not present + if (!roomAlias.includes("#")) { + roomAlias = `#${roomAlias}`; + } + // Add server part, if missing + if (!roomAlias.includes(":")) { + roomAlias = `${roomAlias}:${Config.defaultServerName()}`; + } + } + + const fragmentQueryStart = hash.indexOf("?"); const fragmentParams = new URLSearchParams( - fragmentQueryStart === -1 ? "" : fragment.substring(fragmentQueryStart) + fragmentQueryStart === -1 ? "" : hash.substring(fragmentQueryStart) ); - const queryParams = new URLSearchParams(query); + const queryParams = new URLSearchParams(search); // Normally, URL params should be encoded in the fragment so as to avoid // leaking them to the server. However, we also check the normal query @@ -114,16 +140,10 @@ export const getUrlParams = ( ...queryParams.getAll(name), ]; - // The part of the fragment before the ? - const fragmentRoute = - fragmentQueryStart === -1 - ? fragment - : fragment.substring(0, fragmentQueryStart); - const fontScale = parseFloat(getParam("fontScale") ?? ""); return { - roomAlias: fragmentRoute.length > 1 ? fragmentRoute : null, + roomAlias: !roomAlias || roomAlias.includes("!") ? null : roomAlias, roomId: getParam("roomId"), viaServers: getAllParams("via"), isEmbedded: hasParam("embed"), @@ -149,6 +169,18 @@ export const getUrlParams = ( * @returns The app parameters for the current URL */ export const useUrlParams = (): UrlParams => { - const { hash, search } = useLocation(); - return useMemo(() => getUrlParams(search, hash), [search, hash]); + const getParams = useCallback(() => { + return getUrlParams(false, window.location); + }, []); + + const reactDomLocation = useLocation(); + const [urlParams, setUrlParams] = useState(getParams()); + + useEffect(() => { + if (window.location !== reactDomLocation) { + setUrlParams(getParams()); + } + }, [getParams, reactDomLocation]); + + return urlParams; }; diff --git a/src/initializer.tsx b/src/initializer.tsx index 37e659e7..f8a6c985 100644 --- a/src/initializer.tsx +++ b/src/initializer.tsx @@ -55,7 +55,7 @@ export class Initializer { languageDetector.addDetector({ name: "urlFragment", // Look for a language code in the URL's fragment - lookup: () => getUrlParams().lang ?? undefined, + lookup: () => getUrlParams(true).lang ?? undefined, }); i18n @@ -136,7 +136,7 @@ export class Initializer { } // Custom fonts - const { fonts, fontScale } = getUrlParams(); + const { fonts, fontScale } = getUrlParams(true); if (fontScale !== null) { document.documentElement.style.setProperty( "--font-scale", diff --git a/src/room/RoomRedirect.tsx b/src/room/RoomRedirect.tsx deleted file mode 100644 index 3d45086d..00000000 --- a/src/room/RoomRedirect.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2022 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 { useEffect } from "react"; -import { useLocation, useHistory } from "react-router-dom"; - -import { Config } from "../config/Config"; -import { LoadingView } from "../FullScreenView"; - -// A component that, when loaded, redirects the client to a full room URL -// based on the current URL being an abbreviated room URL -export function RoomRedirect() { - const { pathname } = useLocation(); - const history = useHistory(); - - useEffect(() => { - let roomId = pathname; - - if (pathname.startsWith("/")) { - roomId = roomId.substring(1, roomId.length); - } - - if (!roomId.startsWith("#") && !roomId.startsWith("!")) { - roomId = `#${roomId}:${Config.defaultServerName()}`; - } - - history.replace(`/room/${roomId.toLowerCase()}`); - }, [pathname, history]); - - return ; -} diff --git a/test/UrlParams-test.ts b/test/UrlParams-test.ts new file mode 100644 index 00000000..9f691326 --- /dev/null +++ b/test/UrlParams-test.ts @@ -0,0 +1,146 @@ +/* +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 { mocked } from "jest-mock"; +import { getUrlParams } from "../src/UrlParams"; +import { Config } from "../src/config/Config"; + +const ROOM_NAME = "roomNameHere"; +const ROOM_ID = "d45f138fsd"; +const ORIGIN = "https://call.element.io"; +const HOMESERVER = "call.ems.host"; + +jest.mock("../src/config/Config"); + +describe("UrlParams", () => { + beforeAll(() => { + mocked(Config.defaultServerName).mockReturnValue("call.ems.host"); + }); + + describe("handles URL with /room/", () => { + it("and nothing else", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/${ROOM_NAME}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and #", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/#${ROOM_NAME}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and # and server part", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/#${ROOM_NAME}:${HOMESERVER}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and server part", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + }); + + describe("handles URL without /room/", () => { + it("and nothing else", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/${ROOM_NAME}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and with #", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/#${ROOM_NAME}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and with # and server part", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/#${ROOM_NAME}:${HOMESERVER}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + + it("and with server part", () => { + expect( + getUrlParams(false, { + origin: ORIGIN, + href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, + search: "", + hash: "", + } as Location).roomAlias + ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + }); + }); + + describe("handles search params", () => { + it("(roomId)", () => { + expect( + getUrlParams(true, { + search: `?roomId=${ROOM_ID}`, + hash: "", + } as Location).roomId + ).toBe(ROOM_ID); + }); + }); + + it("ignores room alias", () => { + expect( + getUrlParams(true, { + origin: ORIGIN, + href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, + hash: "", + search: "", + } as Location).roomAlias + ).toBeFalsy(); + }); +}); From fdc41aaa50238209235aa5dff0e8c2c6cea9a4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 16:20:19 +0200 Subject: [PATCH 03/21] Use friendly URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/App.tsx | 3 --- src/home/CallList.tsx | 5 ++++- src/home/RegisteredView.tsx | 2 +- src/home/UnauthenticatedView.tsx | 5 ++--- src/matrix-utils.ts | 12 ++++-------- 5 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 0822849d..e9a1129d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -67,9 +67,6 @@ export default function App({ history }: AppProps) { - - - diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx index 545dfade..2cc821b9 100644 --- a/src/home/CallList.tsx +++ b/src/home/CallList.tsx @@ -74,7 +74,10 @@ function CallTile({ }: CallTileProps) { return (
- + { setOnFinished(() => { setClient(client, session); const aliasLocalpart = roomAliasLocalpartFromRoomName(roomName); - const [, serverName] = client.getUserId().split(":"); - history.push(`/room/#${aliasLocalpart}:${serverName}`); + history.push(`/${aliasLocalpart}`); }); setLoading(false); @@ -100,7 +99,7 @@ export const UnauthenticatedView: FC = () => { // Only consider the registration successful if we managed to create the room, too setClient(client, session); - history.push(`/room/${roomIdOrAlias}`); + history.push(`/${roomIdOrAlias.substring(1).split(":")[0]}`); } submit().catch((error) => { diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index 9a7645d2..85a7b313 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -346,15 +346,11 @@ export async function createRoom( // Returns a URL to that will load Element Call with the given room export function getRoomUrl(roomIdOrAlias: string): string { if (roomIdOrAlias.startsWith("#")) { - const [localPart, host] = roomIdOrAlias.replace("#", "").split(":"); - - if (host !== Config.defaultServerName()) { - return `${window.location.protocol}//${window.location.host}/room/${roomIdOrAlias}`; - } else { - return `${window.location.protocol}//${window.location.host}/${localPart}`; - } + return `${window.location.protocol}//${window.location.host}/${ + roomIdOrAlias.substring(1).split(":")[0] + }`; } else { - return `${window.location.protocol}//${window.location.host}/room/#?roomId=${roomIdOrAlias}`; + return `${window.location.protocol}//${window.location.host}?roomId=${roomIdOrAlias}`; } } From e1ef18093f6ee7dede747b2c83ae0f636de09558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 19:23:26 +0200 Subject: [PATCH 04/21] Fix alias vs id + participants bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/CallList.tsx | 16 ++++++++-------- src/home/useGroupCallRooms.ts | 13 +++++++------ test/home/CallList-test.tsx | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx index 2cc821b9..c3d5a6ae 100644 --- a/src/home/CallList.tsx +++ b/src/home/CallList.tsx @@ -35,13 +35,13 @@ export function CallList({ rooms, client, disableFacepile }: CallListProps) { return ( <>
- {rooms.map(({ roomId, roomName, avatarUrl, participants }) => ( + {rooms.map(({ roomAlias, roomName, avatarUrl, participants }) => ( @@ -59,7 +59,7 @@ export function CallList({ rooms, client, disableFacepile }: CallListProps) { interface CallTileProps { name: string; avatarUrl: string; - roomId: string; + roomAlias: string; participants: RoomMember[]; client: MatrixClient; disableFacepile?: boolean; @@ -67,7 +67,7 @@ interface CallTileProps { function CallTile({ name, avatarUrl, - roomId, + roomAlias, participants, client, disableFacepile, @@ -75,7 +75,7 @@ function CallTile({ return (
{name} - {getRoomUrl(roomId)} + {getRoomUrl(roomAlias)} {participants && !disableFacepile && (
); diff --git a/src/home/useGroupCallRooms.ts b/src/home/useGroupCallRooms.ts index fcbe67ff..b1eb2e7a 100644 --- a/src/home/useGroupCallRooms.ts +++ b/src/home/useGroupCallRooms.ts @@ -22,7 +22,7 @@ import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEv import { useState, useEffect } from "react"; export interface GroupCallRoom { - roomId: string; + roomAlias: string; roomName: string; avatarUrl: string; room: Room; @@ -79,23 +79,24 @@ function sortRooms(client: MatrixClient, rooms: Room[]): Room[] { } export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] { - const [rooms, setRooms] = useState([]); + const [rooms, setRooms] = useState([]); useEffect(() => { function updateRooms() { const groupCalls = client.groupCallEventHandler.groupCalls.values(); const rooms = Array.from(groupCalls).map((groupCall) => groupCall.room); - const sortedRooms = sortRooms(client, rooms); - const items = sortedRooms.map((room) => { + const filteredRooms = rooms.filter((r) => r.getCanonicalAlias()); // We don't display rooms without an alias + const sortedRooms = sortRooms(client, filteredRooms); + const items: GroupCallRoom[] = sortedRooms.map((room) => { const groupCall = client.getGroupCallForRoom(room.roomId); return { - roomId: room.getCanonicalAlias() || room.roomId, + roomAlias: room.getCanonicalAlias(), roomName: room.name, avatarUrl: room.getMxcAvatarUrl(), room, groupCall, - participants: [...groupCall.participants], + participants: [...groupCall.participants.keys()], }; }); setRooms(items); diff --git a/test/home/CallList-test.tsx b/test/home/CallList-test.tsx index 7b3925d4..7dfb7b21 100644 --- a/test/home/CallList-test.tsx +++ b/test/home/CallList-test.tsx @@ -34,7 +34,7 @@ describe("CallList", () => { it("should show room", async () => { const rooms = [ - { roomName: "Room #1", roomId: "!roomId" }, + { roomName: "Room #1", roomAlias: "!roomId" }, ] as GroupCallRoom[]; const result = renderComponent(rooms); From b08044c06d48b95456fbcc0533e8d13a1b38f723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 19:30:38 +0200 Subject: [PATCH 05/21] More fixes of id vs alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/UnauthenticatedView.tsx | 6 +++--- test/home/CallList-test.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/home/UnauthenticatedView.tsx b/src/home/UnauthenticatedView.tsx index f49cf218..820b11ab 100644 --- a/src/home/UnauthenticatedView.tsx +++ b/src/home/UnauthenticatedView.tsx @@ -78,9 +78,9 @@ export const UnauthenticatedView: FC = () => { true ); - let roomIdOrAlias: string; + let roomAlias: string; try { - [roomIdOrAlias] = await createRoom(client, roomName, ptt); + [roomAlias] = await createRoom(client, roomName, ptt); } catch (error) { if (error.errcode === "M_ROOM_IN_USE") { setOnFinished(() => { @@ -99,7 +99,7 @@ export const UnauthenticatedView: FC = () => { // Only consider the registration successful if we managed to create the room, too setClient(client, session); - history.push(`/${roomIdOrAlias.substring(1).split(":")[0]}`); + history.push(`/${roomAlias.substring(1).split(":")[0]}`); } submit().catch((error) => { diff --git a/test/home/CallList-test.tsx b/test/home/CallList-test.tsx index 7dfb7b21..a161960f 100644 --- a/test/home/CallList-test.tsx +++ b/test/home/CallList-test.tsx @@ -34,7 +34,7 @@ describe("CallList", () => { it("should show room", async () => { const rooms = [ - { roomName: "Room #1", roomAlias: "!roomId" }, + { roomName: "Room #1", roomAlias: "#room-name:server.org" }, ] as GroupCallRoom[]; const result = renderComponent(rooms); From 0bba62045110c1722263029b35ae7f39f71e044f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 19:32:25 +0200 Subject: [PATCH 06/21] Further id vs alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/RegisteredView.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx index cd5bc02a..3d0c6eb0 100644 --- a/src/home/RegisteredView.tsx +++ b/src/home/RegisteredView.tsx @@ -69,10 +69,10 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { setError(undefined); setLoading(true); - const [roomIdOrAlias] = await createRoom(client, roomName, ptt); + const [roomAlias] = await createRoom(client, roomName, ptt); - if (roomIdOrAlias) { - history.push(`/${roomIdOrAlias.substring(1).split(":")[0]}`); + if (roomAlias) { + history.push(`/${roomAlias.substring(1).split(":")[0]}`); } } From 8fbcc06cd8f5635fc166665204c7300f1557883d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 Jul 2023 20:05:08 +0200 Subject: [PATCH 07/21] Don't use the whole `Location` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/UrlParams.ts | 54 ++++++++++++--------------- test/UrlParams-test.ts | 84 +++++++++--------------------------------- 2 files changed, 41 insertions(+), 97 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 55d8ee10..f41e3cfa 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useCallback, useEffect, useState } from "react"; +import { useMemo } from "react"; import { useLocation } from "react-router-dom"; import { Config } from "./config/Config"; @@ -96,27 +96,28 @@ interface UrlParams { */ export const getUrlParams = ( ignoreRoomAlias?: boolean, - location: Location = window.location + search = window.location.search, + pathname = window.location.pathname, + hash = window.location.hash ): UrlParams => { - const { href, origin, search, hash } = location; - let roomAlias: string | undefined; if (!ignoreRoomAlias) { - roomAlias = href.substring(origin.length + 1); + if (hash === "") { + roomAlias = pathname.substring(1); // Strip the "/" - // If we have none, we throw - if (!roomAlias) { - throw Error("No pathname"); + // Delete "/room/" and "?", if present + if (roomAlias.startsWith("room/")) { + roomAlias = roomAlias.substring("room/".length); + } + // Add "#", if not present + if (!roomAlias.startsWith("#")) { + roomAlias = `#${roomAlias}`; + } + } else { + roomAlias = hash; } - // Delete "/room/" and "?", if present - if (roomAlias.startsWith("room/")) { - roomAlias = roomAlias.substring("room/".length).split("?")[0]; - } - // Add "#", if not present - if (!roomAlias.includes("#")) { - roomAlias = `#${roomAlias}`; - } - // Add server part, if missing + + // Add server part, if not present if (!roomAlias.includes(":")) { roomAlias = `${roomAlias}:${Config.defaultServerName()}`; } @@ -169,18 +170,9 @@ export const getUrlParams = ( * @returns The app parameters for the current URL */ export const useUrlParams = (): UrlParams => { - const getParams = useCallback(() => { - return getUrlParams(false, window.location); - }, []); - - const reactDomLocation = useLocation(); - const [urlParams, setUrlParams] = useState(getParams()); - - useEffect(() => { - if (window.location !== reactDomLocation) { - setUrlParams(getParams()); - } - }, [getParams, reactDomLocation]); - - return urlParams; + const { search, pathname, hash } = useLocation(); + return useMemo( + () => getUrlParams(false, search, pathname, hash), + [search, pathname, hash] + ); }; diff --git a/test/UrlParams-test.ts b/test/UrlParams-test.ts index 9f691326..9d1e5198 100644 --- a/test/UrlParams-test.ts +++ b/test/UrlParams-test.ts @@ -32,115 +32,67 @@ describe("UrlParams", () => { describe("handles URL with /room/", () => { it("and nothing else", () => { - expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/${ROOM_NAME}`, - search: "", - hash: "", - } as Location).roomAlias - ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + expect(getUrlParams(false, "", `/room/${ROOM_NAME}`, "").roomAlias).toBe( + `#${ROOM_NAME}:${HOMESERVER}` + ); }); it("and #", () => { expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/#${ROOM_NAME}`, - search: "", - hash: "", - } as Location).roomAlias + getUrlParams(false, "", `${ORIGIN}/room/`, `#${ROOM_NAME}`).roomAlias ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); }); it("and # and server part", () => { expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/#${ROOM_NAME}:${HOMESERVER}`, - search: "", - hash: "", - } as Location).roomAlias + getUrlParams(false, "", `/room/`, `#${ROOM_NAME}:${HOMESERVER}`) + .roomAlias ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); }); it("and server part", () => { expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, - search: "", - hash: "", - } as Location).roomAlias + getUrlParams(false, "", `/room/${ROOM_NAME}:${HOMESERVER}`, "") + .roomAlias ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); }); }); describe("handles URL without /room/", () => { it("and nothing else", () => { - expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/${ROOM_NAME}`, - search: "", - hash: "", - } as Location).roomAlias - ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + expect(getUrlParams(false, "", `/${ROOM_NAME}`, "").roomAlias).toBe( + `#${ROOM_NAME}:${HOMESERVER}` + ); }); it("and with #", () => { - expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/#${ROOM_NAME}`, - search: "", - hash: "", - } as Location).roomAlias - ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); + expect(getUrlParams(false, "", "", `#${ROOM_NAME}`).roomAlias).toBe( + `#${ROOM_NAME}:${HOMESERVER}` + ); }); it("and with # and server part", () => { expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/#${ROOM_NAME}:${HOMESERVER}`, - search: "", - hash: "", - } as Location).roomAlias + getUrlParams(false, "", "", `#${ROOM_NAME}:${HOMESERVER}`).roomAlias ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); }); it("and with server part", () => { expect( - getUrlParams(false, { - origin: ORIGIN, - href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, - search: "", - hash: "", - } as Location).roomAlias + getUrlParams(false, "", `/${ROOM_NAME}:${HOMESERVER}`, "").roomAlias ).toBe(`#${ROOM_NAME}:${HOMESERVER}`); }); }); describe("handles search params", () => { it("(roomId)", () => { - expect( - getUrlParams(true, { - search: `?roomId=${ROOM_ID}`, - hash: "", - } as Location).roomId - ).toBe(ROOM_ID); + expect(getUrlParams(true, `?roomId=${ROOM_ID}`).roomId).toBe(ROOM_ID); }); }); it("ignores room alias", () => { expect( - getUrlParams(true, { - origin: ORIGIN, - href: `${ORIGIN}/room/${ROOM_NAME}:${HOMESERVER}`, - hash: "", - search: "", - } as Location).roomAlias + getUrlParams(true, "", `/room/${ROOM_NAME}:${HOMESERVER}`).roomAlias ).toBeFalsy(); }); }); From 6c8b96ed3d5393882cb0ebed8e678f726774e0f9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 4 Jul 2023 18:57:35 +0100 Subject: [PATCH 08/21] Use prebuilt image for docker compose --- backend-docker-compose.yml | 11 ++-- backend/auth/Dockerfile | 15 ----- backend/auth/go.mod | 20 ------ backend/auth/go.sum | 94 --------------------------- backend/auth/server.go | 126 ------------------------------------- 5 files changed, 4 insertions(+), 262 deletions(-) delete mode 100644 backend/auth/Dockerfile delete mode 100644 backend/auth/go.mod delete mode 100644 backend/auth/go.sum delete mode 100644 backend/auth/server.go diff --git a/backend-docker-compose.yml b/backend-docker-compose.yml index d575cf18..58b147e9 100644 --- a/backend-docker-compose.yml +++ b/backend-docker-compose.yml @@ -1,5 +1,3 @@ -# LiveKit requires host networking, which is only available on Linux -# This compose will not function correctly on Mac or Windows version: "3.9" networks: @@ -7,15 +5,14 @@ networks: services: auth-service: - build: - context: ./backend/auth - container_name: auth-server + image: ghcr.io/vector-im/lk-jwt-service:latest-ci hostname: auth-server ports: - 8881:8080 environment: - - LIVEKIT_KEY=${LIVEKIT_KEY} - - LIVEKIT_SECRET=${LIVEKIT_SECRET} + - LIVEKIT_URL=ws://localhost:7880 + - LIVEKIT_KEY=devkey + - LIVEKIT_SECRET=secret deploy: restart_policy: condition: on-failure diff --git a/backend/auth/Dockerfile b/backend/auth/Dockerfile deleted file mode 100644 index c7bbd955..00000000 --- a/backend/auth/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM golang:1.20-alpine - -WORKDIR /app - -COPY go.mod ./ -COPY go.sum ./ -RUN go mod download - -COPY *.go ./ - -RUN go build -o /auth-server - -EXPOSE 8080 - -CMD [ "/auth-server" ] diff --git a/backend/auth/go.mod b/backend/auth/go.mod deleted file mode 100644 index 75d1a533..00000000 --- a/backend/auth/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module vector-auth-server - -go 1.20 - -require github.com/livekit/protocol v1.5.7 - -require ( - github.com/go-jose/go-jose/v3 v3.0.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/twitchtv/twirp v8.1.3+incompatible // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/backend/auth/go.sum b/backend/auth/go.sum deleted file mode 100644 index e8419741..00000000 --- a/backend/auth/go.sum +++ /dev/null @@ -1,94 +0,0 @@ -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= -github.com/frostbyte73/core v0.0.9 h1:AmE9GjgGpPsWk9ZkmY3HsYUs2hf2tZt+/W6r49URBQI= -github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= -github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c= -github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkDaKb5iXdynYrzB84ErPPO4LbRASk58= -github.com/livekit/protocol v1.5.7 h1:jZeFQEmLuIhFblXDGPRCBbfjVJHb+YU7AsO+SMoXF70= -github.com/livekit/protocol v1.5.7/go.mod h1:ZaOnsvP+JS4s7vI1UO+JVdBagvvLp/lBXDAl2hkDS0I= -github.com/livekit/psrpc v0.3.0 h1:giBZsfM3CWA0oIYXofsMITbVQtyW7u/ES9sQmVspHPM= -github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/nats-io/nats.go v1.25.0 h1:t5/wCPGciR7X3Mu8QOi4jiJaXaWM8qtkLu4lzGZvYHE= -github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4= -github.com/pion/ice/v2 v2.3.4 h1:tjYjTLpWyZzUjpDnzk6T1y3oQyhyY2DiM2t095iDhyQ= -github.com/pion/interceptor v0.1.16 h1:0GDZrfNO+BmVNWymS31fMlVtPO2IJVBzy2Qq5XCYMIg= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/srtp/v2 v2.0.14 h1:Glt0MqEvINrDxL+aanmK4DiFjvs+uN2iYc6XD/iKpoY= -github.com/pion/stun v0.5.2 h1:J/8glQnDV91dfk2+ZnGN0o9bUJgABhTNljwfQWByoXE= -github.com/pion/transport/v2 v2.2.0 h1:u5lFqFHkXLMXMzai8tixZDfVjb8eOjH35yCunhPeb1c= -github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= -github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54= -github.com/pion/webrtc/v3 v3.2.4 h1:gWSx4dqQb77051qBT9ipDrOyP6/sGYcAQP3UPjM8pU8= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU= -github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/auth/server.go b/backend/auth/server.go deleted file mode 100644 index f099784e..00000000 --- a/backend/auth/server.go +++ /dev/null @@ -1,126 +0,0 @@ -package main - -import ( - "encoding/json" - "log" - "net/http" - "os" - - "time" - - "github.com/livekit/protocol/auth" -) - -type Handler struct { - key, secret string -} - -type OpenIDTokenType struct { -} - -type SFURequest struct { - Room string `json:"room"` - OpenIDToken OpenIDTokenType `json:"openid_token"` - DeviceID string `json:"device_id"` - RemoveMeUserID string `json:"remove_me_user_id"` // we'll get this from OIDC -} - -type SFUResponse struct { - URL string `json:"url"` - JWT string `json:"jwt"` -} - -func (h *Handler) handle(w http.ResponseWriter, r *http.Request) { - log.Printf("Request from %s", r.RemoteAddr) - - // Set the CORS headers - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Methods", "POST") - w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token") - - // Handle preflight request (CORS) - if r.Method == "OPTIONS" { - w.WriteHeader(http.StatusOK) - return - } else if r.Method == "POST" { - var body SFURequest - err := json.NewDecoder(r.Body).Decode(&body) - if err != nil { - log.Printf("Error decoding JSON: %v", err) - w.WriteHeader(http.StatusBadRequest) - return - } - - if body.Room == "" { - log.Printf("Request missing room") - w.WriteHeader(http.StatusBadRequest) - return - } - - token, err := getJoinToken(h.key, h.secret, body.Room, body.RemoveMeUserID+":"+body.DeviceID) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - - res := SFUResponse{URL: "http://localhost:7880/", JWT: token} - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(res) - } else { - w.WriteHeader(http.StatusMethodNotAllowed) - } - - /* - roomName := r.URL.Query().Get("roomName") - name := r.URL.Query().Get("name") - identity := r.URL.Query().Get("identity") - - log.Printf("roomName: %s, name: %s, identity: %s", roomName, name, identity) - - if roomName == "" || name == "" || identity == "" { - w.WriteHeader(http.StatusBadRequest) - return - } - */ -} - -func main() { - key := os.Getenv("LIVEKIT_KEY") - secret := os.Getenv("LIVEKIT_SECRET") - - // Check if the key and secret are empty. - if key == "" || secret == "" { - log.Fatal("LIVEKIT_KEY and LIVEKIT_SECRET environment variables must be set") - } - - log.Printf("LIVEKIT_KEY: %s and LIVEKIT_SECRET %s", key, secret) - - handler := &Handler{ - key: key, - secret: secret, - } - - http.HandleFunc("/sfu/get", handler.handle) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func getJoinToken(apiKey, apiSecret, room, identity string) (string, error) { - at := auth.NewAccessToken(apiKey, apiSecret) - - canPublish := true - canSubscribe := true - grant := &auth.VideoGrant{ - RoomJoin: true, - RoomCreate: true, - CanPublish: &canPublish, - CanSubscribe: &canSubscribe, - Room: room, - } - - at.AddGrant(grant). - SetIdentity(identity). - SetValidFor(time.Hour) - - return at.ToJWT() -} From 607e1b7b43aac502e9ca1c790fe9370eaf298573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 6 Jul 2023 12:02:39 +0200 Subject: [PATCH 09/21] Fix `getRoomUrl()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/matrix-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index 85a7b313..3bef9e40 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -350,7 +350,7 @@ export function getRoomUrl(roomIdOrAlias: string): string { roomIdOrAlias.substring(1).split(":")[0] }`; } else { - return `${window.location.protocol}//${window.location.host}?roomId=${roomIdOrAlias}`; + return `${window.location.protocol}//${window.location.host}/room?roomId=${roomIdOrAlias}`; } } From 4a4c66caf2ab947ea1d02f15591c77304e2e5451 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 13 Jul 2023 09:55:33 +0100 Subject: [PATCH 10/21] Update README with new dev backend instructions. --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8210bf77..5545d44e 100644 --- a/README.md +++ b/README.md @@ -88,15 +88,12 @@ yarn dev ### Backend -Add in you `.env` in root dir with: +A docker compose file is provided to start a LiveKit server and auth +service for development. These use a test 'secret' published in this +repository, so this must be used only for local development and +***never be exposed to the public Internet.*** -```yaml -# Develop backend settings: -LIVEKIT_KEY="devkey" -LIVEKIT_SECRET="secret" -``` - -Add SFU parameter in your local config `./public/config.yml`: +To use it, add SFU parameter in your local config `./public/config.yml`: ```yaml "livekit": { From c99a400dd1181183c7d516b5a66547c484e28794 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 13 Jul 2023 09:58:56 +0100 Subject: [PATCH 11/21] Prettier --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5545d44e..b671ac88 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ yarn dev A docker compose file is provided to start a LiveKit server and auth service for development. These use a test 'secret' published in this repository, so this must be used only for local development and -***never be exposed to the public Internet.*** +**_never be exposed to the public Internet._** To use it, add SFU parameter in your local config `./public/config.yml`: From 3c30a5812baeff309951d3c44ddb3e6257fe7865 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Fri, 14 Jul 2023 12:41:21 -0400 Subject: [PATCH 12/21] Fix registration not logging you into the new account --- src/auth/RegisterPage.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/auth/RegisterPage.tsx b/src/auth/RegisterPage.tsx index a486aa46..c49d9b43 100644 --- a/src/auth/RegisterPage.tsx +++ b/src/auth/RegisterPage.tsx @@ -80,11 +80,7 @@ export const RegisterPage: FC = () => { passwordlessUser ); - if (!client || !client.groupCallEventHandler || !setClient) { - return; - } - - if (passwordlessUser) { + if (client && client?.groupCallEventHandler && passwordlessUser) { // Migrate the user's rooms for (const groupCall of client.groupCallEventHandler.groupCalls.values()) { const roomId = groupCall.room.roomId; @@ -107,7 +103,7 @@ export const RegisterPage: FC = () => { } } - setClient({ client: newClient, session }); + setClient?.({ client: newClient, session }); PosthogAnalytics.instance.eventSignup.cacheSignupEnd(new Date()); }; From be340ca4e4b02d870165bce7f02bad81e884b400 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 14 Jul 2023 18:42:31 +0100 Subject: [PATCH 13/21] Add more logs to JWT service code --- src/livekit/openIDSFU.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 3cc61fbb..083e95b2 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -41,13 +41,16 @@ export async function getSFUConfigWithOpenID( // if the call has a livekit service URL, try it. if (groupCall.livekitServiceURL) { try { - logger.info(`Trying to get JWT from ${groupCall.livekitServiceURL}...`); + logger.info( + `Trying to get JWT from call's configured URL of ${groupCall.livekitServiceURL}...` + ); const sfuConfig = await getLiveKitJWT( client, groupCall.livekitServiceURL, roomName, openIdToken ); + logger.info(`Got JWT from call state event URL.`); return sfuConfig; } catch (e) { @@ -71,9 +74,12 @@ export async function getSFUConfigWithOpenID( openIdToken ); - logger.info(`Updating call livekit service URL with: ${urlFromConf}...`); + logger.info( + `Got JWT, updating call livekit service URL with: ${urlFromConf}...` + ); try { await groupCall.updateLivekitServiceURL(urlFromConf); + logger.info(`Call livekit service URL updated.`); } catch (e) { logger.warn( `Failed to update call livekit service URL: continuing anyway.` From 2d3d58cdc75f86c7f78148e4cf3eac7b436a5e6d Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Fri, 14 Jul 2023 14:46:45 -0400 Subject: [PATCH 14/21] Fix avatar field in profile settings being hidden It was being hidden when you didn't yet have an avatar set, which made it impossible to ever set one. --- src/input/AvatarInputField.tsx | 2 +- src/settings/ProfileSettingsTab.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/input/AvatarInputField.tsx b/src/input/AvatarInputField.tsx index 484f440e..0218258e 100644 --- a/src/input/AvatarInputField.tsx +++ b/src/input/AvatarInputField.tsx @@ -34,7 +34,7 @@ import styles from "./AvatarInputField.module.css"; interface Props extends AllHTMLAttributes { id: string; label: string; - avatarUrl: string; + avatarUrl: string | undefined; displayName: string; onRemoveAvatar: () => void; } diff --git a/src/settings/ProfileSettingsTab.tsx b/src/settings/ProfileSettingsTab.tsx index 8de8dd52..e6a59634 100644 --- a/src/settings/ProfileSettingsTab.tsx +++ b/src/settings/ProfileSettingsTab.tsx @@ -77,7 +77,7 @@ export function ProfileSettingsTab({ client }: Props) { return (
- {avatarUrl && displayName && ( + {displayName && ( Date: Mon, 17 Jul 2023 12:41:46 +0100 Subject: [PATCH 15/21] Remove redundant server url from readme example --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b671ac88..4133ed31 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,6 @@ To use it, add SFU parameter in your local config `./public/config.yml`: ```yaml "livekit": { - "server_url": "ws://localhost:7880", "jwt_service_url": "http:/localhost:8881" }, ``` From f28cf0ce699dd2f8391afc9251371754b78746b1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 17 Jul 2023 19:16:28 +0100 Subject: [PATCH 16/21] Fix embedded mode This was trying to get the room alias, which causes the config to be read. We don't need the room alias here though, so pass the flag to not return it. --- src/widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget.ts b/src/widget.ts index 93107fcd..fc7e529b 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -109,7 +109,7 @@ export const widget: WidgetHelpers | null = (() => { baseUrl, e2eEnabled, allowIceFallback, - } = getUrlParams(); + } = getUrlParams(true); if (!roomId) throw new Error("Room ID must be supplied"); if (!userId) throw new Error("User ID must be supplied"); if (!deviceId) throw new Error("Device ID must be supplied"); From c15b2a62d5d8a69a40ebe247d1168233616c1b77 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 17 Jul 2023 19:22:22 +0100 Subject: [PATCH 17/21] Fix jsdoc --- src/UrlParams.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index f41e3cfa..4a37254a 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -90,8 +90,10 @@ interface UrlParams { /** * Gets the app parameters for the current URL. - * @param query The URL query string - * @param fragment The URL fragment string + * @param ignoreRoomAlias If true, does not try to parse a room alias from the URL + * @param search The URL search string + * @param pathname The URL path name + * @param hash The URL hash * @returns The app parameters encoded in the URL */ export const getUrlParams = ( From 4eb9326bd2079b87262181dcad6320f2d645e921 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 17 Jul 2023 19:33:29 +0100 Subject: [PATCH 18/21] Enable debug logging Fixes https://github.com/vector-im/element-call/issues/1267 --- src/livekit/useLiveKit.ts | 4 +++- vite.config.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/livekit/useLiveKit.ts b/src/livekit/useLiveKit.ts index 7a0a5330..dac6a052 100644 --- a/src/livekit/useLiveKit.ts +++ b/src/livekit/useLiveKit.ts @@ -1,4 +1,4 @@ -import { Room, RoomOptions } from "livekit-client"; +import { Room, RoomOptions, setLogLevel } from "livekit-client"; import { useLiveKitRoom } from "@livekit/components-react"; import { useMemo } from "react"; @@ -15,6 +15,8 @@ export type DeviceChoices = { enabled: boolean; }; +setLogLevel("debug"); + export function useLiveKit( userChoices: UserChoices, sfuConfig?: SFUConfig diff --git a/vite.config.js b/vite.config.js index bbebd667..13274776 100644 --- a/vite.config.js +++ b/vite.config.js @@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { const plugins = [ react(), - basicSsl(), + //basicSsl(), svgrPlugin(), htmlTemplate.default({ data: { From b7f5069e9854eefbffe5d3e3d0424961a0b2af17 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:41:54 +0200 Subject: [PATCH 19/21] set video enabled even if tracks are not yet initialized (#1273) This could fix "muted on join issues" but could introduce issues where the buttons show unmuted even if no device is available. Signed-off-by: Timo K --- src/room/VideoPreview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/room/VideoPreview.tsx b/src/room/VideoPreview.tsx index ae5e311c..5fac133e 100644 --- a/src/room/VideoPreview.tsx +++ b/src/room/VideoPreview.tsx @@ -106,11 +106,11 @@ export function VideoPreview({ matrixInfo, onUserChoicesChanged }: Props) { onUserChoicesChanged({ video: { selectedId: videoIn.selectedId, - enabled: videoEnabled && !!videoTrack, + enabled: videoEnabled, }, audio: { selectedId: audioIn.selectedId, - enabled: audioEnabled && !!audioTrack, + enabled: audioEnabled, }, }); }, [ From 50ba23b7ea43a2f3b610a0510a61075d37c3e19d Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 18 Jul 2023 16:59:51 +0100 Subject: [PATCH 20/21] Revert unintentional change --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index 13274776..bbebd667 100644 --- a/vite.config.js +++ b/vite.config.js @@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { const plugins = [ react(), - //basicSsl(), + basicSsl(), svgrPlugin(), htmlTemplate.default({ data: { From 9200fac28e28650f556b631b64131a691d30ea83 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 20 Jul 2023 18:30:20 +0100 Subject: [PATCH 21/21] Fix URL Co-authored-by: Robin --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4133ed31..7731d6fe 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ To use it, add SFU parameter in your local config `./public/config.yml`: ```yaml "livekit": { - "jwt_service_url": "http:/localhost:8881" + "jwt_service_url": "http://localhost:8881" }, ```