Merge pull request #246 from matiu/feature/validation-header

feature: add "is email validated" header to emailplugin responses
This commit is contained in:
Esteban Ordano 2014-11-12 15:57:53 -03:00
commit 1c7c39a104
2 changed files with 594 additions and 547 deletions

View File

@ -92,14 +92,11 @@ emailPlugin.init = function (config) {
emailPlugin.crypto = config.crypto || crypto; emailPlugin.crypto = config.crypto || crypto;
emailPlugin.confirmUrl = ( emailPlugin.confirmUrl = (
process.env.INSIGHT_EMAIL_CONFIRM_HOST process.env.INSIGHT_EMAIL_CONFIRM_HOST || config.confirmUrl || 'https://insight.bitpay.com'
|| config.confirmUrl
|| 'https://insight.bitpay.com'
) + globalConfig.apiPrefix + '/email/validate'; ) + globalConfig.apiPrefix + '/email/validate';
emailPlugin.redirectUrl = ( emailPlugin.redirectUrl = (
config.redirectUrl config.redirectUrl || 'https://copay.io/in/app?confirmed=true'
|| 'https://copay.io/in/app?confirmed=true'
); );
}; };
@ -115,7 +112,9 @@ emailPlugin.init = function (config) {
* will be called, terminating the request. * will be called, terminating the request.
*/ */
emailPlugin.returnError = function(error, response) { emailPlugin.returnError = function(error, response) {
response.status(error.code).json({error: error.message}).end(); response.status(error.code).json({
error: error.message
}).end();
}; };
/** /**
@ -127,6 +126,7 @@ emailPlugin.returnError = function (error, response) {
emailPlugin.sendVerificationEmail = function(email, secret) { emailPlugin.sendVerificationEmail = function(email, secret) {
var confirmUrl = emailPlugin.makeConfirmUrl(email, secret); var confirmUrl = emailPlugin.makeConfirmUrl(email, secret);
async.series([ async.series([
function(callback) { function(callback) {
emailPlugin.makeEmailBody({ emailPlugin.makeEmailBody({
email: email, email: email,
@ -340,7 +340,9 @@ emailPlugin.save = function (request, response) {
queryData += data; queryData += data;
if (queryData.length > MAX_ALLOWED_STORAGE) { if (queryData.length > MAX_ALLOWED_STORAGE) {
queryData = ''; queryData = '';
response.writeHead(413, {'Content-Type': 'text/plain'}).end(); response.writeHead(413, {
'Content-Type': 'text/plain'
}).end();
request.connection.destroy(); request.connection.destroy();
} }
}).on('end', function() { }).on('end', function() {
@ -402,7 +404,10 @@ emailPlugin.processPost = function(request, response, email, key, passphrase, re
function(callback) { function(callback) {
emailPlugin.createVerificationSecretAndSendEmail(email, function(err) { emailPlugin.createVerificationSecretAndSendEmail(email, function(err) {
if (err) { if (err) {
callback({code: 500, message: err}); callback({
code: 500,
message: err
});
} else { } else {
callback(); callback();
} }
@ -412,10 +417,11 @@ emailPlugin.processPost = function(request, response, email, key, passphrase, re
if (err) { if (err) {
emailPlugin.returnError(err, response); emailPlugin.returnError(err, response);
} else { } else {
response.json({success: true}).end(); response.json({
success: true
}).end();
} }
} });
);
}; };
@ -432,34 +438,57 @@ emailPlugin.getCredentialsFromRequest = function(request) {
var email = authHeader.substr(0, splitIndex); var email = authHeader.substr(0, splitIndex);
var passphrase = authHeader.substr(splitIndex + 1); var passphrase = authHeader.substr(splitIndex + 1);
return {email: email, passphrase: passphrase}; return {
email: email,
passphrase: passphrase
};
};
emailPlugin.addValidationHeader = function(response, email, callback) {
console.log('[emailstore.js.450]'); //TODO
emailPlugin.db.get(validatedKey(email), function(err, value) {
if (err && !err.notFound)
return callback(err);
if (value)
return callback();
response.set('X-Email-Needs-Validation', 'true');
return callback(null, value || false);
});
}; };
/** /**
* Retrieve a record from the database * Retrieve a record from the database
*/ */
emailPlugin.retrieve = function(request, response) { emailPlugin.retrieve = function(request, response) {
var credentialsResult = emailPlugin.getCredentialsFromRequest(request); var credentialsResult = emailPlugin.getCredentialsFromRequest(request);
if (_.contains(emailPlugin.errors, credentialsResult)) { if (_.contains(emailPlugin.errors, credentialsResult)) {
return emailPlugin.returnError(credentialsResult, response); return emailPlugin.returnError(credentialsResult);
} }
var email = credentialsResult.email; var email = credentialsResult.email;
var passphrase = credentialsResult.passphrase; var passphrase = credentialsResult.passphrase;
var key = request.param('key'); var key = request.param('key');
console.log('[emailstore.js.450:key:]',key); //TODO
if (!passphrase || !email || !key) { if (!passphrase || !email || !key) {
return emailPlugin.returnError(emailPlugin.errors.MISSING_PARAMETER, response); return emailPlugin.returnError(emailPlugin.errors.MISSING_PARAMETER, response);
} }
console.log('[emailstore.js.453]'); //TODO
emailPlugin.retrieveDataByEmailAndPassphrase(email, key, passphrase, function(err, value) { emailPlugin.retrieveDataByEmailAndPassphrase(email, key, passphrase, function(err, value) {
if (err) { if (err)
return emailPlugin.returnError(err, response); return emailPlugin.returnError(err, response);
}
emailPlugin.addValidationHeader(response, email, function(err) {
if (err)
return emailPlugin.returnError(err, response);
response.send(value).end(); response.send(value).end();
}); });
});
}; };
/** /**
@ -484,17 +513,26 @@ emailPlugin.validate = function (request, response) {
if (err.notFound) { if (err.notFound) {
return emailPlugin.returnError(emailPlugin.errors.NOT_FOUND, response); return emailPlugin.returnError(emailPlugin.errors.NOT_FOUND, response);
} }
return emailPlugin.returnError({code: 500, message: err}, response); return emailPlugin.returnError({
code: 500,
message: err
}, response);
} else if (value !== secret) { } else if (value !== secret) {
return emailPlugin.returnError(emailPlugin.errors.INVALID_CODE, response); return emailPlugin.returnError(emailPlugin.errors.INVALID_CODE, response);
} else { } else {
emailPlugin.db.put(validatedKey(email), true, function(err, value) { emailPlugin.db.put(validatedKey(email), true, function(err, value) {
if (err) { if (err) {
return emailPlugin.returnError({code: 500, message: err}, response); return emailPlugin.returnError({
code: 500,
message: err
}, response);
} else { } else {
emailPlugin.db.del(pendingKey(email), function(err, value) { emailPlugin.db.del(pendingKey(email), function(err, value) {
if (err) { if (err) {
return emailPlugin.returnError({code: 500, message: err}, response); return emailPlugin.returnError({
code: 500,
message: err
}, response);
} else { } else {
response.redirect(emailPlugin.redirectUrl); response.redirect(emailPlugin.redirectUrl);
} }
@ -524,7 +562,9 @@ emailPlugin.changePassphrase = function (request, response) {
queryData += data; queryData += data;
if (queryData.length > MAX_ALLOWED_STORAGE) { if (queryData.length > MAX_ALLOWED_STORAGE) {
queryData = ''; queryData = '';
response.writeHead(413, {'Content-Type': 'text/plain'}).end(); response.writeHead(413, {
'Content-Type': 'text/plain'
}).end();
request.connection.destroy(); request.connection.destroy();
} }
}).on('end', function() { }).on('end', function() {
@ -541,7 +581,9 @@ emailPlugin.changePassphrase = function (request, response) {
if (error) { if (error) {
return emailPlugin.returnError(error, response); return emailPlugin.returnError(error, response);
} }
return response.json({success: true}).end(); return response.json({
success: true
}).end();
}); });
}); });
}); });
@ -573,7 +615,9 @@ emailPlugin.oldSave = function (request, response) {
queryData += data; queryData += data;
if (queryData.length > MAX_ALLOWED_STORAGE) { if (queryData.length > MAX_ALLOWED_STORAGE) {
queryData = ''; queryData = '';
response.writeHead(413, {'Content-Type': 'text/plain'}).end(); response.writeHead(413, {
'Content-Type': 'text/plain'
}).end();
request.connection.destroy(); request.connection.destroy();
} }
}).on('end', function() { }).on('end', function() {

View File

@ -387,9 +387,12 @@ describe('emailstore test', function() {
plugin.retrieveDataByEmailAndPassphrase = sinon.stub(); plugin.retrieveDataByEmailAndPassphrase = sinon.stub();
plugin.retrieveDataByEmailAndPassphrase.onFirstCall().callsArgWith(3, null, 'encrypted'); plugin.retrieveDataByEmailAndPassphrase.onFirstCall().callsArgWith(3, null, 'encrypted');
response.send.onFirstCall().returnsThis(); response.send.onFirstCall().returnsThis();
plugin.addValidationHeader = sinon.stub().callsArg(2);
plugin.retrieve(request, response); plugin.retrieve(request, response);
request.header.calledOnce.should.equal(true); request.header.calledOnce.should.equal(true);
response.send.calledOnce.should.equal(true);
assert(request.header.firstCall.args[0] === 'authorization'); assert(request.header.firstCall.args[0] === 'authorization');
assert(plugin.retrieveDataByEmailAndPassphrase.firstCall.args[0] === 'email'); assert(plugin.retrieveDataByEmailAndPassphrase.firstCall.args[0] === 'email');