Merge pull request #238 from zaach/real-password-reset
Password reset with fxa-client #235 Travis is finally green. r+. Thanks for the explanations @zaach!
This commit is contained in:
Коммит
504400ecff
|
@ -13,25 +13,6 @@ define([
|
|||
'processed/constants'
|
||||
],
|
||||
function (FxaClient, Constants) {
|
||||
// placeholder promise to stand in for FxaClient functionality that is
|
||||
// not yet ready.
|
||||
function PromiseMock() {
|
||||
}
|
||||
PromiseMock.prototype = {
|
||||
then: function (callback) {
|
||||
var promise = new PromiseMock();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return promise;
|
||||
},
|
||||
done: function (callback) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function FxaClientWrapper() {
|
||||
this.client = new FxaClient(Constants.FXA_ACCOUNT_SERVER);
|
||||
}
|
||||
|
@ -54,12 +35,17 @@ function (FxaClient, Constants) {
|
|||
return this.client.verifyCode(uid, code);
|
||||
},
|
||||
|
||||
requestPasswordReset: function () {
|
||||
return new PromiseMock();
|
||||
requestPasswordReset: function (email) {
|
||||
return this.client.passwordForgotSendCode(email);
|
||||
},
|
||||
|
||||
completePasswordReset: function () {
|
||||
return new PromiseMock();
|
||||
completePasswordReset: function (email, newPassword, token, code) {
|
||||
return this.client.passwordForgotVerifyCode(code, token)
|
||||
.then(function (result) {
|
||||
return this.client.accountReset(email,
|
||||
newPassword,
|
||||
result.accountResetToken);
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,22 +22,28 @@ function (_, BaseView, Template, FxaClient, Session, Url) {
|
|||
},
|
||||
|
||||
afterRender: function () {
|
||||
this.uid = Url.searchParam('uid');
|
||||
if (! this.uid) {
|
||||
return this.displayError('no uid specified');
|
||||
this.token = Url.searchParam('token');
|
||||
if (! this.token) {
|
||||
return this.displayError('no token specified');
|
||||
}
|
||||
|
||||
this.code = Url.searchParam('code');
|
||||
if (! this.code) {
|
||||
return this.displayError('no code specified');
|
||||
}
|
||||
|
||||
this.email = Url.searchParam('email');
|
||||
if (! this.email) {
|
||||
return this.displayError('no email specified');
|
||||
}
|
||||
},
|
||||
|
||||
submit: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (! (this.uid &&
|
||||
if (! (this.token &&
|
||||
this.code &&
|
||||
this.email &&
|
||||
this._validatePasswords())) {
|
||||
return;
|
||||
}
|
||||
|
@ -45,7 +51,7 @@ function (_, BaseView, Template, FxaClient, Session, Url) {
|
|||
var password = this._getPassword();
|
||||
|
||||
var client = new FxaClient();
|
||||
client.completePasswordReset(password, this.uid, this.code)
|
||||
client.completePasswordReset(this.email, password, this.token, this.code)
|
||||
.done(_.bind(this._onResetCompleteSuccess, this),
|
||||
_.bind(this._onResetCompleteFailure, this));
|
||||
},
|
||||
|
|
|
@ -6,6 +6,11 @@ const config = require('./configuration');
|
|||
const path = require('path');
|
||||
|
||||
module.exports = function(app) {
|
||||
// handle password reset links
|
||||
app.get('/v1/complete_reset_password', function(req, res) {
|
||||
res.redirect(req.originalUrl.slice(3));
|
||||
});
|
||||
|
||||
// handle email verification links
|
||||
app.get('/v1/verify_email', function(req, res) {
|
||||
res.redirect(req.originalUrl.slice(3));
|
||||
|
|
|
@ -5,24 +5,76 @@
|
|||
define([
|
||||
'intern!object',
|
||||
'intern/chai!assert',
|
||||
'require'
|
||||
], function (registerSuite, assert, require) {
|
||||
'require',
|
||||
'intern/node_modules/dojo/node!xmlhttprequest',
|
||||
'app/bower_components/fxa-js-client/fxa-client',
|
||||
'intern/node_modules/dojo/Deferred',
|
||||
'tests/lib/restmail'
|
||||
], function (registerSuite, assert, require, nodeXMLHttpRequest, FxaClient, Deferred, restmail) {
|
||||
'use strict';
|
||||
|
||||
var url = 'http://localhost:3030/complete_reset_password';
|
||||
var AUTH_SERVER_ROOT = 'http://127.0.0.1:9000/v1';
|
||||
var EMAIL_SERVER_ROOT = 'http://127.0.0.1:9001';
|
||||
var PAGE_URL_ROOT = 'http://localhost:3030/complete_reset_password';
|
||||
var PASSWORD = 'password';
|
||||
var email;
|
||||
var code;
|
||||
var token;
|
||||
|
||||
registerSuite({
|
||||
name: 'complete_reset_password',
|
||||
|
||||
setup: function () {
|
||||
var dfd = new Deferred();
|
||||
|
||||
var user = 'signin' + Math.random();
|
||||
email = user + '@restmail.net';
|
||||
|
||||
var client = new FxaClient(AUTH_SERVER_ROOT, {
|
||||
xhr: nodeXMLHttpRequest.XMLHttpRequest
|
||||
});
|
||||
|
||||
client.signUp(email, PASSWORD)
|
||||
.then(function () {
|
||||
return client.passwordForgotSendCode(email);
|
||||
})
|
||||
.then(function (result) {
|
||||
token = result.passwordForgotToken;
|
||||
|
||||
restmail(EMAIL_SERVER_ROOT + '/mail/' + user, 2,
|
||||
function (err, emails) {
|
||||
code = emails[1].html.match(/code=([A-Za-z0-9]+)/)[1];
|
||||
dfd.resolve(code);
|
||||
}
|
||||
);
|
||||
}, dfd.reject.bind(dfd));
|
||||
|
||||
return dfd.promise;
|
||||
},
|
||||
|
||||
'open page': function () {
|
||||
|
||||
var url = PAGE_URL_ROOT + '?token=' + token + '&code=' + code + '&email=' + encodeURIComponent(email);
|
||||
|
||||
return this.get('remote')
|
||||
.get(require.toUrl(url))
|
||||
.waitForElementById('fxa-complete-reset-password-header')
|
||||
|
||||
.elementByCssSelector('form input#password')
|
||||
.click()
|
||||
.type(PASSWORD)
|
||||
.end()
|
||||
|
||||
.elementByCssSelector('form input#vpassword')
|
||||
.click()
|
||||
.type(PASSWORD)
|
||||
.end()
|
||||
|
||||
.elementByCssSelector('button[type="submit"]')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
.waitForElementById('fxa-reset-password-complete-header')
|
||||
.end();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -33,6 +33,16 @@ define([
|
|||
.get(require.toUrl(PAGE_URL))
|
||||
.waitForElementById('fxa-reset-password-header')
|
||||
|
||||
.elementByCssSelector('form input.email')
|
||||
.click()
|
||||
.type(email)
|
||||
.end()
|
||||
|
||||
.elementByCssSelector('button[type="submit"]')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
.waitForElementById('fxa-confirm-reset-password-header')
|
||||
.end();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
define([
|
||||
'intern/node_modules/dojo/node!xmlhttprequest',
|
||||
], function (nodeXMLHttpRequest) {
|
||||
'use strict';
|
||||
|
||||
function request(uri, method, jsonPayload, cb) {
|
||||
var xhr = new nodeXMLHttpRequest.XMLHttpRequest();
|
||||
var payload;
|
||||
|
||||
xhr.open(method, uri);
|
||||
xhr.onerror = function onerror() {
|
||||
cb(xhr.responseText);
|
||||
};
|
||||
xhr.onload = function onload() {
|
||||
var result;
|
||||
try {
|
||||
result = JSON.parse(xhr.responseText);
|
||||
} catch (e) {
|
||||
return cb(e);
|
||||
}
|
||||
if (result.error) {
|
||||
return cb(result.error);
|
||||
}
|
||||
cb(null, result);
|
||||
};
|
||||
|
||||
if (jsonPayload) {
|
||||
payload = JSON.stringify(jsonPayload);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
xhr.send(payload);
|
||||
}
|
||||
|
||||
return request;
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
define([
|
||||
'tests/lib/request',
|
||||
], function (request) {
|
||||
'use strict';
|
||||
|
||||
function waitForEmail(uri, number, cb) {
|
||||
if (!number) {
|
||||
number = 1;
|
||||
}
|
||||
console.log('Waiting for email...');
|
||||
|
||||
request(uri, 'GET', null, function (err, result) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (result.length >= number) {
|
||||
return cb(null, result);
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
waitForEmail(uri, number, cb);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return waitForEmail;
|
||||
});
|
Загрузка…
Ссылка в новой задаче