Merge pull request #729 from matrix-org/dbkr/register_ui_auth
Port registration over to use InteractiveAuth
This commit is contained in:
@@ -27,6 +27,9 @@ export default React.createClass({
|
||||
displayName: 'InteractiveAuth',
|
||||
|
||||
propTypes: {
|
||||
// matrix client to use for UI auth requests
|
||||
matrixClient: React.PropTypes.object.isRequired,
|
||||
|
||||
// response from initial request. If not supplied, will do a request on
|
||||
// mount.
|
||||
authData: React.PropTypes.shape({
|
||||
@@ -38,11 +41,27 @@ export default React.createClass({
|
||||
// callback
|
||||
makeRequest: React.PropTypes.func.isRequired,
|
||||
|
||||
// callback called when the auth process has finished
|
||||
// callback called when the auth process has finished,
|
||||
// successfully or unsuccessfully.
|
||||
// @param {bool} status True if the operation requiring
|
||||
// auth was completed sucessfully, false if canceled.
|
||||
// @param result The result of the authenticated call
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
onAuthFinished: React.PropTypes.func.isRequired,
|
||||
|
||||
// Inputs provided by the user to the auth process
|
||||
// and used by various stages. As passed to js-sdk
|
||||
// interactive-auth
|
||||
inputs: React.PropTypes.object,
|
||||
|
||||
// As js-sdk interactive-auth
|
||||
makeRegistrationUrl: React.PropTypes.func,
|
||||
sessionId: React.PropTypes.string,
|
||||
clientSecret: React.PropTypes.string,
|
||||
emailSid: React.PropTypes.string,
|
||||
|
||||
// If true, poll to see if the auth flow has been completed
|
||||
// out-of-band
|
||||
poll: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
@@ -60,12 +79,18 @@ export default React.createClass({
|
||||
this._authLogic = new InteractiveAuth({
|
||||
authData: this.props.authData,
|
||||
doRequest: this._requestCallback,
|
||||
startAuthStage: this._startAuthStage,
|
||||
inputs: this.props.inputs,
|
||||
stateUpdated: this._authStateUpdated,
|
||||
matrixClient: this.props.matrixClient,
|
||||
sessionId: this.props.sessionId,
|
||||
clientSecret: this.props.clientSecret,
|
||||
emailSid: this.props.emailSid,
|
||||
});
|
||||
|
||||
this._authLogic.attemptAuth().then((result) => {
|
||||
this.props.onFinished(true, result);
|
||||
this.props.onAuthFinished(true, result);
|
||||
}).catch((error) => {
|
||||
this.props.onAuthFinished(false, error);
|
||||
console.error("Error during user-interactive auth:", error);
|
||||
if (this._unmounted) {
|
||||
return;
|
||||
@@ -76,17 +101,32 @@ export default React.createClass({
|
||||
errorText: msg
|
||||
});
|
||||
}).done();
|
||||
|
||||
this._intervalId = null;
|
||||
if (this.props.poll) {
|
||||
this._intervalId = setInterval(() => {
|
||||
this._authLogic.poll();
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this._unmounted = true;
|
||||
|
||||
if (this._intervalId !== null) {
|
||||
clearInterval(this._intervalId);
|
||||
}
|
||||
},
|
||||
|
||||
_startAuthStage: function(stageType, error) {
|
||||
_authStateUpdated: function(stageType, stageState) {
|
||||
const oldStage = this.state.authStage;
|
||||
this.setState({
|
||||
authStage: stageType,
|
||||
errorText: error ? error.error : null,
|
||||
}, this._setFocus);
|
||||
stageState: stageState,
|
||||
errorText: stageState.error,
|
||||
}, () => {
|
||||
if (oldStage != stageType) this._setFocus();
|
||||
});
|
||||
},
|
||||
|
||||
_requestCallback: function(auth) {
|
||||
@@ -117,19 +157,35 @@ export default React.createClass({
|
||||
|
||||
_renderCurrentStage: function() {
|
||||
const stage = this.state.authStage;
|
||||
var StageComponent = getEntryComponentForLoginType(stage);
|
||||
if (!stage) return null;
|
||||
|
||||
const StageComponent = getEntryComponentForLoginType(stage);
|
||||
return (
|
||||
<StageComponent ref="stageComponent"
|
||||
loginType={stage}
|
||||
matrixClient={this.props.matrixClient}
|
||||
authSessionId={this._authLogic.getSessionId()}
|
||||
clientSecret={this._authLogic.getClientSecret()}
|
||||
stageParams={this._authLogic.getStageParams(stage)}
|
||||
submitAuthDict={this._submitAuthDict}
|
||||
errorText={this.state.stageErrorText}
|
||||
busy={this.state.busy}
|
||||
inputs={this.props.inputs}
|
||||
stageState={this.state.stageState}
|
||||
fail={this._onAuthStageFailed}
|
||||
setEmailSid={this._setEmailSid}
|
||||
makeRegistrationUrl={this.props.makeRegistrationUrl}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
_onAuthStageFailed: function(e) {
|
||||
this.props.onAuthFinished(false, e);
|
||||
},
|
||||
_setEmailSid: function(sid) {
|
||||
this._authLogic.setEmailSid(sid);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let error = null;
|
||||
if (this.state.errorText) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -65,6 +66,9 @@ module.exports = React.createClass({
|
||||
// displayname, if any, to set on the device when logging
|
||||
// in/registering.
|
||||
defaultDeviceDisplayName: React.PropTypes.string,
|
||||
|
||||
// A function that makes a registration URL
|
||||
makeRegistrationUrl: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
@@ -324,23 +328,19 @@ module.exports = React.createClass({
|
||||
Lifecycle.logout();
|
||||
break;
|
||||
case 'start_registration':
|
||||
var newState = payload.params || {};
|
||||
newState.screen = 'register';
|
||||
if (
|
||||
payload.params &&
|
||||
payload.params.client_secret &&
|
||||
payload.params.session_id &&
|
||||
payload.params.hs_url &&
|
||||
payload.params.is_url &&
|
||||
payload.params.sid
|
||||
) {
|
||||
newState.register_client_secret = payload.params.client_secret;
|
||||
newState.register_session_id = payload.params.session_id;
|
||||
newState.register_hs_url = payload.params.hs_url;
|
||||
newState.register_is_url = payload.params.is_url;
|
||||
newState.register_id_sid = payload.params.sid;
|
||||
}
|
||||
this.setStateForNewScreen(newState);
|
||||
const params = payload.params || {};
|
||||
this.setStateForNewScreen({
|
||||
screen: 'register',
|
||||
// these params may be undefined, but if they are,
|
||||
// unset them from our state: we don't want to
|
||||
// resume a previous registration session if the
|
||||
// user just clicked 'register'
|
||||
register_client_secret: params.client_secret,
|
||||
register_session_id: params.session_id,
|
||||
register_hs_url: params.hs_url,
|
||||
register_is_url: params.is_url,
|
||||
register_id_sid: params.sid,
|
||||
});
|
||||
this.notifyNewScreen('register');
|
||||
break;
|
||||
case 'start_login':
|
||||
@@ -356,13 +356,22 @@ module.exports = React.createClass({
|
||||
});
|
||||
break;
|
||||
case 'start_upgrade_registration':
|
||||
// stash our guest creds so we can backout if needed
|
||||
// also stash our credentials, then if we restore the session,
|
||||
// we can just do it the same way whether we started upgrade
|
||||
// registration or explicitly logged out
|
||||
this.guestCreds = MatrixClientPeg.getCredentials();
|
||||
this.setStateForNewScreen({
|
||||
screen: "register",
|
||||
upgradeUsername: MatrixClientPeg.get().getUserIdLocalpart(),
|
||||
guestAccessToken: MatrixClientPeg.get().getAccessToken(),
|
||||
});
|
||||
|
||||
// stop the client: if we are syncing whilst the registration
|
||||
// is completed in another browser, we'll be 401ed for using
|
||||
// a guest access token for a non-guest account.
|
||||
// It will be restarted in onReturnToGuestClick
|
||||
Lifecycle.stopMatrixClient();
|
||||
|
||||
this.notifyNewScreen('register');
|
||||
break;
|
||||
case 'start_password_recovery':
|
||||
@@ -1069,6 +1078,13 @@ module.exports = React.createClass({
|
||||
this.setState({currentRoomId: room_id});
|
||||
},
|
||||
|
||||
_makeRegistrationUrl: function(params) {
|
||||
if (this.props.startingFragmentQueryParams.referrer) {
|
||||
params.referrer = this.props.startingFragmentQueryParams.referrer;
|
||||
}
|
||||
return this.props.makeRegistrationUrl(params);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var ForgotPassword = sdk.getComponent('structures.login.ForgotPassword');
|
||||
var LoggedInView = sdk.getComponent('structures.LoggedInView');
|
||||
@@ -1132,7 +1148,7 @@ module.exports = React.createClass({
|
||||
teamServerConfig={this.props.config.teamServerConfig}
|
||||
customHsUrl={this.getCurrentHsUrl()}
|
||||
customIsUrl={this.getCurrentIsUrl()}
|
||||
registrationUrl={this.props.registrationUrl}
|
||||
makeRegistrationUrl={this._makeRegistrationUrl}
|
||||
defaultDeviceDisplayName={this.props.defaultDeviceDisplayName}
|
||||
onLoggedIn={this.onRegistered}
|
||||
onLoginClick={this.onLoginClick}
|
||||
|
||||
@@ -19,13 +19,13 @@ limitations under the License.
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var sdk = require('../../../index');
|
||||
var Signup = require("../../../Signup");
|
||||
var Login = require("../../../Login");
|
||||
var PasswordLogin = require("../../views/login/PasswordLogin");
|
||||
var CasLogin = require("../../views/login/CasLogin");
|
||||
var ServerConfig = require("../../views/login/ServerConfig");
|
||||
|
||||
/**
|
||||
* A wire component which glues together login UI components and Signup logic
|
||||
* A wire component which glues together login UI components and Login logic
|
||||
*/
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Login',
|
||||
@@ -146,7 +146,7 @@ module.exports = React.createClass({
|
||||
|
||||
var fallbackHsUrl = hsUrl == this.props.defaultHsUrl ? this.props.fallbackHsUrl : null;
|
||||
|
||||
var loginLogic = new Signup.Login(hsUrl, isUrl, fallbackHsUrl, {
|
||||
var loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
|
||||
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
|
||||
});
|
||||
this._loginLogic = loginLogic;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,10 +15,9 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import Matrix from 'matrix-js-sdk';
|
||||
|
||||
import q from 'q';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import sdk from '../../../index';
|
||||
@@ -31,10 +31,6 @@ import RtsClient from '../../../RtsClient';
|
||||
|
||||
const MIN_PASSWORD_LENGTH = 6;
|
||||
|
||||
/**
|
||||
* TODO: It would be nice to make use of the InteractiveAuthEntryComponents
|
||||
* here, rather than inventing our own.
|
||||
*/
|
||||
module.exports = React.createClass({
|
||||
displayName: 'Registration',
|
||||
|
||||
@@ -42,7 +38,7 @@ module.exports = React.createClass({
|
||||
onLoggedIn: React.PropTypes.func.isRequired,
|
||||
clientSecret: React.PropTypes.string,
|
||||
sessionId: React.PropTypes.string,
|
||||
registrationUrl: React.PropTypes.string,
|
||||
makeRegistrationUrl: React.PropTypes.func.isRequired,
|
||||
idSid: React.PropTypes.string,
|
||||
customHsUrl: React.PropTypes.string,
|
||||
customIsUrl: React.PropTypes.string,
|
||||
@@ -83,27 +79,20 @@ module.exports = React.createClass({
|
||||
formVals: {
|
||||
email: this.props.email,
|
||||
},
|
||||
// true if we're waiting for the user to complete
|
||||
// user-interactive auth
|
||||
// If we've been given a session ID, we're resuming
|
||||
// straight back into UI auth
|
||||
doingUIAuth: Boolean(this.props.sessionId),
|
||||
hsUrl: this.props.customHsUrl,
|
||||
isUrl: this.props.customIsUrl,
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
// attach this to the instance rather than this.state since it isn't UI
|
||||
this.registerLogic = new Signup.Register(
|
||||
this.props.customHsUrl, this.props.customIsUrl, {
|
||||
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
|
||||
}
|
||||
);
|
||||
this.registerLogic.setClientSecret(this.props.clientSecret);
|
||||
this.registerLogic.setSessionId(this.props.sessionId);
|
||||
this.registerLogic.setRegistrationUrl(this.props.registrationUrl);
|
||||
this.registerLogic.setIdSid(this.props.idSid);
|
||||
this.registerLogic.setGuestAccessToken(this.props.guestAccessToken);
|
||||
if (this.props.referrer) {
|
||||
this.registerLogic.setReferrer(this.props.referrer);
|
||||
}
|
||||
this.registerLogic.recheckState();
|
||||
|
||||
this._replaceClient();
|
||||
|
||||
if (
|
||||
this.props.teamServerConfig &&
|
||||
@@ -135,154 +124,124 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
dis.unregister(this.dispatcherRef);
|
||||
this._unmounted = true;
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// may have already done an HTTP hit (e.g. redirect from an email) so
|
||||
// check for any pending response
|
||||
var promise = this.registerLogic.getPromise();
|
||||
if (promise) {
|
||||
this.onProcessingRegistration(promise);
|
||||
}
|
||||
},
|
||||
|
||||
onHsUrlChanged: function(newHsUrl) {
|
||||
this.registerLogic.setHomeserverUrl(newHsUrl);
|
||||
this.setState({
|
||||
hsUrl: newHsUrl,
|
||||
});
|
||||
this._replaceClient();
|
||||
},
|
||||
|
||||
onIsUrlChanged: function(newIsUrl) {
|
||||
this.registerLogic.setIdentityServerUrl(newIsUrl);
|
||||
this.setState({
|
||||
isUrl: newIsUrl,
|
||||
});
|
||||
this._replaceClient();
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
if (payload.action !== "registration_step_update") {
|
||||
return;
|
||||
}
|
||||
// If the registration state has changed, this means the
|
||||
// user now needs to do something. It would be better
|
||||
// to expose the explicitly in the register logic.
|
||||
this.setState({
|
||||
busy: false
|
||||
_replaceClient: function() {
|
||||
this._matrixClient = Matrix.createClient({
|
||||
baseUrl: this.state.hsUrl,
|
||||
idBaseUrl: this.state.isUrl,
|
||||
});
|
||||
},
|
||||
|
||||
onFormSubmit: function(formVals) {
|
||||
var self = this;
|
||||
this.setState({
|
||||
errorText: "",
|
||||
busy: true,
|
||||
formVals: formVals,
|
||||
doingUIAuth: true,
|
||||
});
|
||||
|
||||
if (formVals.username !== this.props.username) {
|
||||
// don't try to upgrade if we changed our username
|
||||
this.registerLogic.setGuestAccessToken(null);
|
||||
}
|
||||
|
||||
this.onProcessingRegistration(this.registerLogic.register(formVals));
|
||||
},
|
||||
|
||||
// Promise is resolved when the registration process is FULLY COMPLETE
|
||||
onProcessingRegistration: function(promise) {
|
||||
var self = this;
|
||||
promise.done(function(response) {
|
||||
self.setState({
|
||||
busy: false
|
||||
_onUIAuthFinished: function(success, response) {
|
||||
if (!success) {
|
||||
this.setState({
|
||||
busy: false,
|
||||
doingUIAuth: false,
|
||||
errorText: response.message || response.toString(),
|
||||
});
|
||||
if (!response || !response.access_token) {
|
||||
console.warn(
|
||||
"FIXME: Register fulfilled without a final response, " +
|
||||
"did you break the promise chain?"
|
||||
);
|
||||
// no matter, we'll grab it direct
|
||||
response = self.registerLogic.getCredentials();
|
||||
}
|
||||
if (!response || !response.user_id || !response.access_token) {
|
||||
console.error("Final response is missing keys.");
|
||||
self.setState({
|
||||
errorText: "Registration failed on server"
|
||||
});
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Done regardless of `teamSelected`. People registering with non-team emails
|
||||
// will just nop. The point of this being we might not have the email address
|
||||
// that the user registered with at this stage (depending on whether this
|
||||
// is the client they initiated registration).
|
||||
let trackPromise = q(null);
|
||||
if (self._rtsClient) {
|
||||
// Track referral if self.props.referrer set, get team_token in order to
|
||||
// retrieve team config and see welcome page etc.
|
||||
trackPromise = self._rtsClient.trackReferral(
|
||||
self.props.referrer || '', // Default to empty string = not referred
|
||||
self.registerLogic.params.idSid,
|
||||
self.registerLogic.params.clientSecret
|
||||
).then((data) => {
|
||||
const teamToken = data.team_token;
|
||||
// Store for use /w welcome pages
|
||||
window.localStorage.setItem('mx_team_token', teamToken);
|
||||
|
||||
self._rtsClient.getTeam(teamToken).then((team) => {
|
||||
console.log(
|
||||
`User successfully registered with team ${team.name}`
|
||||
);
|
||||
if (!team.rooms) {
|
||||
return;
|
||||
}
|
||||
// Auto-join rooms
|
||||
team.rooms.forEach((room) => {
|
||||
if (room.auto_join && room.room_id) {
|
||||
console.log(`Auto-joining ${room.room_id}`);
|
||||
MatrixClientPeg.get().joinRoom(room.room_id);
|
||||
}
|
||||
});
|
||||
}, (err) => {
|
||||
console.error('Error getting team config', err);
|
||||
});
|
||||
|
||||
return teamToken;
|
||||
}, (err) => {
|
||||
console.error('Error tracking referral', err);
|
||||
});
|
||||
}
|
||||
|
||||
return trackPromise.then((teamToken) => {
|
||||
console.info('Team token promise',teamToken);
|
||||
self.props.onLoggedIn({
|
||||
userId: response.user_id,
|
||||
deviceId: response.device_id,
|
||||
homeserverUrl: self.registerLogic.getHomeserverUrl(),
|
||||
identityServerUrl: self.registerLogic.getIdentityServerUrl(),
|
||||
accessToken: response.access_token
|
||||
}, teamToken);
|
||||
}).then(() => {
|
||||
self._setupPushers();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err.message) {
|
||||
self.setState({
|
||||
errorText: err.message
|
||||
});
|
||||
}
|
||||
self.setState({
|
||||
busy: false
|
||||
});
|
||||
console.log(err);
|
||||
this.setState({
|
||||
// we're still busy until we get unmounted: don't show the registration form again
|
||||
busy: true,
|
||||
doingUIAuth: false,
|
||||
});
|
||||
this.props.onLoggedIn({
|
||||
userId: response.user_id,
|
||||
deviceId: response.device_id,
|
||||
homeserverUrl: this.state.hsUrl,
|
||||
identityServerUrl: this.state.isUrl,
|
||||
accessToken: response.access_token,
|
||||
});
|
||||
|
||||
// Done regardless of `teamSelected`. People registering with non-team emails
|
||||
// will just nop. The point of this being we might not have the email address
|
||||
// that the user registered with at this stage (depending on whether this
|
||||
// is the client they initiated registration).
|
||||
let trackPromise = q(null);
|
||||
if (this._rtsClient) {
|
||||
// Track referral if this.props.referrer set, get team_token in order to
|
||||
// retrieve team config and see welcome page etc.
|
||||
trackPromise = this._rtsClient.trackReferral(
|
||||
this.props.referrer || '', // Default to empty string = not referred
|
||||
this.registerLogic.params.idSid,
|
||||
this.registerLogic.params.clientSecret
|
||||
).then((data) => {
|
||||
const teamToken = data.team_token;
|
||||
// Store for use /w welcome pages
|
||||
window.localStorage.setItem('mx_team_token', teamToken);
|
||||
this.props.onTeamMemberRegistered(teamToken);
|
||||
|
||||
this._rtsClient.getTeam(teamToken).then((team) => {
|
||||
console.log(
|
||||
`User successfully registered with team ${team.name}`
|
||||
);
|
||||
if (!team.rooms) {
|
||||
return;
|
||||
}
|
||||
// Auto-join rooms
|
||||
team.rooms.forEach((room) => {
|
||||
if (room.auto_join && room.room_id) {
|
||||
console.log(`Auto-joining ${room.room_id}`);
|
||||
MatrixClientPeg.get().joinRoom(room.room_id);
|
||||
}
|
||||
});
|
||||
}, (err) => {
|
||||
console.error('Error getting team config', err);
|
||||
});
|
||||
|
||||
return teamToken;
|
||||
}, (err) => {
|
||||
console.error('Error tracking referral', err);
|
||||
});
|
||||
}
|
||||
|
||||
trackPromise.then((teamToken) => {
|
||||
console.info('Team token promise',teamToken);
|
||||
this.props.onLoggedIn({
|
||||
userId: response.user_id,
|
||||
deviceId: response.device_id,
|
||||
homeserverUrl: this.registerLogic.getHomeserverUrl(),
|
||||
identityServerUrl: this.registerLogic.getIdentityServerUrl(),
|
||||
accessToken: response.access_token
|
||||
}, teamToken);
|
||||
}).then(() => {
|
||||
return this._setupPushers();
|
||||
}).done();
|
||||
},
|
||||
|
||||
_setupPushers: function() {
|
||||
if (!this.props.brand) {
|
||||
return;
|
||||
return q();
|
||||
}
|
||||
MatrixClientPeg.get().getPushers().done((resp)=>{
|
||||
var pushers = resp.pushers;
|
||||
for (var i = 0; i < pushers.length; ++i) {
|
||||
return MatrixClientPeg.get().getPushers().then((resp)=>{
|
||||
const pushers = resp.pushers;
|
||||
for (let i = 0; i < pushers.length; ++i) {
|
||||
if (pushers[i].kind == 'email') {
|
||||
var emailPusher = pushers[i];
|
||||
const emailPusher = pushers[i];
|
||||
emailPusher.data = { brand: this.props.brand };
|
||||
MatrixClientPeg.get().setPusher(emailPusher).done(() => {
|
||||
console.log("Set email branding to " + this.props.brand);
|
||||
@@ -327,116 +286,114 @@ module.exports = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
onCaptchaResponse: function(response) {
|
||||
this.registerLogic.tellStage("m.login.recaptcha", {
|
||||
response: response
|
||||
});
|
||||
},
|
||||
|
||||
onTeamSelected: function(teamSelected) {
|
||||
if (!this._unmounted) {
|
||||
this.setState({ teamSelected });
|
||||
}
|
||||
},
|
||||
|
||||
_getRegisterContentJsx: function() {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
_makeRegisterRequest: function(auth) {
|
||||
let guestAccessToken = this.props.guestAccessToken;
|
||||
|
||||
var currStep = this.registerLogic.getStep();
|
||||
var registerStep;
|
||||
switch (currStep) {
|
||||
case "Register.COMPLETE":
|
||||
break; // NOP
|
||||
case "Register.START":
|
||||
case "Register.STEP_m.login.dummy":
|
||||
// NB. Our 'username' prop is specifically for upgrading
|
||||
// a guest account
|
||||
if (this.state.teamServerBusy) {
|
||||
registerStep = <Spinner />;
|
||||
break;
|
||||
}
|
||||
registerStep = (
|
||||
if (
|
||||
this.state.formVals.username !== this.props.username ||
|
||||
this.state.hsUrl != this.props.defaultHsUrl
|
||||
) {
|
||||
// don't try to upgrade if we changed our username
|
||||
// or are registering on a different HS
|
||||
guestAccessToken = null;
|
||||
}
|
||||
|
||||
return this._matrixClient.register(
|
||||
this.state.formVals.username,
|
||||
this.state.formVals.password,
|
||||
undefined, // session id: included in the auth dict already
|
||||
auth,
|
||||
// Only send the bind_email param if we're sending username / pw params
|
||||
// (Since we need to send no params at all to use the ones saved in the
|
||||
// session).
|
||||
Boolean(this.state.formVals.username) || undefined,
|
||||
guestAccessToken,
|
||||
);
|
||||
},
|
||||
|
||||
_getUIAuthInputs() {
|
||||
return {
|
||||
emailAddress: this.state.formVals.email,
|
||||
phoneCountry: this.state.formVals.phoneCountry,
|
||||
phoneNumber: this.state.formVals.phoneNumber,
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const LoginHeader = sdk.getComponent('login.LoginHeader');
|
||||
const LoginFooter = sdk.getComponent('login.LoginFooter');
|
||||
const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth');
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
const ServerConfig = sdk.getComponent('views.login.ServerConfig');
|
||||
|
||||
let registerBody;
|
||||
if (this.state.doingUIAuth) {
|
||||
registerBody = (
|
||||
<InteractiveAuth
|
||||
matrixClient={this._matrixClient}
|
||||
makeRequest={this._makeRegisterRequest}
|
||||
onAuthFinished={this._onUIAuthFinished}
|
||||
inputs={this._getUIAuthInputs()}
|
||||
makeRegistrationUrl={this.props.makeRegistrationUrl}
|
||||
sessionId={this.props.sessionId}
|
||||
clientSecret={this.props.clientSecret}
|
||||
emailSid={this.props.idSid}
|
||||
poll={true}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.busy || this.state.teamServerBusy) {
|
||||
registerBody = <Spinner />;
|
||||
} else {
|
||||
let guestUsername = this.props.username;
|
||||
if (this.state.hsUrl != this.props.defaultHsUrl) {
|
||||
guestUsername = null;
|
||||
}
|
||||
let errorSection;
|
||||
if (this.state.errorText) {
|
||||
errorSection = <div className="mx_Login_error">{this.state.errorText}</div>;
|
||||
}
|
||||
registerBody = (
|
||||
<div>
|
||||
<RegistrationForm
|
||||
showEmail={true}
|
||||
defaultUsername={this.state.formVals.username}
|
||||
defaultEmail={this.state.formVals.email}
|
||||
defaultPassword={this.state.formVals.password}
|
||||
teamsConfig={this.state.teamsConfig}
|
||||
guestUsername={this.props.username}
|
||||
guestUsername={guestUsername}
|
||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||
onError={this.onFormValidationFailed}
|
||||
onRegisterClick={this.onFormSubmit}
|
||||
onTeamSelected={this.onTeamSelected}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "Register.STEP_m.login.email.identity":
|
||||
registerStep = (
|
||||
<div>
|
||||
Please check your email to continue registration.
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case "Register.STEP_m.login.recaptcha":
|
||||
var publicKey;
|
||||
var serverParams = this.registerLogic.getServerData().params;
|
||||
if (serverParams && serverParams["m.login.recaptcha"]) {
|
||||
publicKey = serverParams["m.login.recaptcha"].public_key;
|
||||
}
|
||||
|
||||
registerStep = (
|
||||
<CaptchaForm sitePublicKey={publicKey}
|
||||
onCaptchaResponse={this.onCaptchaResponse}
|
||||
{errorSection}
|
||||
<ServerConfig ref="serverConfig"
|
||||
withToggleButton={true}
|
||||
customHsUrl={this.props.customHsUrl}
|
||||
customIsUrl={this.props.customIsUrl}
|
||||
defaultHsUrl={this.props.defaultHsUrl}
|
||||
defaultIsUrl={this.props.defaultIsUrl}
|
||||
onHsUrlChanged={this.onHsUrlChanged}
|
||||
onIsUrlChanged={this.onIsUrlChanged}
|
||||
delayTimeMs={1000}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown register state: %s", currStep);
|
||||
break;
|
||||
}
|
||||
var busySpinner;
|
||||
if (this.state.busy) {
|
||||
busySpinner = (
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var returnToAppJsx;
|
||||
let returnToAppJsx;
|
||||
if (this.props.onCancelClick) {
|
||||
returnToAppJsx =
|
||||
returnToAppJsx = (
|
||||
<a className="mx_Login_create" onClick={this.props.onCancelClick} href="#">
|
||||
Return to app
|
||||
</a>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Create an account</h2>
|
||||
{registerStep}
|
||||
<div className="mx_Login_error">{this.state.errorText}</div>
|
||||
{busySpinner}
|
||||
<ServerConfig ref="serverConfig"
|
||||
withToggleButton={ this.registerLogic.getStep() === "Register.START" }
|
||||
customHsUrl={this.props.customHsUrl}
|
||||
customIsUrl={this.props.customIsUrl}
|
||||
defaultHsUrl={this.props.defaultHsUrl}
|
||||
defaultIsUrl={this.props.defaultIsUrl}
|
||||
onHsUrlChanged={this.onHsUrlChanged}
|
||||
onIsUrlChanged={this.onIsUrlChanged}
|
||||
delayTimeMs={1000} />
|
||||
<div className="mx_Login_error">
|
||||
</div>
|
||||
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
|
||||
I already have an account
|
||||
</a>
|
||||
{ returnToAppJsx }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var LoginHeader = sdk.getComponent('login.LoginHeader');
|
||||
var LoginFooter = sdk.getComponent('login.LoginFooter');
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="mx_Login">
|
||||
<div className="mx_Login_box">
|
||||
@@ -446,7 +403,12 @@ module.exports = React.createClass({
|
||||
this.state.teamSelected.domain + "/icon.png" :
|
||||
null}
|
||||
/>
|
||||
{this._getRegisterContentJsx()}
|
||||
<h2>Create an account</h2>
|
||||
{registerBody}
|
||||
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
|
||||
I already have an account
|
||||
</a>
|
||||
{returnToAppJsx}
|
||||
<LoginFooter />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user