diff --git a/src/SignupStages.js b/src/SignupStages.js
index 2b0d163a08..72e789e6a6 100644
--- a/src/SignupStages.js
+++ b/src/SignupStages.js
@@ -53,66 +53,24 @@ class RecaptchaStage extends Stage {
constructor(matrixClient, signupInstance) {
super(RecaptchaStage.TYPE, matrixClient, signupInstance);
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
so we can
- // render to it.
+ // called when the recaptcha has been completed.
onReceiveData(data) {
- if (!data || !data.divId) {
+ if (!data || !data.response) {
return;
}
- this.divId = data.divId;
- this._attemptRender();
+ this.defer.resolve({
+ auth: {
+ type: 'm.login.recaptcha',
+ response: data.response,
+ }
+ });
}
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;
}
-
- _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";
diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js
index 0f1b6d331f..6d25efef6c 100644
--- a/src/components/structures/login/Registration.js
+++ b/src/components/structures/login/Registration.js
@@ -228,12 +228,9 @@ module.exports = React.createClass({
});
},
- onCaptchaLoaded: function(divIdName) {
+ onCaptchaResponse: function(response) {
this.registerLogic.tellStage("m.login.recaptcha", {
- divId: divIdName
- });
- this.setState({
- busy: false // requires user input
+ response: response
});
},
@@ -267,8 +264,15 @@ module.exports = React.createClass({
);
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 = (
-
+
);
break;
default:
diff --git a/src/components/views/login/CaptchaForm.js b/src/components/views/login/CaptchaForm.js
index fdbe6f1db1..0e5922f464 100644
--- a/src/components/views/login/CaptchaForm.js
+++ b/src/components/views/login/CaptchaForm.js
@@ -26,28 +26,34 @@ module.exports = React.createClass({
displayName: 'CaptchaForm',
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() {
return {
- onCaptchaLoaded: function() {
- console.error("Unhandled onCaptchaLoaded");
- }
+ onCaptchaResponse: () => {},
+ };
+ },
+
+ getInitialState: function() {
+ return {
+ errorText: null,
};
},
componentDidMount: function() {
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
// so we do this instead.
- var self = this;
- if (this.refs.recaptchaContainer) {
+ if (global.grecaptcha) {
+ // already loaded
+ this._onCaptchaLoaded();
+ } else {
console.log("Loading recaptcha script...");
var scriptTag = document.createElement('script');
- window.mx_on_recaptcha_loaded = function() {
- console.log("Loaded recaptcha script.");
- self.props.onCaptchaLoaded(DIV_ID);
- };
+ window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded()};
scriptTag.setAttribute(
'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() {
- // FIXME: Tight coupling with the div id and SignupStages.js
+ let error = null;
+ if (this.state.errorText) {
+ error = (
+
+ {this.state.errorText}
+
+ );
+ }
+
return (
This Home Server would like to make sure you are not a robot
+ {error}
);
}
-});
\ No newline at end of file
+});