问题 将服务连接到现有的流星帐户


我正在设置一个流星应用程序,涉及用户名和密码注册,然后希望将该帐户与Facebook和Twitter连接。

我的第一部分很容易上手,只需使用帐户包。但是当我有一个登录用户调用Meteor.loginWithFacebook()时,它会将它们记录下来并创建一个新帐户。我想要的是将facebook凭据添加到当前登录用户的内容。

流星文档有这样的:

{
  _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: "cool@example.com", verified: true },
    { address: "another@different.com", 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 }
      ]
    }
  }
}

这似乎是一个帐户,其用户名也通过Facebook验证。但我不确定这是否只是一个你无法用基本的Meteor实现的例子。

我想要做的基本上是

Meteor.connectWithExternalAccount();

它运行与Meteor.loginWithExternalAccount()相同的过程,但只是将信息添加到当前登录的用户。

如果有人可以稍微解释基于帐户的程序包,那么我就可以知道从哪里开始,这将是非常好的。

此外,有谁知道这是否将包含在任何未来版本的Meteor中?


5077
2017-12-05 04:50


起源

github.com/meteor/meteor/pull/1133 - emgee
emgee,看起来像我正在寻找的!问题是,我的'accounts-base'文件夹没有accounts_client.js文件。至少不在我看的地方,这是在项目文件.meteor / local / build / app / packages中 - fnsjdnfksjdb


答案:


所以一直在努力解决这个问题,但不幸的是拉动请求 https://github.com/meteor/meteor/pull/1133 从未合并过。可能你最好的选择是检查流星核心的Google网上论坛,看看是否有任何评论,如果没有,看看你是否可以得到一个核心开发者来评论它。

如果您仍想使用拉取请求,您可以做的是删除各种Meteor accounts-* 然后在项目的根目录中创建一个 /packages 文件夹和副本yubozhao的补丁 accounts-* 那里的包裹(可能很聪明地附加 -custom)。你那时候 meteor add accounts-base-custom等,将它们添加到您的项目中。

但是请注意,yubozhao在6-7个月之前写道,你可能需要坚持使用当前流行的任何版本的Meteor来实现它。

2014年4月更新: 现在有一个Atmosphere包,它有一个可能有用的类似用例: https://atmospherejs.com/package/accounts-merge


3
2017-12-15 01:03



我将尝试将pull请求中的文件克隆到一个包中,并希望它能够正常工作。如果没有,我想我会试着仔细阅读并找出过去六个月里发生的事情。我在流星谷歌小组中找不到任何关于它的讨论。 - fnsjdnfksjdb
我根本无法使用这种技术。还有其他想法吗? - fnsjdnfksjdb
当拉动请求最初编写时,Meteor的当前版本是0.6.4 - 可能会尝试 meteor run --release 0.6.4 并看看你是否可以在该版本中使用它。 - emgee
我确实尝试过。我认为问题来自于有两个关于Accounts对象的软件包。甚至无法让Meteor.linkWithFacebook存在于客户端上。 - fnsjdnfksjdb
您是否删除了Meteor Accounts软件包?并且只使用yubozhao的补丁包?同样重要的是,我从未尝试过修补过的,所以不知道它们是否有效。 - emgee


这是一个适合我的代码(在服务器文件夹内):

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
                    }
                }
            });
        }
    }

在客户端js文件夹中:

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);
                    }
                });
            });
    }
}

};

模板事件中的相同js文件:

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

并为html刚做完这个:

<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>

主要是您需要将数据服务设置为您的服务,然后模板单击事件接受数据服务并执行addUserService(数据传递)。

希望它能奏效,请告诉我。


6
2017-12-15 09:01



这取决于在注册时获取用户电子邮件,对吗?它不适用于Twitter,因为你无法通过api获得Twitter用户的电子邮件。这不适合我的用例,因为我没有要求注册电子邮件和Twitter非常重要。 - fnsjdnfksjdb
是的,它从用户收到电子邮件的rilies,我不知道twitter,但似乎正确的行为基于电子邮件地址显然是因为它的uniqe。 - Boaz Hoch
我希望得到的答案只是使用用户已登录帐户的事实选择要添加到哪个帐户。 - fnsjdnfksjdb
我不完全明白。您是否希望向已经放入的用户添加更多帐户服务?如果是这种情况,可以通过检查Meteor.userid()并将数据推送到他的user-> profile-> services来轻松完成 - Boaz Hoch
我需要使用Meteor.loginWithFacebook()创建的数据,但我不能在不丢失userId的情况下获得 - fnsjdnfksjdb