Accounts.onCreateUser not working as expected

Hey guys,

I’m trying to run the following on Accounts.onCreateUser() on the server when a new user signs up. I’m basically trying to hook into the newly created account and add a new field, but it doesn’t seem to do anything at all.

Accounts.onCreateUser(function (options, user) {
  Meteor.users.update({_id: user._id}, {fields: {uid: 'somethingrandomhere'}});

  if (options.profile)
    user.profile = options.profile;

  return user;
});

What am I doing wrong?

Is this running BEFORE the user record is actually created? And if so what can I use instead to achieve the desired result?

Hmm so it does work if you try to update or insert to another collection from this hook but you can’t seem to update the Meteor.users collection this way.

Accounts.onCreateUser(function (options, user) {
  let pid = generatePid();
  UserMeta.insert({
    uid: user._id,
    pid: pid,
    username: user.username
  });

  if (options.profile)
    user.profile = options.profile;

  return user;
});

I guess it is something to do with the time that this hook is being called?

The onCreateUser hook runs just before the record is inserted into the database and expects your function to return the user object again.
That returned object is then inserted into the database.

From the docs:

ARGUMENTS

func Function
Called whenever a new user is created. Return the new user object, or throw an Error to abort the creation.

The function should return the user document (either the one passed in or a newly-created object) with whatever modifications are desired. The returned document is inserted directly into the Meteor.users collection.

So if you want to add a field to the user record, just add it to the user object and return it:

Accounts.onCreateUser(function (options, user) {
  // Directly modify the user object, the modified object will be inserted into the Users Collection
  user.uid = 'somethingrandomhere';
  return user;
});
1 Like

Ahh it’s that simple?

Thanks bro :slight_smile:

1 Like

Yeah the docs aren’t as explicit as they should be about when this hook is called, and why it doesn’t exist in the db yet

1 Like

Do you know of any good tutorials that go quite deep into Meteor / Mongo routines?

It’s the one area I seem to be struggling with the most.

Most of the things I can find seem to be aimed at single page apps with a single user in mind (i.e little or no interaction with other users on the system), and they are all pretty basic. I’m as new to MongoDB as I am to Meteor (MySQL is what I’m used to) so I’m finding it quite confusing to do some pretty trivial things like displaying a list of users for a “follow” system for instance, without exposing sensitive data (email etc) about all users.

Have you looked at the Meteor Guide?

1 Like

Yes, I’ve read them through many times but it’s just not sinking in. I can do the basic stuff, where I’m coming unstuck is when it comes to security measures when accessing / sharing collections that contain sensitive data.

It is totally possible that I’m way overthinking it, as illustrated in my original question in this thread, and a big part of that is the fact that I’m still uncomfortable with Mongo and how it’s data is accessed, from a security point of view. Again, this is probably due to my MySQL background where, as I’m sure you know, security and access rights are a major issue. I guess it’s freaking me out a bit that security issues don’t seem to play a big part in any of the Meteor tutorials that I’ve followed. In short I think I’m really looking for a “Do’s & Don’ts” of Mongo / Meteor.

I know about autopublish and insecure and those have been removed, but I’m still a bit in the dark about best practices when it comes to accessing and sharing Mongo data.

It’s not really any different in MongoDB, either.

Let’s face it, you can create a MySQL database and access it using the root account forever by using software to control what you can do. However, that’s clearly risky, and you would normally limit access very tightly by assigning appropriate right to users.

In MongoDB, you can make similar tradeoffs - have an all-powerful user and limit access through software - that’s basically what you get out of the box with a simple Meteor application. There are packages to help (or possibly hinder, in the case of insecure and autopublish) - alanning:roles being one. You can also secure access at the database level using MongoDb role-based access, which is recommended for any serious app.

Meteor makes some fairly sensible decisions regarding the data which is exposed to the clients via pub/sub. However, if you choose to, you can expose everything to everyone. It’s mostly down to common-sense planning: the principle of least privilege being a good touchstone.

1 Like

Thanks Rob,

Didn’t know about MongoDb role access at all! This looks like the “calming pill” I needed :smile:

1 Like

Just in case you want to try this out and decide to roll your own DB:
The MONGO_URL environment variable then needs to look like this:

MONGO_URL=user:password@ip_adress:port/meteordb?authSource=userdb

Where the password definitely shouldn’t include special characters and the authSource is the database inside Mongo where you’re creating your users in.
What you’re then looking for is either a readWrite or a dbOwner rule.

I probably should create a pull request for the Meteor documentation to reflect this factoid - took me a bit to figure it out.

1 Like