Evanss
Evanss

Reputation: 23183

How to normalise user data from varying structures in Meteor?

Users in my Meteor app can create accounts 'manually' or with the accounts-facebook package.

If they create an account manually then in the database their email is stored like this:

emails: [address: '[email protected]', verified: false]

But if they use the Facebook login then its stored like this:

services: {
  facebook: {
    email: "[email protected]"
  }
}

I have an user account page where I need to display the users email and allow them to change it. How can I deal with the varying structure?

I made this React component to display the users email. When I just had the default Meteor user profiles it worked, but now Ive added Facebook login it errors as props.user.emails doenst exist.

        <div className="form-primary__row">
          <label>Email:</label>
          {props.user.emails.map((item, i) => {
            return (
              <input defaultValue={item.address} key={i} name="email" />
            );
          })}
        </div>

This is my method for a user to update their email. It also worked when I just had Meteors accounts but won't work with Facebook.

Meteor.methods({
  'user.updateEmail'({ email }) {
    Meteor.users.update(
      { _id: Meteor.userId() },
      {
        $set: {
          'emails.0.address': email,
          'emails.0.verified': false,
        },
      },
    );
  },
});

Upvotes: 1

Views: 37

Answers (1)

blueren
blueren

Reputation: 2870

One approach is to use Accounts.onCreated()

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.

Accounts.onCreateUser(function (options, user) {
    // if the account is created using the manual approach,
    // simply return the user object that will be inserted into
    // the Users collection.
    if (!user.services.facebook) {
        return user;
    }

    // if user is created using fb's API,
    // manually set the emails array, then return the user object
    // which will be inserted into the Users collection.
    user.username = user.services.facebook.name;
    user.emails = [{address: user.services.facebook.email}];

    return user;
});

The above ensures that the emails array always contains the email, whichever the login method the user chooses to use.

Upvotes: 1

Related Questions