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

Commit 74885c9

Browse files
authored
Merge pull request #42 from element-hq/langleyd/mobile_registeration
Add mobile registration
2 parents 9426fec + 20a4f0a commit 74885c9

File tree

6 files changed

+94
-22
lines changed

6 files changed

+94
-22
lines changed

res/css/_components.pcss

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
@import "./structures/auth/_ConfirmSessionLockTheftView.pcss";
9595
@import "./structures/auth/_Login.pcss";
9696
@import "./structures/auth/_LoginSplashView.pcss";
97+
@import "./structures/auth/_MobileRegistration.pcss";
9798
@import "./structures/auth/_Registration.pcss";
9899
@import "./structures/auth/_SessionLockStolenView.pcss";
99100
@import "./structures/auth/_SetupEncryptionBody.pcss";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
Copyright 2024 New Vector Ltd.
3+
4+
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
5+
Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
.mx_MobileRegister_body {
9+
padding: 32px;
10+
}

src/components/structures/MatrixChat.tsx

+28-6
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ import { cleanUpDraftsIfRequired } from "../../DraftCleaner";
140140
// legacy export
141141
export { default as Views } from "../../Views";
142142

143-
const AUTH_SCREENS = ["register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];
143+
const AUTH_SCREENS = ["register", "mobile_register", "login", "forgot_password", "start_sso", "start_cas", "welcome"];
144144

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

245246
hideToSRUsers: false,
247+
isMobileRegistration: false,
246248

247249
syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
248250
resizeNotifier: new ResizeNotifier(),
@@ -650,6 +652,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
650652
case "require_registration":
651653
startAnyRegistrationFlow(payload as any);
652654
break;
655+
case "start_mobile_registration":
656+
this.startRegistration(payload.params || {}, true);
657+
break;
653658
case "start_registration":
654659
if (Lifecycle.isSoftLogout()) {
655660
this.onSoftLogout();
@@ -946,19 +951,28 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
946951
});
947952
}
948953

