Start of registration support.

This commit is contained in:
David Baker 2015-07-13 19:14:02 +01:00
parent 98baa0cb0a
commit a7e4a2847e
7 changed files with 267 additions and 4 deletions

View File

@ -23,6 +23,7 @@ var RoomList = ComponentBroker.get('organisms/RoomList');
var RoomView = ComponentBroker.get('organisms/RoomView'); var RoomView = ComponentBroker.get('organisms/RoomView');
var MatrixToolbar = ComponentBroker.get('molecules/MatrixToolbar'); var MatrixToolbar = ComponentBroker.get('molecules/MatrixToolbar');
var Login = ComponentBroker.get('templates/Login'); var Login = ComponentBroker.get('templates/Login');
var Register = ComponentBroker.get('templates/Register');
var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat"); var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat");
@ -51,6 +52,10 @@ module.exports = React.createClass({
return ( return (
<Loader /> <Loader />
); );
} else if (this.state.screen == 'register') {
return (
<Register onLoggedIn={this.onLoggedIn} />
);
} else { } else {
return ( return (
<Login onLoggedIn={this.onLoggedIn} /> <Login onLoggedIn={this.onLoggedIn} />

View File

@ -40,6 +40,7 @@ module.exports = React.createClass({
<h1>Please log in:</h1> <h1>Please log in:</h1>
{this.componentForStep(this.state.step)} {this.componentForStep(this.state.step)}
<div className="error">{this.state.errorText}</div> <div className="error">{this.state.errorText}</div>
<a onClick={this.showRegister} href="#">Create a new account</a>
</div> </div>
); );
} }

View File

@ -0,0 +1,55 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
var React = require('react');
var ComponentBroker = require("../../../../src/ComponentBroker");
var Loader = require("react-loader");
var RegisterController = require("../../../../src/controllers/templates/Register");
module.exports = React.createClass({
displayName: 'Register',
mixins: [RegisterController],
registerContent: function() {
if (this.state.busy) {
return (
<Loader />
);
} else {
return (
<div>
<h1>Create a new account:</h1>
{this.componentForStep(this.state.step)}
<div className="error">{this.state.errorText}</div>
<a onClick={this.showLogin} href="#">Sign in with existing account</a>
</div>
);
}
},
render: function() {
return (
<div className="mx_Register">
{this.registerContent()}
</div>
);
}
});

View File

@ -81,5 +81,6 @@ require('../skins/base/views/molecules/MemberTile');
require('../skins/base/views/organisms/RoomList'); require('../skins/base/views/organisms/RoomList');
require('../skins/base/views/organisms/RoomView'); require('../skins/base/views/organisms/RoomView');
require('../skins/base/views/templates/Login'); require('../skins/base/views/templates/Login');
require('../skins/base/views/templates/Register');
require('../skins/base/views/organisms/Notifier'); require('../skins/base/views/organisms/Notifier');
} }

View File

@ -67,10 +67,25 @@ module.exports = {
logged_in: false, logged_in: false,
ready: false ready: false
}); });
localStorage.removeItem("mx_hs_url");
localStorage.removeItem("mx_user_id");
localStorage.removeItem("mx_access_token");
Notifier.stop(); Notifier.stop();
MatrixClientPeg.get().removeAllListeners(); MatrixClientPeg.get().removeAllListeners();
MatrixClientPeg.replace(null); MatrixClientPeg.replace(null);
break; break;
case 'start_registration':
if (this.state.logged_in) return;
this.setState({
screen: 'register'
});
break;
case 'start_login':
if (this.state.logged_in) return;
this.setState({
screen: 'login'
});
break;
case 'view_room': case 'view_room':
this.focusComposer = true; this.focusComposer = true;
this.setState({ this.setState({
@ -99,7 +114,10 @@ module.exports = {
}, },
onLoggedIn: function() { onLoggedIn: function() {
this.setState({logged_in: true}); this.setState({
screen: 'register',
logged_in: true
});
this.startMatrixClient(); this.startMatrixClient();
}, },

View File

@ -20,6 +20,7 @@ var React = require('react');
var MatrixClientPeg = require("../../MatrixClientPeg"); var MatrixClientPeg = require("../../MatrixClientPeg");
var Matrix = require("matrix-js-sdk"); var Matrix = require("matrix-js-sdk");
var dis = require("../../dispatcher");
var ComponentBroker = require("../../ComponentBroker"); var ComponentBroker = require("../../ComponentBroker");
@ -85,9 +86,6 @@ module.exports = {
if (that.props.onLoggedIn) { if (that.props.onLoggedIn) {
that.props.onLoggedIn(); that.props.onLoggedIn();
} }
/*dis.dispatch({
'action': 'logged_in'
});*/
}, function(error) { }, function(error) {
that.setStep("stage_m.login.password"); that.setStep("stage_m.login.password");
that.setState({errorText: 'Login failed.'}); that.setState({errorText: 'Login failed.'});
@ -118,4 +116,10 @@ module.exports = {
); );
} }
}, },
showRegister: function() {
dis.dispatch({
action: 'start_registration'
});
}
}; };

