Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding more fields to Meteor user accounts

I am using mrt add accounts-ui-bootstrap-dropdown and mrt add accounts-password to get a simple login page running on my app.

The accounts users gives me a nice hash containing ids, createdAt, emails, etc.

If I wanted to add other fields in this hash so I can make use of them later, how would I do that? For example, I want then to also enter their given name and surname:

"given_name": "John", "surname": "Doe"

like image 543
user1584575 Avatar asked May 07 '14 01:05

user1584575


People also ask

What is the meteor User () function for?

The Meteor Accounts system builds on top of the userId support in publish and methods . The core packages add the concept of user documents stored in the database, and additional packages add secure password authentication, integration with third party login services, and a pre-built user interface.

Which of the following user accounts packages are provided by the meteor developer group?

Here's a complete list of login providers for which Meteor actively maintains core packages: Facebook with accounts-facebook. Google with accounts-google. GitHub with accounts-github.

How do I add custom data to a user in Meteor?

The best way to store your custom data onto the Meteor.users collection is to add a new uniquely-named top-level field on the user document. For example, if you wanted to add a mailing address to a user, you could do it like this: You can use any field name other than those used by the Accounts system.

What is the meteor accounts system?

The Meteor Accounts system builds on top of the userId support in publish and methods. The core packages add the concept of user documents stored in the database, and additional packages add secure password authentication, integration with third party login services, and a pre-built user interface.

What is the User Package in Meteor?

This package is the core of Meteor’s developer-facing user accounts functionality. This includes: A users collection with a standard schema, accessed through Meteor.users, and the client-side singletons Meteor.userId () and Meteor.user (), which represent the login state on the client.

Where is user data stored in Meteor?

The Meteor.users collection. Meteor comes with a default MongoDB collection for user data. It’s stored in the database under the name users, and is accessible in your code through Meteor.users. The schema of a user document in this collection will depend on which login service was used to create the account.


3 Answers

The accepted answer has the HOW right, but the WHERE is outdated information. (Yes, this would be better as a comment on the answer, but I can't do that yet.)

From the Meteor 1.2 documentation:

The best way to store your custom data onto the Meteor.users collection is to add a new uniquely-named top-level field on the user document.

And regarding using Meteor.user.profile to store custom information:

🔗Don’t use profile

There’s a tempting existing field called profile that is added by default when a new user registers. This field was historically intended to be used as a scratch pad for user-specific data - maybe their image avatar, name, intro text, etc. Because of this, the profile field on every user is automatically writeable by that user from the client. It’s also automatically published to the client for that particular user.

Basically, it's probably fine to store basic information such as name, address, dob, etc in the profile field, but not a good idea to store anything beyond that as it will, by default, be writeable by the client and vulnerable to malicious users.

like image 29
soisystems Avatar answered Oct 06 '22 20:10

soisystems


Users are special objects in meteor ; you don't want to add fields in the user but in the users profile.

From the doc :

By default the server publishes username, emails, and profile.

If you want to add properties like surname when you create the account, you should use in the Account.onCreateUser server-side hook : http://docs.meteor.com/#accounts_oncreateuser

Accounts.onCreateUser(function(options, user) {
    //pass the surname in the options

    user.profile['surname'] = options.surname

    return user
}

If you want to update a user after, you can do it from the client that way :

Meteor.users.update({_id:Meteor.user()._id}, { $set: {what you want to update} });

By default, the users base will allow that (the current user may update itself). If you don't trust your users and want to ensure that everything is properly update, you can also forbid any updates from the client and make them via a Meteor.call() and proceed to the checkings server-side. But this would be sad.


Edit :

As said in the comments, adding options via the standard account-ui won't be possible. You'll only be able to update the user after the registration. To add options when you subscribe, you'll have to make you own form.

I won't insult you by writing html markup, but here is what you want to have after the submit event (and after the various checking) :

var options = {
    username: $('input#username')[0].value,
    emails: [{
        address: $('input#email')[0].value,
        verified: false
    }],
    password: $('input#password')[0].value,
    profile: {
        surname: $('input#surname')
    },
};
Accounts.createUser( options , function(err){
    if( err ) $('div#errors').html( err.message );
});

You only need the account-base package ; not the account-ui.

Login with the social networks is cake :

Meteor.loginWithFacebook({
    requestPermissions: ['email', 'user_birthday', 'user_location']
}, function(error){loginCallBack(error);});

About the answer ram1 made :

This is not the way meteor works. You do not "POST" a form. You want all your client / server communication done via the websocket. The equivalent of what you are talking about is making a "Meteor.call('myserverfunction', myarguments, mycallback)" of a server method from the client and you pass the arguments you want the server to use.

But this is not the way you will get the best of meteor. There is the philosophy you want to work with :

  1. you have datas in your local mini mongo you got from the server
  2. you update locally those datas in your base / view
  3. meteor do his magic to transmit those updates to the server
  4. there the server can answer : ok, updates saved, this is seamless for you. Or answer : nop ! reverse the changes (and you can implement an error notification system)

(it can answer no because you don't have the permission to update this field, because this update break a rule you did set up...)

All you do is setting permissions and controls on the databases server-side. That way, when an honest client make an update, he sees the result instantly ; way before it has been pushed to the server and send to the other clients. This is latency compensation, one of the seven principles of meteor.

If you modify a data via Meteor.call, you will do that :

  1. send an update to the server
  2. the server checks and update the base
  3. the server send the update to the clients (including you)
  4. your local base updates and your view update => you see your update

=> this is what you had in yesterday app ; meteor allow you to build a today app. Don't apply the old recipes :)

like image 145
fabien Avatar answered Oct 06 '22 20:10

fabien


I had the same problem and managed to do it only with Accounts.createUser:

Accounts.createUser({
    email: email,
    password: password,
    profile: {
            givenName: 'John',
            surname: 'Doe',
            gender: 'M'
        }
}

Thats very simple way and it works. Just add your desired variables in the profile section and it should be ready. Hope it helps someone.

like image 11
Kristiyan Lukanov Avatar answered Oct 06 '22 22:10

Kristiyan Lukanov