Refactor CaptchaForm to put less logic in signupstages
A bunch of work being done in the Recaptcha signupstage makes more sense in the CaptchaForm; let's move it.
This commit is contained in:
parent
6ffddabaaa
commit
eb36509620
3 changed files with 77 additions and 68 deletions
|
@ -53,66 +53,24 @@ class RecaptchaStage extends Stage {
|
||||||
constructor(matrixClient, signupInstance) {
|
constructor(matrixClient, signupInstance) {
|
||||||
super(RecaptchaStage.TYPE, matrixClient, signupInstance);
|
super(RecaptchaStage.TYPE, matrixClient, signupInstance);
|
||||||
this.defer = q.defer(); // resolved with the captcha response
|
this.defer = q.defer(); // resolved with the captcha response
|
||||||
this.publicKey = null; // from the HS
|
|
||||||
this.divId = null; // from the UI component
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// called when the UI component has loaded the recaptcha <div> so we can
|
// called when the recaptcha has been completed.
|
||||||
// render to it.
|
|
||||||
onReceiveData(data) {
|
onReceiveData(data) {
|
||||||
if (!data || !data.divId) {
|
if (!data || !data.response) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.divId = data.divId;
|
this.defer.resolve({
|
||||||
this._attemptRender();
|
auth: {
|
||||||
|
type: 'm.login.recaptcha',
|
||||||
|
response: data.response,
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
complete() {
|
complete() {
|
||||||
var publicKey;
|
|
||||||
var serverParams = this.signupInstance.getServerData().params;
|
|
||||||
if (serverParams && serverParams["m.login.recaptcha"]) {
|
|
||||||
publicKey = serverParams["m.login.recaptcha"].public_key;
|
|
||||||
}
|
|
||||||
if (!publicKey) {
|
|
||||||
return q.reject({
|
|
||||||
message: "This server has not supplied enough information for Recaptcha " +
|
|
||||||
"authentication",
|
|
||||||
isFatal: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.publicKey = publicKey;
|
|
||||||
this._attemptRender();
|
|
||||||
return this.defer.promise;
|
return this.defer.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
_attemptRender() {
|
|
||||||
if (!global.grecaptcha) {
|
|
||||||
console.error("grecaptcha not loaded!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.publicKey) {
|
|
||||||
console.error("No public key for recaptcha!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.divId) {
|
|
||||||
console.error("No div ID specified!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("Rendering to %s", this.divId);
|
|
||||||
var self = this;
|
|
||||||
global.grecaptcha.render(this.divId, {
|
|
||||||
sitekey: this.publicKey,
|
|
||||||
callback: function(response) {
|
|
||||||
console.log("Received captcha response");
|
|
||||||
self.defer.resolve({
|
|
||||||
auth: {
|
|
||||||
type: 'm.login.recaptcha',
|
|
||||||
response: response
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RecaptchaStage.TYPE = "m.login.recaptcha";
|
RecaptchaStage.TYPE = "m.login.recaptcha";
|
||||||
|
|
||||||
|
|
|
@ -228,12 +228,9 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onCaptchaLoaded: function(divIdName) {
|
onCaptchaResponse: function(response) {
|
||||||
this.registerLogic.tellStage("m.login.recaptcha", {
|
this.registerLogic.tellStage("m.login.recaptcha", {
|
||||||
divId: divIdName
|
response: response
|
||||||
});
|
|
||||||
this.setState({
|
|
||||||
busy: false // requires user input
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -267,8 +264,15 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Register.STEP_m.login.recaptcha":
|
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 = (
|
registerStep = (
|
||||||
<CaptchaForm onCaptchaLoaded={this.onCaptchaLoaded} />
|
<CaptchaForm sitePublicKey={publicKey}
|
||||||
|
onCaptchaResponse={this.onCaptchaResponse}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -26,28 +26,34 @@ module.exports = React.createClass({
|
||||||
displayName: 'CaptchaForm',
|
displayName: 'CaptchaForm',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onCaptchaLoaded: React.PropTypes.func.isRequired // called with div id name
|
sitePublicKey: React.PropTypes.string,
|
||||||
|
|
||||||
|
// called with the captcha response
|
||||||
|
onCaptchaResponse: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
onCaptchaLoaded: function() {
|
onCaptchaResponse: () => {},
|
||||||
console.error("Unhandled onCaptchaLoaded");
|
};
|
||||||
}
|
},
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
errorText: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
|
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
|
||||||
// so we do this instead.
|
// so we do this instead.
|
||||||
var self = this;
|
if (global.grecaptcha) {
|
||||||
if (this.refs.recaptchaContainer) {
|
// already loaded
|
||||||
|
this._onCaptchaLoaded();
|
||||||
|
} else {
|
||||||
console.log("Loading recaptcha script...");
|
console.log("Loading recaptcha script...");
|
||||||
var scriptTag = document.createElement('script');
|
var scriptTag = document.createElement('script');
|
||||||
window.mx_on_recaptcha_loaded = function() {
|
window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded()};
|
||||||
console.log("Loaded recaptcha script.");
|
|
||||||
self.props.onCaptchaLoaded(DIV_ID);
|
|
||||||
};
|
|
||||||
scriptTag.setAttribute(
|
scriptTag.setAttribute(
|
||||||
'src', global.location.protocol+"//www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit"
|
'src', global.location.protocol+"//www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit"
|
||||||
);
|
);
|
||||||
|
@ -55,13 +61,54 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_renderRecaptcha: function(divId) {
|
||||||
|
if (!global.grecaptcha) {
|
||||||
|
console.error("grecaptcha not loaded!");
|
||||||
|
throw new Error("Recaptcha did not load successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
var publicKey = this.props.sitePublicKey;
|
||||||
|
if (!publicKey) {
|
||||||
|
console.error("No public key for recaptcha!");
|
||||||
|
throw new Error(
|
||||||
|
"This server has not supplied enough information for Recaptcha "
|
||||||
|
+ "authentication");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Rendering to %s", divId);
|
||||||
|
global.grecaptcha.render(divId, {
|
||||||
|
sitekey: publicKey,
|
||||||
|
callback: this.props.onCaptchaResponse,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_onCaptchaLoaded: function() {
|
||||||
|
console.log("Loaded recaptcha script.");
|
||||||
|
try {
|
||||||
|
this._renderRecaptcha(DIV_ID);
|
||||||
|
} catch (e) {
|
||||||
|
this.setState({
|
||||||
|
errorText: e.toString(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
// FIXME: Tight coupling with the div id and SignupStages.js
|
let error = null;
|
||||||
|
if (this.state.errorText) {
|
||||||
|
error = (
|
||||||
|
<div className="error">
|
||||||
|
{this.state.errorText}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref="recaptchaContainer">
|
<div ref="recaptchaContainer">
|
||||||
This Home Server would like to make sure you are not a robot
|
This Home Server would like to make sure you are not a robot
|
||||||
<div id={DIV_ID}></div>
|
<div id={DIV_ID}></div>
|
||||||
|
{error}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue