Get Recaptcha working again. Add a backchannel for stage prodding.

Recaptcha is a special snowflake because it dynamically loads the script
and THEN renders with info from the registration request. This means we
need a back-channel for the UI component to 'tell' the stage that everything
is loaded. This Just Works which is nice.
This commit is contained in:
Kegan Dougal 2015-11-18 17:43:38 +00:00
parent 991a96cfc5
commit 3e903be73d
2 changed files with 48 additions and 8 deletions

View file

@ -38,8 +38,9 @@ class Register extends Signup {
this.username = null; // desired this.username = null; // desired
this.email = null; // desired this.email = null; // desired
this.password = null; // desired this.password = null; // desired
this.params = {}; // random other stuff (e.g. query params) this.params = {}; // random other stuff (e.g. query params, NOT params from the server)
this.credentials = null; this.credentials = null;
this.activeStage = null;
} }
setClientSecret(secret) { setClientSecret(secret) {
@ -66,6 +67,10 @@ class Register extends Signup {
return this.credentials; return this.credentials;
} }
getServerData() {
return this.data || {};
}
setStep(step) { setStep(step) {
this._step = 'Register.' + step; this._step = 'Register.' + step;
// TODO: // TODO:
@ -112,6 +117,7 @@ class Register extends Signup {
var flow = self.chooseFlow(error.data.flows); var flow = self.chooseFlow(error.data.flows);
if (flow) { if (flow) {
console.log("Active flow => %s", JSON.stringify(flow));
var flowStage = self.firstUncompletedStageIndex(flow); var flowStage = self.firstUncompletedStageIndex(flow);
return self.startStage(flow.stages[flowStage]); return self.startStage(flow.stages[flowStage]);
} }
@ -174,6 +180,7 @@ class Register extends Signup {
} }
var stage = new StageClass(MatrixClientPeg.get(), this); var stage = new StageClass(MatrixClientPeg.get(), this);
this.activeStage = stage;
return stage.complete().then(function(request) { return stage.complete().then(function(request) {
if (request.auth) { if (request.auth) {
return self._tryRegister(request.auth); return self._tryRegister(request.auth);
@ -220,6 +227,13 @@ class Register extends Signup {
return otherFlow; return otherFlow;
} }
} }
tellStage(stageName, data) {
if (this.activeStage && this.activeStage.type === stageName) {
console.log("Telling stage %s about something..", stageName);
this.activeStage.onReceiveData(data);
}
}
} }

View file

@ -16,6 +16,10 @@ class Stage {
// Has a "message" string and an "isFatal" flag. // Has a "message" string and an "isFatal" flag.
return q.reject("NOT IMPLEMENTED"); return q.reject("NOT IMPLEMENTED");
} }
onReceiveData() {
// NOP
}
} }
Stage.TYPE = "NOT IMPLEMENTED"; Stage.TYPE = "NOT IMPLEMENTED";
@ -39,12 +43,22 @@ DummyStage.TYPE = "m.login.dummy";
class RecaptchaStage extends Stage { class RecaptchaStage extends Stage {
constructor(matrixClient, signupInstance) { constructor(matrixClient, signupInstance) {
super(RecaptchaStage.TYPE, matrixClient, signupInstance); super(RecaptchaStage.TYPE, matrixClient, signupInstance);
this.defer = q.defer();
this.publicKey = null;
}
onReceiveData(data) {
if (data !== "loaded") {
return;
}
this._attemptRender();
} }
complete() { complete() {
var publicKey; var publicKey;
if (this.signupInstance.params['m.login.recaptcha']) { var serverParams = this.signupInstance.getServerData().params;
publicKey = this.signupInstance.params['m.login.recaptcha'].public_key; if (serverParams && serverParams["m.login.recaptcha"]) {
publicKey = serverParams["m.login.recaptcha"].public_key;
} }
if (!publicKey) { if (!publicKey) {
return q.reject({ return q.reject({
@ -53,12 +67,26 @@ class RecaptchaStage extends Stage {
isFatal: true isFatal: true
}); });
} }
this.publicKey = publicKey;
this._attemptRender();
var defer = q.defer(); 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;
}
var self = this;
global.grecaptcha.render('mx_recaptcha', { global.grecaptcha.render('mx_recaptcha', {
sitekey: publicKey, sitekey: this.publicKey,
callback: function(response) { callback: function(response) {
return defer.resolve({ return self.defer.resolve({
auth: { auth: {
type: 'm.login.recaptcha', type: 'm.login.recaptcha',
response: response response: response
@ -66,8 +94,6 @@ class RecaptchaStage extends Stage {
}); });
} }
}); });
return defer.promise;
} }
} }
RecaptchaStage.TYPE = "m.login.recaptcha"; RecaptchaStage.TYPE = "m.login.recaptcha";