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

Posted

技术标签:

【中文标题】将服务连接到现有的流星帐户【英文标题】:Connect service to existing meteor account 【发布时间】:2013-12-21 21:40:22 【问题描述】:

我正在设置一个流星应用程序,其中涉及使用用户名和密码进行注册,然后希望将该帐户与 facebook 和 twitter 连接。

我的第一部分很容易启动并运行,只需使用 accounts 包。但是当我有一个登录用户调用 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() 运行相同的过程,但只是将信息添加到当前登录的用户。

如果有人能稍微解释一下accounts-base包,这样我就可以知道从哪里开始,那就太好了。

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

【问题讨论】:

github.com/meteor/meteor/pull/1133 emgee,这看起来像我要找的东西!问题是,我的“accounts-base”文件夹没有 accounts_client.js 文件。至少不是我在看的地方,在项目文件 .meteor/local/build/app/packages 【参考方案1】:

这是对我有用的代码(在服务器文件夹内):

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>

主要是你需要为你的服务设置data-service,然后模板点击事件获取data-service并执行addUserService(data-passed)。

希望它会起作用,请告诉我。

【讨论】:

这依赖于在注册时获取用户电子邮件,对吗?而且它不适用于 twitter,因为您无法通过 api 获取 twitter 用户的电子邮件。这不适合我的用例,因为我在注册时不要求提供电子邮件,而 Twitter 非常重要。 是的,它依赖于从用户那里获取电子邮件,我不知道 twitter,但显然基于电子邮件地址采取行动似乎是正确的,因为它是唯一的。 我希望得到一个答案,该答案仅使用用户已经登录帐户的事实来选择要添加到的帐户。 我不太明白。您希望为已登录的用户添加更多帐户服务?如果是这种情况,可以通过检查 Meteor.userid () 轻松完成并将数据推送到他的用户->个人资料->服务 我需要使用 Meteor.loginWithFacebook() 创建的数据,但如果不丢失 userId 就无法获得这些数据【参考方案2】:

所以已经有解决这个问题的工作,但不幸的是,拉取请求 https://github.com/meteor/meteor/pull/1133 从未被合并。可能你最好的选择是检查流星核心谷歌群组,看看是否有任何评论,如果没有,看看你是否可以让核心开发人员评论它。

如果你还想继续使用 pull request,你可以做的是删除各种 Meteor accounts-* 包,然后在你的项目的根目录下,创建一个 /packages 文件夹并将 yubozhao 修补的 accounts-* 包复制到那里(可能很聪明地追加-custom)。然后,您需要 meteor add accounts-base-custom 等将它们添加到您的项目中。

请注意,yubozhao 是在 6 到 7 个月前写的,您可能需要坚持使用当时最新的 Meteor 版本才能正常工作。

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

【讨论】:

我会尝试将拉取请求中的文件克隆到一个包中,并希望它能正常工作。如果没有,我想我会尝试通读它并找出过去六个月中出现的问题。我在流星谷歌组中找不到任何讨论。 我根本无法使用这种技术。还有其他想法吗? 在最初编写拉取请求时,Meteor 的当前版本是 0.6.4 — 可以尝试 meteor run --release 0.6.4 看看是否可以让它在该版本中工作。 我确实尝试过。我认为问题出在有两个关于 Accounts 对象或其他内容的包。甚至无法让 Meteor.linkWithFacebook 存在于客户端。 您是否删除了库存的 Meteor Accounts 包?并且只使用yubozhao的补丁包?顺便说一句,我从来没有真正尝试过修补的,所以不知道它们是否有效。

以上是关于将服务连接到现有的流星帐户的主要内容,如果未能解决你的问题,请参考以下文章

如何防止流星重新连接到服务器

将 phpmyadmin 连接到现有的数据库服务器

如何使用证书将 gitlab 连接到现有的 kubernetes 集群

流星 SSL 连接

如何使用服务帐户将 .net 应用程序连接到数据库

将 spark 应用程序连接到远程 sql 服务器时出现 jdbc 连接超时错误