View File

@ -0,0 +1,179 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
var React = require('react');
var MatrixClientPeg = require("../../MatrixClientPeg");
var Matrix = require("matrix-js-sdk");
var dis = require("../../dispatcher");
var ComponentBroker = require("../../ComponentBroker");
var ServerConfig = ComponentBroker.get("molecules/ServerConfig");
module.exports = {
getInitialState: function() {
return {
step: 'initial',
busy: false,
currentStep: 0,
totalSteps: 1
};
},
setStep: function(step) {
this.setState({ step: step, errorText: '', busy: false });
},
getSupportedStageTypes: function() {
return ['m.login.email.identity', 'm.login.recaptcha'];
},
chooseFlow: function(flows) {
// this is fairly simple right now
var supportedTypes = this.getSupportedStageTypes();
var emailFlow = null;
var otherFlow = null;
for (var flowI = 0; flowI < flows.length; ++flowI) {
var flow = flows[flowI];
var flowHasEmail = false;
var flowSupported = true;
for (var stageI = 0; stageI < flow.stages.length; ++stageI) {
var stage = flow.stages[stageI];
if (supportedTypes.indexOf(stage) == -1) {
flowSupported = false;
}
if (stage == 'm.login.email.identity') {
flowHasEmail = true;
}
}
if (flowSupported) {
if (flowHasEmail) {
emailFlow = flow;
} else {
otherFlow = flow;
}
}
}
if (this.savedParams.email != '') {
return emailFlow;
} else {
return otherFlow;
}
},
onInitialStageSubmit: function(ev) {
ev.preventDefault();
MatrixClientPeg.replaceUsingUrl(this.refs.serverConfig.getHsUrl());
this.setState({hs_url: this.refs.serverConfig.getHsUrl()});
var cli = MatrixClientPeg.get();
this.setState({busy: true});
var self = this;
var email = this.refs.email.getDOMNode().value;
var username = this.refs.username.getDOMNode().value;
var password = this.refs.password.getDOMNode().value;
this.savedParams = {
email: email,
username: username,
password: password
};
cli.register(username, password).done(function(result) {
self.onRegistered();
}, function(error) {
if (error.httpStatus == 401) {
var flow = self.chooseFlow(error.data.flows);
self.setState({
busy: false,
flows: flow,
currentStep: 1,
totalSteps: flow.stages.length+1,
flowStage: 0
});
self.setStep('stage_'+flow.stages[0]);
} else {
self.setStep("initial");
self.setState({
busy: false,
errorText: 'Unable to contact the given Home Server'
});
}
});
},
onRegistered: function(user_id, access_token) {
MatrixClientPeg.replace(Matrix.createClient({
baseUrl: this.state.hs_url,
userId: data.user_id,
accessToken: data.access_token
}));
var localStorage = window.localStorage;
if (localStorage) {
localStorage.setItem("mx_hs_url", this.state.hs_url);
localStorage.setItem("mx_user_id", user_id);
localStorage.setItem("mx_access_token", access_token);
} else {
console.warn("No local storage available: can't persist session!");
}
if (that.props.onLoggedIn) {
that.props.onLoggedIn();
}
},
componentForStep: function(step) {
switch (step) {
case 'initial':
return (
<div>
<form onSubmit={this.onInitialStageSubmit}>
Email: <input ref="email" /><br />
Username: <input ref="username" /><br />
Password: <input ref="password" /><br />
<ServerConfig ref="serverConfig" />
<input type="submit" value="Continue" />
</form>
</div>
);
// XXX: clearly these should be separate organisms
case 'stage_m.login.email.identity':
return (
<div>
Please check your email to continue registration.
</div>
);
case 'stage_m.login.recaptcha':
return (
<div>
This is the recaptcha stage. Sucks, doesn't it.
</div>
);
}
},
showLogin: function() {
dis.dispatch({
action: 'start_login'
});
}
};