Add createdAt timestamp to new user records. Add extra safety belt to prevent duplicate email or username.

This commit is contained in:
Nick Martin
2012-09-20 13:39:31 -07:00
parent 3e650e786e
commit c50cd1defa
2 changed files with 108 additions and 4 deletions

View File

@@ -103,6 +103,10 @@
return _.extend(user, extra);
};
Meteor.accounts.onCreateUserHook = function (options, extra, user) {
// add created at timestamp (and protect passed in user object from
// modification)
user = _.extend({createdAt: +(new Date)}, user);
var fullUser;
if (onCreateUserHook) {
@@ -118,13 +122,22 @@
}
_.each(validateNewUserHooks, function (hook) {
if (!hook(user))
if (!hook(fullUser))
throw new Meteor.Error(403, "User validation failed");
});
// XXX check for existing user with duplicate email or username.
// better here than the two places we call it (and immediately
// follow with an insert)
// check for existing user with duplicate email or username.
if (fullUser.username &&
Meteor.users.findOne({username: fullUser.username}))
throw new Meteor.Error(403, "Username already exists.");
if (fullUser.emails) {
var addresses = _.map(fullUser.emails, function (e) {
return e.address; });
if (Meteor.users.findOne({'emails.address': {$in: addresses}}))
throw new Meteor.Error(403, "Email already exists.");
}
return fullUser;
};

View File

@@ -39,3 +39,94 @@ Tinytest.add('accounts - updateOrCreateUser', function (test) {
});
Tinytest.add('accounts - onCreateUserHook username', function (test) {
var userIn = {
username: Meteor.uuid()
};
// user does not already exist. return a user object with fields set.
var userOut = Meteor.accounts.onCreateUserHook(
userIn,
{profile: {name: 'Foo Bar'}},
userIn
);
test.equal(typeof userOut.createdAt, 'number');
test.equal(userOut.profile.name, 'Foo Bar');
test.equal(userOut.username, userIn.username);
// insert the user
var uid = Meteor.users.insert(userOut);
// run the hook again. now the user exists, so it throws an error.
test.throws(function () {
Meteor.accounts.onCreateUserHook(
userIn,
{profile: {name: 'Foo Bar'}},
userIn
);
});
// cleanup
Meteor.users.remove(uid);
});
Tinytest.add('accounts - onCreateUserHook email', function (test) {
var email1 = Meteor.uuid();
var email2 = Meteor.uuid();
var email3 = Meteor.uuid();
var userIn = {
emails: [{address: email1, verified: false},
{address: email2, verified: true}]
};
// user does not already exist. return a user object with fields set.
var userOut = Meteor.accounts.onCreateUserHook(
userIn,
{profile: {name: 'Foo Bar'}},
userIn
);
test.equal(typeof userOut.createdAt, 'number');
test.equal(userOut.profile.name, 'Foo Bar');
test.equal(userOut.emails, userIn.emails);
// insert the user
var uid = Meteor.users.insert(userOut);
// run the hook again with the exact same emails.
// run the hook again. now the user exists, so it throws an error.
test.throws(function () {
Meteor.accounts.onCreateUserHook(
userIn,
{profile: {name: 'Foo Bar'}},
userIn
);
});
// now with only one of them.
test.throws(function () {
Meteor.accounts.onCreateUserHook(
{}, {}, {emails: [{address: email1}]}
);
});
test.throws(function () {
Meteor.accounts.onCreateUserHook(
{}, {}, {emails: [{address: email2}]}
);
});
// a third email works.
var user3 = Meteor.accounts.onCreateUserHook(
{}, {}, {emails: [{address: email3}]}
);
test.equal(typeof userOut.createdAt, 'number');
// cleanup
Meteor.users.remove(uid);
});