diff --git a/common/models/user.js b/common/models/user.js index 3394e19e..7aa7e04c 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -9,6 +9,7 @@ var g = require('strong-globalize')(); +var isEmail = require('isemail'); var loopback = require('../../lib/loopback'); var utils = require('../../lib/utils'); var path = require('path'); @@ -752,10 +753,9 @@ module.exports = function(User) { assert(loopback.AccessToken, 'AccessToken model must be defined before User model'); UserModel.accessToken = loopback.AccessToken; - // email validation regex - var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - - UserModel.validatesFormatOf('email', { with: re, message: g.f('Must provide a valid email') }); + UserModel.validate('email', emailValidator, { + message: g.f('Must provide a valid email'), + }); // FIXME: We need to add support for uniqueness of composite keys in juggler if (!(UserModel.settings.realmRequired || UserModel.settings.realmDelimiter)) { @@ -772,3 +772,14 @@ module.exports = function(User) { User.setup(); }; + +function emailValidator(err, done) { + var value = this.email; + if (value == null) + return; + if (typeof value !== 'string') + return err('string'); + if (value === '') return; + if (!isEmail(value)) + return err('email'); +} diff --git a/package.json b/package.json index 92766fbd..2b059745 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "inflection": "^1.6.0", "loopback-connector-remote": "^2.0.0-alpha.1", "loopback-datasource-juggler": "^3.0.0-alpha.7", + "isemail": "^1.2.0", "loopback-phase": "^1.2.0", "nodemailer": "^2.5.0", "nodemailer-stub-transport": "^1.0.0", diff --git a/test/user.test.js b/test/user.test.js index 477019f2..a13d3c7b 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -120,10 +120,7 @@ describe('User', function() { assert.equal(err.name, 'ValidationError'); assert.equal(err.statusCode, 422); assert.equal(err.details.context, User.modelName); - assert.deepEqual(err.details.codes.email, [ - 'presence', - 'format.null', - ]); + assert.deepEqual(err.details.codes.email, ['presence']); done(); }); @@ -143,11 +140,21 @@ describe('User', function() { it('Requires a valid email', function(done) { User.create({ email: 'foo@', password: '123' }, function(err) { assert(err); - + assert.equal(err.name, 'ValidationError'); + assert.equal(err.statusCode, 422); + assert.equal(err.details.context, User.modelName); + assert.deepEqual(err.details.codes.email, ['custom.email']); done(); }); }); + it('allows TLD domains in email', function() { + return User.create({ + email: 'local@com', + password: '123', + }); + }); + it('Requires a unique email', function(done) { User.create({ email: 'a@b.com', password: 'foobar' }, function() { User.create({ email: 'a@b.com', password: 'batbaz' }, function(err) {