Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connect service to existing meteor account

I am setting up a meteor app that involves signing up with a username and password, then hopefully connecting that account with facebook and twitter.

I have the first part up and running easily, just with the accounts package. But when I have a logged in user call Meteor.loginWithFacebook(), it logs them out and creates a new account. What I want is something that adds the facebook credentials to the currently logged in user.

The meteor docs have this:

{
  _id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f",  // Meteor.userId()
  username: "cool_kid_13", // unique name
  emails: [
    // each email address can only belong to one user.
    { address: "[email protected]", verified: true },
    { address: "[email protected]", verified: false }
  ],
  createdAt: Wed Aug 21 2013 15:16:52 GMT-0700 (PDT),
  profile: {
    // The profile is writable by the user by default.
    name: "Joe Schmoe"
  },
  services: {
    facebook: {
      id: "709050", // facebook id
      accessToken: "AAACCgdX7G2...AbV9AZDZD"
    },
    resume: {
      loginTokens: [
        { token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
          when: 1349761684048 }
      ]
    }
  }
}

which appears to be an account with a username that's also authenticated with Facebook. But I'm not sure if that's just an example that you can't actually achieve with basic Meteor stuff.

What I am trying to make is basically

Meteor.connectWithExternalAccount();

which runs the same process as Meteor.loginWithExternalAccount(), but just adds the information to the currently logged in user.

If someone could just explain the accounts-base package a bit so I could know where to start for myself that would be great.

Also, does anyone know if this will be included in any future versions of Meteor?

like image 930
fnsjdnfksjdb Avatar asked Dec 05 '13 04:12

fnsjdnfksjdb


People also ask

What is the name of the package that provides basic user accounts functionality?

`accounts-base` This package is the core of Meteor's developer-facing user accounts functionality.

What is the purpose of the Loginbuttons template?

The login function adds a login button on the template when displayed in a browser. Here it the format of the login function. This tag is responsible for displaying the following buttons on the Web page.


1 Answers

Here is a code that worked for me ( inside server folder ):

Accounts.onCreateUser(function(options, user) {
    var email, oldUser, service;
    /*
    user.groups = {
        created: "",
        invited:"",
        RSVP:{
            coming:"",
            notComing:"",
            noReplay:""
        }
    };
    */
    if (user.profile == null) {
        user.profile = options.profile
    }
    if (user.services != null) {
        service = _.keys(user.services)[0];
        email = user.services[service].email;
        if (email != null) {
            oldUser = Meteor.users.findOne({
                "emails.address": email
            });
            if (oldUser != null) {
                if (oldUser.services == null) {
                    oldUser.services = {};
                }
                if (service === "google" || service === "facebook") {
                    oldUser.services[service] = user.services[service];
                    Meteor.users.remove(oldUser._id);
                    user = oldUser;
                }
            } else {
                if (service === "google" || service === "facebook") {
                    if (user.services[service].email != null) {
                        user.emails = [
                            {
                                address: user.services[service].email,
                                verified: true
                            }
                        ];
                    } else {
                        throw new Meteor.Error(500, "" + service + " account has no email attached");
                    }
                    user.profile.name = user.services[service].name;
                }
            }
        }
    }
    return user;
});

userAddOauthCredentials: function(token, userId, service) {
        var data, oldUser, selector, updateSelector;
        switch (service) {
            case "facebook":
                data = Facebook.retrieveCredential(token).serviceData;
                break;
            case "google":
                data = Google.retrieveCredential(token).serviceData;
        }
        selector = "services." + service + ".id";
        oldUser = Meteor.users.findOne({
            selector: data.id
        });
        if (oldUser != null) {
            throw new Meteor.Error(500, ("This " + service + " account has already") + "been assigned to another user.");
        }
        updateSelector = "services." + service;
        Meteor.users.update(userId, {
            $set: {
                updateSelector: data
            }
        });
        if (!_.contains(Meteor.user().emails, data.email)) {
            return Meteor.users.update(userId, {
                $push: {
                    "emails": {
                        address: data.email,
                        verified: true
                    }
                }
            });
        }
    }

inside client js folder :

var addUserService;

addUserService = function(service) {
    if (service === "email") {
} else {
    switch (service) {
        case "facebook":
            return Facebook.requestCredential({
                requestPermissions: ["email", "user_friends", "manage_notifications"]
            }, function(token) {
                return Meteor.call("userAddOauthCredentials", token, Meteor.userId(), service, function(err, resp) {
                    if (err != null) {
                        return Meteor.userError.throwError(err.reason);
                    }
                });
            });
        case "google":
            return Google.requestCredential({
                requestPermissions: ["email", "https://www.googleapis.com/auth/calendar"],
                requestOfflineToken: true
            }, function(token) {
                return Meteor.call("userAddOauthCredentials", token, Meteor.userId(), service, function(err, resp) {
                    if (err != null) {
                        return Meteor.userError.throwError(err.reason);
                    }
                });
            });
    }
}

};

same js file inside template events:

"click a": function(e) {
       var service;
        e.preventDefault();
        service = $(event.target).data("service");
        return addUserService(service);
    }

and for the html just done this:

<div class="social"><a id="fb" data-service="facebook"><img src="/../facebook.png"></a></div>
    <div class="social"><a id="go" data-service="google"><img src="/../googleplus.png"></a></div>

mainly you need to have the data-service set to your service, then the template click event takes the data-service and execute the addUserService(data-passed).

hope it will work, please let me know.

like image 122
Boaz Hoch Avatar answered Oct 05 '22 22:10

Boaz Hoch