Merge pull request #365 from strongloop/feature/login-email-verification

Add an option to honor emailVerified
This commit is contained in:
Raymond Feng 2014-07-08 13:24:10 -07:00
commit f8ffd978cf
4 changed files with 94 additions and 5 deletions

View File

@ -18,7 +18,7 @@ module.exports = MailConnector;
*/
function MailConnector(settings) {
assert(typeof settings === 'object', 'cannot initiaze MailConnector without a settings object');
assert(typeof settings === 'object', 'cannot initialize MailConnector without a settings object');
var transports = settings.transports || [];
this.transportsIndex = {};
this.transports = [];

View File

@ -186,6 +186,15 @@ User.login = function (credentials, include, fn) {
debug('An error is reported from User.findOne: %j', err);
fn(defaultError);
} else if(user) {
if (self.settings.emailVerificationRequired) {
if (!user.emailVerified) {
// Fail to log in if email verification is not done yet
debug('User email has not been verified');
err = new Error('login failed as the email has not been verified');
err.statusCode = 401;
return fn(err);
}
}
user.hasPassword(credentials.password, function(err, isMatch) {
if(err) {
debug('An error is reported from User.hasPassword: %j', err);
@ -441,6 +450,15 @@ User.setup = function () {
this.$password = bcrypt.hashSync(plain, salt);
}
// Make sure emailVerified is not set by creation
UserModel.beforeRemote('create', function(ctx, user, next) {
var body = ctx.req.body;
if (body && body.emailVerified) {
body.emailVerified = false;
}
next();
});
loopback.remoteMethod(
UserModel.login,
{

View File

@ -76,8 +76,6 @@
"browser": {
"express": "./lib/browser-express.js",
"connect": false,
"passport": false,
"passport-local": false,
"nodemailer": false
},
"license": {

View File

@ -8,6 +8,8 @@ var userMemory = loopback.createDataSource({
describe('User', function(){
var validCredentials = {email: 'foo@bar.com', password: 'bar'};
var validCredentialsEmailVerified = {email: 'foo1@bar.com', password: 'bar1', emailVerified: true};
var validCredentialsEmailVerifiedOverREST = {email: 'foo2@bar.com', password: 'bar2', emailVerified: true};
var validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600};
var invalidCredentials = {email: 'foo1@bar.com', password: 'bar1'};
var incompleteCredentials = {password: 'bar1'};
@ -30,7 +32,9 @@ describe('User', function(){
app.use(loopback.rest());
app.model(User);
User.create(validCredentials, done);
User.create(validCredentials, function(err, user) {
User.create(validCredentialsEmailVerified, done);
});
});
afterEach(function (done) {
@ -105,6 +109,18 @@ describe('User', function(){
var u = new User({username: 'foo', password: 'bar'});
assert(u.password !== 'bar');
});
it('Create a user over REST should remove emailVerified property', function(done) {
request(app)
.post('/users')
.expect('Content-Type', /json/)
.expect(200)
.send(validCredentialsEmailVerifiedOverREST)
.end(function(err, res){
assert(!res.body.emailVerified);
done();
});
});
});
describe('User.login', function() {
@ -155,7 +171,7 @@ describe('User', function(){
});
});
});
it('Login a user over REST by providing credentials', function(done) {
request(app)
.post('/users/login')
@ -235,6 +251,63 @@ describe('User', function(){
});
});
});
describe('User.login requiring email verification', function() {
beforeEach(function() {
User.settings.emailVerificationRequired = true;
});
afterEach(function() {
User.settings.emailVerificationRequired = false;
});
it('Login a user by without email verification', function(done) {
User.login(validCredentials, function (err, accessToken) {
assert(err);
done();
});
});
it('Login a user by with email verification', function(done) {
User.login(validCredentialsEmailVerified, function (err, accessToken) {
assert(accessToken.userId);
assert(accessToken.id);
assert.equal(accessToken.id.length, 64);
done();
});
});
it('Login a user over REST when email verification is required', function(done) {
request(app)
.post('/users/login')
.expect('Content-Type', /json/)
.expect(200)
.send(validCredentialsEmailVerified)
.end(function(err, res){
if(err) return done(err);
var accessToken = res.body;
assert(accessToken.userId);
assert(accessToken.id);
assert.equal(accessToken.id.length, 64);
assert(accessToken.user === undefined);
done();
});
});
it('Login a user over REST without email verification when it is required', function(done) {
request(app)
.post('/users/login')
.expect('Content-Type', /json/)
.expect(401)
.send(validCredentials)
.end(function(err, res) {
done();
});
});
});
describe('User.logout', function() {
it('Logout a user by providing the current accessToken id (using node)', function(done) {