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

Add mobile registration #42

Merged
merged 7 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/_components.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
@import "./structures/auth/_ConfirmSessionLockTheftView.pcss";
@import "./structures/auth/_Login.pcss";
@import "./structures/auth/_LoginSplashView.pcss";
@import "./structures/auth/_MobileRegistration.pcss";
@import "./structures/auth/_Registration.pcss";
@import "./structures/auth/_SessionLockStolenView.pcss";
@import "./structures/auth/_SetupEncryptionBody.pcss";
Expand Down
10 changes: 10 additions & 0 deletions res/css/structures/auth/_MobileRegistration.pcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Copyright 2024 New Vector Ltd.

SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

.mx_MobileRegister_body {
padding: 32px;
}
34 changes: 28 additions & 6 deletions src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ import { cleanUpDraftsIfRequired } from "../../DraftCleaner";
// legacy export
export { default as Views } from "../../Views";

const AUTH_SCREENS = ["register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];
const AUTH_SCREENS = ["register", "mobile_register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];

// Actions that are redirected through the onboarding process prior to being
// re-dispatched. NOTE: some actions are non-trivial and would require
Expand Down Expand Up @@ -189,6 +189,7 @@ interface IState {
register_session_id?: string;
// eslint-disable-next-line camelcase
register_id_sid?: string;
isMobileRegistration?: boolean;
// When showing Modal dialogs we need to set aria-hidden on the root app element
// and disable it when there are no dialogs
hideToSRUsers: boolean;
Expand Down Expand Up @@ -243,6 +244,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
currentUserId: null,

hideToSRUsers: false,
isMobileRegistration: false,

syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
resizeNotifier: new ResizeNotifier(),
Expand Down Expand Up @@ -650,6 +652,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
case "require_registration":
startAnyRegistrationFlow(payload as any);
break;
case "start_mobile_registration":
this.startRegistration(payload.params || {}, true);
break;
case "start_registration":
if (Lifecycle.isSoftLogout()) {
this.onSoftLogout();
Expand Down Expand Up @@ -946,19 +951,28 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
});
}

private async startRegistration(params: { [key: string]: string }): Promise<void> {
private async startRegistration(params: { [key: string]: string }, isMobileRegistration?: boolean): Promise<void> {
if (!SettingsStore.getValue(UIFeature.Registration)) {
this.showScreen("welcome");
return;
}
const isMobileRegistrationAllowed =
isMobileRegistration && SettingsStore.getValue("Registration.mobileRegistrationHelper");

const newState: Partial<IState> = {
view: Views.REGISTER,
};

// Only honour params if they are all present, otherwise we reset
// HS and IS URLs when switching to registration.
if (params.client_secret && params.session_id && params.hs_url && params.is_url && params.sid) {
if (isMobileRegistrationAllowed && params.hs_url) {
try {
const config = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(params.hs_url);
newState.serverConfig = config;
} catch (err) {
logger.warn("Failed to load hs_url param:", params.hs_url);
}
} else if (params.client_secret && params.session_id && params.hs_url && params.is_url && params.sid) {
// Only honour params if they are all present, otherwise we reset
// HS and IS URLs when switching to registration.
newState.serverConfig = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
params.hs_url,
params.is_url,
Expand All @@ -978,10 +992,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
newState.register_id_sid = params.sid;
}

newState.isMobileRegistration = isMobileRegistrationAllowed;

this.setStateForNewView(newState);
ThemeController.isLogin = true;
this.themeWatcher.recheck();
this.notifyNewScreen("register");
this.notifyNewScreen(isMobileRegistrationAllowed ? "mobile_register" : "register");
}

// switch view to the given room
Expand Down Expand Up @@ -1721,6 +1737,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
params: params,
});
PerformanceMonitor.instance.start(PerformanceEntryNames.REGISTER);
} else if (screen === "mobile_register") {
dis.dispatch({
action: "start_mobile_registration",
params: params,
});
} else if (screen === "login") {
dis.dispatch({
action: "start_login",
Expand Down Expand Up @@ -2080,6 +2101,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
onServerConfigChange={this.onServerConfigChange}
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
fragmentAfterLogin={fragmentAfterLogin}
mobileRegister={this.state.isMobileRegistration}
{...this.getServerProperties()}
/>
);
Expand Down
66 changes: 50 additions & 16 deletions src/components/structures/auth/Registration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ const debuglog = (...args: any[]): void => {
}
};

export interface MobileRegistrationResponse {
user_id: string;
home_server: string;
access_token: string;
device_id: string;
}

interface IProps {
serverConfig: ValidatedServerConfig;
defaultDeviceDisplayName?: string;
Expand All @@ -62,7 +69,7 @@ interface IProps {
sessionId?: string;
idSid?: string;
fragmentAfterLogin?: string;

mobileRegister?: boolean;
// Called when the user has logged in. Params:
// - object with userId, deviceId, homeserverUrl, identityServerUrl, accessToken
// - The user's password, if available and applicable (may be cached in memory
Expand Down Expand Up @@ -410,18 +417,33 @@ export default class Registration extends React.Component<IProps, IState> {
debuglog("Registration: ui auth finished:", { hasEmail, hasAccessToken });
// don’t log in if we found a session for a different user
if (hasAccessToken && !newState.differentLoggedInUserId) {
await this.props.onLoggedIn(
{
userId,
deviceId: (response as RegisterResponse).device_id!,
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
accessToken,
},
this.state.formVals.password!,
);
if (this.props.mobileRegister) {
const mobileResponse: MobileRegistrationResponse = {
user_id: userId,
home_server: this.state.matrixClient.getHomeserverUrl(),
access_token: accessToken,
langleyd marked this conversation as resolved.
Show resolved Hide resolved
device_id: (response as RegisterResponse).device_id!,
};
const event = new CustomEvent<MobileRegistrationResponse>("mobileregistrationresponse", {
detail: mobileResponse,
});
window.dispatchEvent(event);
newState.busy = false;
newState.completedNoSignin = true;
} else {
await this.props.onLoggedIn(
{
userId,
deviceId: (response as RegisterResponse).device_id!,
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
accessToken,
},
this.state.formVals.password!,
);

this.setupPushers();
this.setupPushers();
}
} else {
newState.busy = false;
newState.completedNoSignin = true;
Expand Down Expand Up @@ -558,7 +580,7 @@ export default class Registration extends React.Component<IProps, IState> {
);
} else if (this.state.matrixClient && this.state.flows.length) {
let ssoSection: JSX.Element | undefined;
if (this.state.ssoFlow) {
if (!this.props.mobileRegister && this.state.ssoFlow) {
let continueWithSection;
const providers = this.state.ssoFlow.identity_providers || [];
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
Expand Down Expand Up @@ -591,7 +613,6 @@ export default class Registration extends React.Component<IProps, IState> {
</React.Fragment>
);
}

return (
<React.Fragment>
{ssoSection}
Expand Down Expand Up @@ -660,7 +681,9 @@ export default class Registration extends React.Component<IProps, IState> {
let body;
if (this.state.completedNoSignin) {
let regDoneText;
if (this.state.differentLoggedInUserId) {
if (this.props.mobileRegister) {
regDoneText = undefined;
} else if (this.state.differentLoggedInUserId) {
regDoneText = (
<div>
<p>
Expand Down Expand Up @@ -717,6 +740,15 @@ export default class Registration extends React.Component<IProps, IState> {
{regDoneText}
</div>
);
} else if (this.props.mobileRegister) {
body = (
<Fragment>
<h1>{_t("auth|mobile_create_account_title", { hsName: this.props.serverConfig.hsName })}</h1>
{errorText}
{serverDeadSection}
{this.renderRegisterComponent()}
</Fragment>
);
} else {
body = (
<Fragment>
Expand Down Expand Up @@ -746,7 +778,9 @@ export default class Registration extends React.Component<IProps, IState> {
</Fragment>
);
}

if (this.props.mobileRegister) {
return <div className="mx_MobileRegister_body">{body}</div>;
}
return (
<AuthPage>
<AuthHeader />
Expand Down
1 change: 1 addition & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
},
"misconfigured_body": "Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.",
"misconfigured_title": "Your %(brand)s is misconfigured",
"mobile_create_account_title": "You're about to create an account on %(hsName)s",
"msisdn_field_description": "Other users can invite you to rooms using your contact details",
"msisdn_field_label": "Phone",
"msisdn_field_number_invalid": "That phone number doesn't look quite right, please check and try again",
Expand Down
4 changes: 4 additions & 0 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,10 @@ export const SETTINGS: { [setting: string]: ISetting } = {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
default: null,
},
"Registration.mobileRegistrationHelper": {
supportedLevels: [SettingLevel.CONFIG],
default: false,
},
"autocompleteDelay": {
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
default: 200,
Expand Down
Loading