Files
element-call/src/auth/useInteractiveRegistration.ts

145 lines
4.1 KiB
TypeScript
Raw Normal View History

2022-05-04 17:09:48 +01:00
/*
Copyright 2022-2024 New Vector Ltd.
2022-05-04 17:09:48 +01:00
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
2022-05-04 17:09:48 +01:00
*/
import { useState, useEffect, useCallback, useRef } from "react";
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
2024-06-04 11:20:25 -04:00
import {
createClient,
type MatrixClient,
type RegisterResponse,
2024-06-04 11:20:25 -04:00
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
2022-01-05 16:47:53 -08:00
import { initClient } from "../utils/matrix";
import { type Session } from "../ClientContext";
2022-12-20 17:26:45 +00:00
import { Config } from "../config/Config";
import { widget } from "../widget";
export const useInteractiveRegistration = (
oldClient?: MatrixClient,
): {
privacyPolicyUrl?: string;
recaptchaKey?: string;
register: (
username: string,
password: string,
displayName: string,
recaptchaResponse: string,
2023-10-11 10:42:04 -04:00
passwordlessUser: boolean,
) => Promise<[MatrixClient, Session]>;
} => {
const [privacyPolicyUrl, setPrivacyPolicyUrl] = useState<string | undefined>(
2023-10-11 10:42:04 -04:00
undefined,
);
const [recaptchaKey, setRecaptchaKey] = useState<string | undefined>(
2023-10-11 10:42:04 -04:00
undefined,
);
const authClient = useRef<MatrixClient | undefined>(undefined);
if (!authClient.current) {
2022-12-20 17:26:45 +00:00
authClient.current = createClient({
baseUrl: Config.defaultHomeserverUrl()!,
2022-12-20 17:26:45 +00:00
});
}
2022-01-05 16:47:53 -08:00
useEffect(() => {
if (widget) return;
// An empty registerRequest is used to get the privacy policy and recaptcha key.
authClient.current!.registerRequest({}).catch((error) => {
setPrivacyPolicyUrl(
2023-10-11 10:42:04 -04:00
error.data?.params["m.login.terms"]?.policies?.privacy_policy?.en?.url,
);
setRecaptchaKey(error.data?.params["m.login.recaptcha"]?.public_key);
2022-01-05 16:47:53 -08:00
});
}, []);
2022-01-05 16:47:53 -08:00
const register = useCallback(
2022-02-15 12:46:58 -08:00
async (
username: string,
password: string,
displayName: string,
recaptchaResponse: string,
2023-10-11 10:42:04 -04:00
passwordlessUser: boolean,
): Promise<[MatrixClient, Session]> => {
2022-01-05 16:47:53 -08:00
const interactiveAuth = new InteractiveAuth({
matrixClient: authClient.current!,
doRequest: async (auth): Promise<RegisterResponse> =>
authClient.current!.registerRequest({
2022-01-05 16:47:53 -08:00
username,
password,
auth: auth || undefined,
}),
stateUpdated: (nextStage, status): void => {
2022-01-05 16:47:53 -08:00
if (status.error) {
throw new Error(status.error);
2022-01-05 16:47:53 -08:00
}
if (nextStage === "m.login.terms") {
interactiveAuth
.submitAuthDict({
type: "m.login.terms",
})
.catch((e) => {
logger.error(e);
});
2022-01-05 16:47:53 -08:00
} else if (nextStage === "m.login.recaptcha") {
interactiveAuth
.submitAuthDict({
type: "m.login.recaptcha",
response: recaptchaResponse,
})
.catch((e) => {
logger.error(e);
});
2022-01-05 16:47:53 -08:00
}
},
requestEmailToken: async (): Promise<{ sid: string }> =>
Promise.resolve({ sid: "dummy" }),
2022-01-05 16:47:53 -08:00
});
// XXX: This claims to return an IAuthData which contains none of these
// things - the js-sdk types may be wrong?
2022-06-01 16:05:58 +01:00
/* eslint-disable camelcase,@typescript-eslint/no-explicit-any */
2022-01-05 16:47:53 -08:00
const { user_id, access_token, device_id } =
(await interactiveAuth.attemptAuth()) as any;
await oldClient?.logout(true);
const client = await initClient(
{
baseUrl: Config.defaultHomeserverUrl()!,
accessToken: access_token,
userId: user_id,
deviceId: device_id,
},
2023-10-11 10:42:04 -04:00
false,
);
2022-01-05 16:47:53 -08:00
2022-02-15 12:46:58 -08:00
await client.setDisplayName(displayName);
2022-01-18 13:41:14 -08:00
const session: Session = {
user_id,
device_id,
access_token,
passwordlessUser,
};
/* eslint-enable camelcase */
2022-01-05 16:47:53 -08:00
if (passwordlessUser) {
session.tempPassword = password;
}
const user = client.getUser(client.getUserId()!)!;
user.setRawDisplayName(displayName);
user.setDisplayName(displayName);
return [client, session];
2022-01-05 16:47:53 -08:00
},
[oldClient],
2022-01-05 16:47:53 -08:00
);
return { privacyPolicyUrl, recaptchaKey, register };
};