949-
private async startRegistration(params: { [key: string]: string }): Promise<void> {
954+
private async startRegistration(params: { [key: string]: string }, isMobileRegistration?: boolean): Promise<void> {
950955
if (!SettingsStore.getValue(UIFeature.Registration)) {
951956
this.showScreen("welcome");
952957
return;
953958
}
959+
const isMobileRegistrationAllowed =
960+
isMobileRegistration && SettingsStore.getValue("Registration.mobileRegistrationHelper");
954961

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

959-
// Only honour params if they are all present, otherwise we reset
960-
// HS and IS URLs when switching to registration.
961-
if (params.client_secret && params.session_id && params.hs_url && params.is_url && params.sid) {
966+
if (isMobileRegistrationAllowed && params.hs_url) {
967+
try {
968+
const config = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(params.hs_url);
969+
newState.serverConfig = config;
970+
} catch (err) {
971+
logger.warn("Failed to load hs_url param:", params.hs_url);
972+
}
973+
} else if (params.client_secret && params.session_id && params.hs_url && params.is_url && params.sid) {
974+
// Only honour params if they are all present, otherwise we reset
975+
// HS and IS URLs when switching to registration.
962976
newState.serverConfig = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(
963977
params.hs_url,
964978
params.is_url,
@@ -978,10 +992,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
978992
newState.register_id_sid = params.sid;
979993
}
980994

995+
newState.isMobileRegistration = isMobileRegistrationAllowed;
996+
981997
this.setStateForNewView(newState);
982998
ThemeController.isLogin = true;
983999
this.themeWatcher.recheck();
984-
this.notifyNewScreen("register");
1000+
this.notifyNewScreen(isMobileRegistrationAllowed ? "mobile_register" : "register");
9851001
}
9861002

9871003
// switch view to the given room
@@ -1721,6 +1737,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
17211737
params: params,
17221738
});
17231739
PerformanceMonitor.instance.start(PerformanceEntryNames.REGISTER);
1740+
} else if (screen === "mobile_register") {
1741+
dis.dispatch({
1742+
action: "start_mobile_registration",
1743+
params: params,
1744+
});
17241745
} else if (screen === "login") {
17251746
dis.dispatch({
17261747
action: "start_login",
@@ -2080,6 +2101,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
20802101
onServerConfigChange={this.onServerConfigChange}
20812102
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
20822103
fragmentAfterLogin={fragmentAfterLogin}
2104+
mobileRegister={this.state.isMobileRegistration}
20832105
{...this.getServerProperties()}
20842106
/>
20852107
);

src/components/structures/auth/Registration.tsx

+50-16
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ const debuglog = (...args: any[]): void => {
5353
}
5454
};
5555

56+
export interface MobileRegistrationResponse {
57+
user_id: string;
58+
home_server: string;
59+
access_token: string;
60+
device_id: string;
61+
}
62+
5663
interface IProps {
5764
serverConfig: ValidatedServerConfig;
5865
defaultDeviceDisplayName?: string;
@@ -62,7 +69,7 @@ interface IProps {
6269
sessionId?: string;
6370
idSid?: string;
6471
fragmentAfterLogin?: string;
65-
72+
mobileRegister?: boolean;
6673
// Called when the user has logged in. Params:
6774
// - object with userId, deviceId, homeserverUrl, identityServerUrl, accessToken
6875
// - The user's password, if available and applicable (may be cached in memory
@@ -410,18 +417,33 @@ export default class Registration extends React.Component<IProps, IState> {
410417
debuglog("Registration: ui auth finished:", { hasEmail, hasAccessToken });
411418
// don’t log in if we found a session for a different user
412419
if (hasAccessToken && !newState.differentLoggedInUserId) {
413-
await this.props.onLoggedIn(
414-
{
415-
userId,
416-
deviceId: (response as RegisterResponse).device_id!,
417-
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
418-
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
419-
accessToken,
420-
},
421-
this.state.formVals.password!,
422-
);
420+
if (this.props.mobileRegister) {
421+
const mobileResponse: MobileRegistrationResponse = {
422+
user_id: userId,
423+
home_server: this.state.matrixClient.getHomeserverUrl(),
424+
access_token: accessToken,
425+
device_id: (response as RegisterResponse).device_id!,
426+
};
427+
const event = new CustomEvent<MobileRegistrationResponse>("mobileregistrationresponse", {
428+
detail: mobileResponse,
429+
});
430+
window.dispatchEvent(event);
431+
newState.busy = false;
432+
newState.completedNoSignin = true;
433+
} else {
434+
await this.props.onLoggedIn(
435+
{
436+
userId,
437+
deviceId: (response as RegisterResponse).device_id!,
438+
homeserverUrl: this.state.matrixClient.getHomeserverUrl(),
439+
identityServerUrl: this.state.matrixClient.getIdentityServerUrl(),
440+
accessToken,
441+
},
442+
this.state.formVals.password!,
443+
);
423444

424-
this.setupPushers();
445+
this.setupPushers();
446+
}
425447
} else {
426448
newState.busy = false;
427449
newState.completedNoSignin = true;
@@ -558,7 +580,7 @@ export default class Registration extends React.Component<IProps, IState> {
558580
);
559581
} else if (this.state.matrixClient && this.state.flows.length) {
560582
let ssoSection: JSX.Element | undefined;
561-
if (this.state.ssoFlow) {
583+
if (!this.props.mobileRegister && this.state.ssoFlow) {
562584
let continueWithSection;
563585
const providers = this.state.ssoFlow.identity_providers || [];
564586
// when there is only a single (or 0) providers we show a wide button with `Continue with X` text
@@ -591,7 +613,6 @@ export default class Registration extends React.Component<IProps, IState> {
591613
</React.Fragment>
592614
);
593615
}
594-
595616
return (
596617
<React.Fragment>
597618
{ssoSection}
@@ -660,7 +681,9 @@ export default class Registration extends React.Component<IProps, IState> {
660681
let body;
661682
if (this.state.completedNoSignin) {
662683
let regDoneText;
663-
if (this.state.differentLoggedInUserId) {
684+
if (this.props.mobileRegister) {
685+
regDoneText = undefined;
686+
} else if (this.state.differentLoggedInUserId) {
664687
regDoneText = (
665688
<div>
666689
<p>
@@ -717,6 +740,15 @@ export default class Registration extends React.Component<IProps, IState> {
717740
{regDoneText}
718741
</div>
719742
);
743+
} else if (this.props.mobileRegister) {
744+
body = (
745+
<Fragment>
746+
<h1>{_t("auth|mobile_create_account_title", { hsName: this.props.serverConfig.hsName })}</h1>
747+
{errorText}
748+
{serverDeadSection}
749+
{this.renderRegisterComponent()}
750+
</Fragment>
751+
);
720752
} else {
721753
body = (
722754
<Fragment>
@@ -746,7 +778,9 @@ export default class Registration extends React.Component<IProps, IState> {
746778
</Fragment>
747779
);
748780
}
749-
781+
if (this.props.mobileRegister) {
782+
return <div className="mx_MobileRegister_body">{body}</div>;
783+
}
750784
return (
751785
<AuthPage>
752786
<AuthHeader />

src/i18n/strings/en_EN.json

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@
229229
},
230230
"misconfigured_body": "Ask your %(brand)s admin to check <a>your config</a> for incorrect or duplicate entries.",
231231
"misconfigured_title": "Your %(brand)s is misconfigured",
232+
"mobile_create_account_title": "You're about to create an account on %(hsName)s",
232233
"msisdn_field_description": "Other users can invite you to rooms using your contact details",
233234
"msisdn_field_label": "Phone",
234235
"msisdn_field_number_invalid": "That phone number doesn't look quite right, please check and try again",

src/settings/Settings.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,10 @@ export const SETTINGS: { [setting: string]: ISetting } = {
876876
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
877877
default: null,
878878
},
879+
"Registration.mobileRegistrationHelper": {
880+
supportedLevels: [SettingLevel.CONFIG],
881+
default: false,
882+
},
879883
"autocompleteDelay": {
880884
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
881885
default: 200,

0 commit comments

Comments
 (0)