Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Use .well-known to discover a default rendezvous server for use with …
Browse files Browse the repository at this point in the history
…Sign in with QR (#11655)
  • Loading branch information
hughns authored Sep 28, 2023
1 parent 0518af7 commit 8442f1c
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/components/views/auth/LoginWithQR.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,11 @@ export default class LoginWithQR extends React.Component<IProps, IState> {
private generateCode = async (): Promise<void> => {
let rendezvous: MSC3906Rendezvous;
try {
const fallbackRzServer = this.props.client.getClientWellKnown()?.["io.element.rendezvous"]?.server;
const transport = new MSC3886SimpleHttpRendezvousTransport<MSC3903ECDHPayload>({
onFailure: this.onFailure,
client: this.props.client,
fallbackRzServer,
});

const channel = new MSC3903ECDHv2RendezvousChannel<MSC3906RendezvousPayload>(
Expand Down
6 changes: 5 additions & 1 deletion src/components/views/settings/devices/LoginWithQRSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
IServerVersions,
UNSTABLE_MSC3882_CAPABILITY,
Capabilities,
IClientWellKnown,
} from "matrix-js-sdk/src/matrix";

import { _t } from "../../../../languageHandler";
Expand All @@ -30,6 +31,7 @@ interface IProps {
onShowQr: () => void;
versions?: IServerVersions;
capabilities?: Capabilities;
wellKnown?: IClientWellKnown;
}

export default class LoginWithQRSection extends React.Component<IProps> {
Expand All @@ -43,7 +45,9 @@ export default class LoginWithQRSection extends React.Component<IProps> {
const capability = UNSTABLE_MSC3882_CAPABILITY.findIn<IMSC3882GetLoginTokenCapability>(this.props.capabilities);
const msc3882Supported =
!!this.props.versions?.unstable_features?.["org.matrix.msc3882"] || !!capability?.enabled;
const msc3886Supported = !!this.props.versions?.unstable_features?.["org.matrix.msc3886"];
const msc3886Supported =
!!this.props.versions?.unstable_features?.["org.matrix.msc3886"] ||
this.props.wellKnown?.["io.element.rendezvous"]?.server;
const offerShowQr = msc3882Supported && msc3886Supported;

// don't show anything if no method is available
Expand Down
10 changes: 8 additions & 2 deletions src/components/views/settings/tabs/user/SessionManagerTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";

Expand Down Expand Up @@ -180,6 +180,7 @@ const SessionManagerTab: React.FC = () => {
const currentUserMember = (userId && matrixClient?.getUser(userId)) || undefined;
const clientVersions = useAsyncMemo(() => matrixClient.getVersions(), [matrixClient]);
const capabilities = useAsyncMemo(async () => matrixClient?.getCapabilities(), [matrixClient]);
const wellKnown = useMemo(() => matrixClient?.getClientWellKnown(), [matrixClient]);

const onDeviceExpandToggle = (deviceId: ExtendedDevice["device_id"]): void => {
if (expandedDeviceIds.includes(deviceId)) {
Expand Down Expand Up @@ -329,7 +330,12 @@ const SessionManagerTab: React.FC = () => {
/>
</SettingsSubsection>
)}
<LoginWithQRSection onShowQr={onShowQrClicked} versions={clientVersions} capabilities={capabilities} />
<LoginWithQRSection
onShowQr={onShowQrClicked}
versions={clientVersions}
capabilities={capabilities}
wellKnown={wellKnown}
/>
</SettingsSection>
</SettingsTab>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function makeClient() {
currentState: {
on: jest.fn(),
},
getClientWellKnown: jest.fn().mockReturnValue({}),
} as unknown as MatrixClient);
}

Expand Down
25 changes: 22 additions & 3 deletions test/components/views/settings/devices/LoginWithQRSection-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ limitations under the License.

import { render } from "@testing-library/react";
import { mocked } from "jest-mock";
import { IServerVersions, MatrixClient, UNSTABLE_MSC3882_CAPABILITY } from "matrix-js-sdk/src/matrix";
import { IClientWellKnown, IServerVersions, MatrixClient, UNSTABLE_MSC3882_CAPABILITY } from "matrix-js-sdk/src/matrix";
import React from "react";

import LoginWithQRSection from "../../../../../src/components/views/settings/devices/LoginWithQRSection";
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";

function makeClient() {
function makeClient(wellKnown: IClientWellKnown) {
return mocked({
getUser: jest.fn(),
isGuest: jest.fn().mockReturnValue(false),
Expand All @@ -37,6 +37,7 @@ function makeClient() {
currentState: {
on: jest.fn(),
},
getClientWellKnown: jest.fn().mockReturnValue(wellKnown),
} as unknown as MatrixClient);
}

Expand All @@ -49,12 +50,13 @@ function makeVersions(unstableFeatures: Record<string, boolean>): IServerVersion

describe("<LoginWithQRSection />", () => {
beforeAll(() => {
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient());
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient({}));
});

const defaultProps = {
onShowQr: () => {},
versions: makeVersions({}),
wellKnown: {},
};

const getComponent = (props = {}) => <LoginWithQRSection {...defaultProps} {...props} />;
Expand Down Expand Up @@ -114,5 +116,22 @@ describe("<LoginWithQRSection />", () => {
);
expect(container).toMatchSnapshot();
});

it("MSC3882 r1 + .well-known", async () => {
const wellKnown = {
"io.element.rendezvous": {
server: "https://rz.local",
},
};
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(makeClient(wellKnown));
const { container } = render(
getComponent({
versions: makeVersions({}),
capabilities: { [UNSTABLE_MSC3882_CAPABILITY.name]: { enabled: true } },
wellKnown,
}),
);
expect(container).toMatchSnapshot();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,44 @@ exports[`<LoginWithQRSection /> should render panel MSC3882 + MSC3886 1`] = `
</div>
`;

exports[`<LoginWithQRSection /> should render panel MSC3882 r1 + .well-known 1`] = `
<div>
<div
class="mx_SettingsSubsection"
>
<div
class="mx_SettingsSubsectionHeading"
>
<h3
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
>
Sign in with QR code
</h3>
</div>
<div
class="mx_SettingsSubsection_content"
>
<div
class="mx_LoginWithQRSection"
>
<p
class="mx_SettingsTab_subsectionText"
>
You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.
</p>
<div
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
role="button"
tabindex="0"
>
Show QR code
</div>
</div>
</div>
</div>
</div>
`;

exports[`<LoginWithQRSection /> should render panel MSC3882 r1 + MSC3886 1`] = `
<div>
<div
Expand Down

0 comments on commit 8442f1c

Please sign in to comment.