Merge pull request #1804 from richardpringle/master
Add case-sensitive email option for User model
This commit is contained in:
commit
6d040a98ae
|
@ -62,6 +62,7 @@ var debug = require('debug')('loopback:user');
|
|||
* @property {String} settings.realmDelimiter When set a realm is required.
|
||||
* @property {Number} settings.resetPasswordTokenTTL Time to live for password reset `AccessToken`. Default is `900` (15 minutes).
|
||||
* @property {Number} settings.saltWorkFactor The `bcrypt` salt work factor. Default is `10`.
|
||||
* @property {Boolean} settings.caseSensitiveEmail Enable case sensitive email.
|
||||
*
|
||||
* @class User
|
||||
* @inherits {PersistedModel}
|
||||
|
@ -577,6 +578,14 @@ module.exports = function(User) {
|
|||
this.settings.maxTTL = this.settings.maxTTL || DEFAULT_MAX_TTL;
|
||||
this.settings.ttl = this.settings.ttl || DEFAULT_TTL;
|
||||
|
||||
UserModel.setter.email = function(value) {
|
||||
if (!UserModel.settings.caseSensitiveEmail) {
|
||||
this.$email = value.toLowerCase();
|
||||
} else {
|
||||
this.$email = value;
|
||||
}
|
||||
};
|
||||
|
||||
UserModel.setter.password = function(plain) {
|
||||
if (typeof plain !== 'string') {
|
||||
return;
|
||||
|
@ -590,6 +599,14 @@ module.exports = function(User) {
|
|||
}
|
||||
};
|
||||
|
||||
// Access token to normalize email credentials
|
||||
UserModel.observe('access', function normalizeEmailCase(ctx, next) {
|
||||
if (!ctx.Model.settings.caseSensitiveEmail && ctx.query.where && ctx.query.where.email) {
|
||||
ctx.query.where.email = ctx.query.where.email.toLowerCase();
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// Make sure emailVerified is not set by creation
|
||||
UserModel.beforeRemote('create', function(ctx, user, next) {
|
||||
var body = ctx.req.body;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
"created": "date",
|
||||
"lastUpdated": "date"
|
||||
},
|
||||
"options": {
|
||||
"caseSensitiveEmail": true
|
||||
},
|
||||
"hidden": ["password"],
|
||||
"acls": [
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@ describe('User', function() {
|
|||
var validCredentialsEmailVerifiedOverREST = {email: 'foo2@bar.com', password: 'bar2', emailVerified: true};
|
||||
var validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600};
|
||||
var validCredentialsWithTTLAndScope = {email: 'foo@bar.com', password: 'bar', ttl: 3600, scope: 'all'};
|
||||
var validMixedCaseEmailCredentials = {email: 'Foo@bar.com', password: 'bar'};
|
||||
var invalidCredentials = {email: 'foo1@bar.com', password: 'invalid'};
|
||||
var incompleteCredentials = {password: 'bar1'};
|
||||
|
||||
|
@ -67,6 +68,26 @@ describe('User', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('Create a new user (email case-sensitivity off)', function(done) {
|
||||
User.settings.caseSensitiveEmail = false;
|
||||
User.create({email: 'F@b.com', password: 'bar'}, function(err, user) {
|
||||
if (err) return done(err);
|
||||
assert(user.id);
|
||||
assert.equal(user.email, user.email.toLowerCase());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Create a new user (email case-sensitive)', function(done) {
|
||||
User.create({email: 'F@b.com', password: 'bar'}, function(err, user) {
|
||||
if (err) return done(err);
|
||||
assert(user.id);
|
||||
assert(user.email);
|
||||
assert.notEqual(user.email, user.email.toLowerCase());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('credentials/challenges are object types', function(done) {
|
||||
User.create({email: 'f1@b.com', password: 'bar1',
|
||||
credentials: {cert: 'xxxxx', key: '111'},
|
||||
|
@ -124,6 +145,27 @@ describe('User', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('Requires a unique email (email case-sensitivity off)', function(done) {
|
||||
User.settings.caseSensitiveEmail = false;
|
||||
User.create({email: 'A@b.com', password: 'foobar'}, function(err) {
|
||||
if (err) return done(err);
|
||||
User.create({email: 'a@b.com', password: 'batbaz'}, function(err) {
|
||||
assert(err, 'should error because the email is not unique!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Requires a unique email (email case-sensitive)', function(done) {
|
||||
User.create({email: 'A@b.com', password: 'foobar'}, function(err, user1) {
|
||||
User.create({email: 'a@b.com', password: 'batbaz'}, function(err, user2) {
|
||||
if (err) return done(err);
|
||||
assert.notEqual(user1.email, user2.email);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Requires a unique username', function(done) {
|
||||
User.create({email: 'a@b.com', username: 'abc', password: 'foobar'}, function() {
|
||||
User.create({email: 'b@b.com', username: 'abc', password: 'batbaz'}, function(err) {
|
||||
|
@ -212,6 +254,25 @@ describe('User', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Access-hook for queries with email NOT case-sensitive', function() {
|
||||
it('Should not throw an error if the query does not contain {where: }', function(done) {
|
||||
User.find({}, function(err) {
|
||||
if (err) done(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to find lowercase email with mixed-case email query', function(done) {
|
||||
User.settings.caseSensitiveEmail = false;
|
||||
User.find({where:{email: validMixedCaseEmailCredentials.email}}, function(err, result) {
|
||||
if (err) done(err);
|
||||
assert(result[0], 'The query did not find the user');
|
||||
assert.equal(result[0].email, validCredentialsEmail);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('User.login', function() {
|
||||
it('Login a user by providing credentials', function(done) {
|
||||
User.login(validCredentials, function(err, accessToken) {
|
||||
|
@ -223,6 +284,23 @@ describe('User', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('Login a user by providing email credentials (email case-sensitivity off)', function(done) {
|
||||
User.settings.caseSensitiveEmail = false;
|
||||
User.login(validMixedCaseEmailCredentials, function(err, accessToken) {
|
||||
assert(accessToken.userId);
|
||||
assert(accessToken.id);
|
||||
assert.equal(accessToken.id.length, 64);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Try to login with invalid email case', function(done) {
|
||||
User.login(validMixedCaseEmailCredentials, function(err, accessToken) {
|
||||
assert(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Login a user by providing credentials with TTL', function(done) {
|
||||
User.login(validCredentialsWithTTL, function(err, accessToken) {
|
||||
assert(accessToken.userId);
|
||||
|
@ -477,7 +555,6 @@ describe('User', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function assertGoodToken(accessToken) {
|
||||
|
|
Loading…
Reference in New Issue