Merge pull request #280 from isocolsky/send_error

Stop profile creation when verification email cannot be send
This commit is contained in:
Matias Alejo Garcia 2014-12-18 15:20:57 -03:00
commit 3e20b219b3
2 changed files with 85 additions and 43 deletions

View File

@ -52,6 +52,10 @@
code: 406,
message: 'User quota exceeded',
},
ERROR_SENDING_EMAIL: {
code: 501,
message: 'Could not send verification email',
},
};
var EMAIL_TO_PASSPHRASE = 'email-to-passphrase-';
@ -141,7 +145,7 @@
* @param {string} email - the user's email
* @param {string} secret - the verification secret
*/
emailPlugin.sendVerificationEmail = function(email, secret) {
emailPlugin.sendVerificationEmail = function(email, secret, callback) {
var confirmUrl = emailPlugin.makeConfirmUrl(email, secret);
logger.debug('ConfirmUrl:',confirmUrl);
@ -176,9 +180,10 @@
emailPlugin.email.sendMail(mailOptions, function(err, info) {
if (err) {
logger.error('An error occurred when trying to send email to ' + email, err);
} else {
logger.info('Message sent: ', info ? info : '');
return callback(err);
}
logger.info('Message sent: ', info ? info : '');
return callback(err, info);
});
});
};
@ -346,14 +351,17 @@
emailPlugin.createVerificationSecretAndSendEmail = function(email, callback) {
emailPlugin.createVerificationSecret(email, function(err, secret) {
if (err) {
if (err || !secret) {
logger.error('error saving verification secret', email, secret, err);
return callback(emailPlugin.errors.INTERNAL_ERROR);
}
if (secret) {
emailPlugin.sendVerificationEmail(email, secret);
}
callback();
emailPlugin.sendVerificationEmail(email, secret, function (err, res) {
if (err) {
logger.error('error sending verification email', email, secret, err);
return callback(emailPlugin.errors.ERROR_SENDING_EMAIL);
}
return callback();
});
});
};
@ -478,7 +486,9 @@
};
emailPlugin.processPost = function(request, response, email, key, passphrase, record) {
var isConfirmed = false;
var isNewProfile = false;
var isConfirmed = true;
var errorCreating = false;
async.series([
/**
@ -486,20 +496,16 @@
*/
function(callback) {
emailPlugin.exists(email, function(err, exists) {
if (err) {
return callback(err);
} else if (exists) {
if (err) return callback(err);
if (exists) {
emailPlugin.checkPassphrase(email, passphrase, function(err, match) {
if (err) {
return callback(err);
}
if (match) {
return callback();
} else {
return callback(emailPlugin.errors.EMAIL_TAKEN);
}
if (err) return callback(err);
if (!match) return callback(emailPlugin.errors.EMAIL_TAKEN);
return callback();
});
} else {
isNewProfile = true;
emailPlugin.savePassphrase(email, passphrase, function(err) {
return callback(err);
});
@ -528,30 +534,31 @@
*/
function(callback) {
emailPlugin.saveEncryptedData(email, key, record, function(err) {
if (err) {
return callback(err);
}
return callback();
return callback(err);
});
},
/**
* Create and store the verification secret. If successful, send a verification email.
*/
function(callback) {
if (!isNewProfile || isConfirmed) return callback();
emailPlugin.createVerificationSecretAndSendEmail(email, function(err) {
if (err) {
callback({
code: 500,
message: err
});
} else {
callback();
errorCreating = true;
}
return callback(err);
});
}
},
],
function(err) {
if (err) {
if (isNewProfile && !isConfirmed && errorCreating) {
emailPlugin.deleteWholeProfile(email, function() {
return emailPlugin.returnError(err, response);
});
}
emailPlugin.returnError(err, response);
} else {
response.json({

View File

@ -22,7 +22,7 @@ describe('emailstore test', function() {
leveldb_stub.get = sinon.stub();
leveldb_stub.del = sinon.stub();
var email_stub = sinon.stub();
email_stub.sendMail = sinon.stub();
email_stub.sendMail = sinon.stub().callsArg(1);
var cryptoMock = {
randomBytes: sinon.stub()
@ -199,7 +199,6 @@ describe('emailstore test', function() {
});
describe('creating verification secret', function() {
var sendVerificationEmail = sinon.stub(plugin, 'sendVerificationEmail');
var fakeEmail = 'fake@email.com';
var fakeRandom = 'fakerandom';
var randomBytes = {
@ -211,8 +210,8 @@ describe('emailstore test', function() {
beforeEach(function() {
leveldb_stub.get.reset();
leveldb_stub.put.reset();
plugin.email.sendMail.reset();
sendVerificationEmail.reset();
cryptoMock.randomBytes = sinon.stub();
cryptoMock.randomBytes.onFirstCall().returns(randomBytes);
});
@ -235,11 +234,11 @@ describe('emailstore test', function() {
done();
});
});
it('calls the function to verify the email', function(done) {
it('sends verification email', function(done) {
setupLevelDb();
plugin.createVerificationSecretAndSendEmail(fakeEmail, function(err) {
sendVerificationEmail.calledOnce;
plugin.email.sendMail.calledOnce.should.be.true;
done();
});
});
@ -260,15 +259,10 @@ describe('emailstore test', function() {
done();
});
});
after(function() {
plugin.sendVerificationEmail.restore();
});
});
});
describe('on registration', function() {
var emailParam = 'email';
var secretParam = 'secret';
var keyParam = 'key';
@ -336,7 +330,6 @@ describe('emailstore test', function() {
plugin.saveEncryptedData = sinon.stub();
plugin.saveEncryptedData.onFirstCall().callsArg(3);
plugin.createVerificationSecretAndSendEmail = sinon.stub();
plugin.createVerificationSecretAndSendEmail.onFirstCall().callsArg(1);
response.send.onFirstCall().returnsThis();
plugin.save(request, response);
@ -347,9 +340,51 @@ describe('emailstore test', function() {
assert(plugin.saveEncryptedData.firstCall.args[0] === emailParam);
assert(plugin.saveEncryptedData.firstCall.args[1] === keyParam);
assert(plugin.saveEncryptedData.firstCall.args[2] === recordParam);
assert(plugin.createVerificationSecretAndSendEmail.firstCall.args[0] === emailParam);
plugin.createVerificationSecretAndSendEmail.called.should.be.false;
plugin.getCredentialsFromRequest = originalCredentials;
});
it('should delete profile on error sending verification email', function() {
var originalCredentials = plugin.getCredentialsFromRequest;
plugin.getCredentialsFromRequest = sinon.mock();
plugin.getCredentialsFromRequest.onFirstCall().returns({
email: emailParam,
passphrase: secretParam
});
plugin.exists = sinon.stub();
plugin.exists.onFirstCall().callsArgWith(1, null, false);
plugin.savePassphrase = sinon.stub();
plugin.savePassphrase.onFirstCall().callsArg(2);
plugin.isConfirmed = sinon.stub();
plugin.isConfirmed.onFirstCall().callsArgWith(1, null, false);
plugin.checkSizeQuota = sinon.stub();
plugin.checkSizeQuota.onFirstCall().callsArgWith(3, null);
plugin.checkAndUpdateItemQuota = sinon.stub();
plugin.checkAndUpdateItemQuota.onFirstCall().callsArgWith(3, null);
plugin.saveEncryptedData = sinon.stub();
plugin.saveEncryptedData.onFirstCall().callsArg(3);
plugin.createVerificationSecretAndSendEmail = sinon.stub();
plugin.createVerificationSecretAndSendEmail.onFirstCall().callsArgWith(1, 'error');
var deleteWholeProfile = sinon.stub(plugin, 'deleteWholeProfile');
deleteWholeProfile.onFirstCall().callsArg(1);
response.send.onFirstCall().returnsThis();
plugin.save(request, response);
assert(plugin.exists.firstCall.args[0] === emailParam);
assert(plugin.savePassphrase.firstCall.args[0] === emailParam);
assert(plugin.savePassphrase.firstCall.args[1] === secretParam);
assert(plugin.saveEncryptedData.firstCall.args[0] === emailParam);
assert(plugin.saveEncryptedData.firstCall.args[1] === keyParam);
assert(plugin.saveEncryptedData.firstCall.args[2] === recordParam);
assert(plugin.createVerificationSecretAndSendEmail.firstCall.args[0] === emailParam);
assert(deleteWholeProfile.firstCall.args[0] === emailParam);
plugin.getCredentialsFromRequest = originalCredentials;
});
after(function () {
plugin.deleteWholeProfile.restore();
});
});
describe('when validating email', function() {