使用“流星帐户"包链接多个服务 [英] Using Meteor Accounts package to link multiple services

查看:53
本文介绍了使用“流星帐户"包链接多个服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,Meteor具有出色的Accounts程序包,可通过密码或其他服务轻松登录.但是,我当前正在创建一个需要多个服务(facebook/twitter/etc)的网络服务.此处的链接:如何将外部服务登录名添加到Meteor中已经存在的帐户中?通过创建重复的帐户并仅合并数据来建议黑客入侵",但是对我来说似乎并不令人满意.

So Meteor has this great Accounts package which allows for easy login via password or other services. However, I'm currently creating a web service with multiple services required (facebook / twitter / etc). The link here: How to add External Service logins to an already existing account in Meteor? suggests a "hack" by creating duplicate accounts and just merging the data, but it seems very unsatisfactory to me.

所以我的问题是:

感谢您的帮助.

推荐答案

已解决!

我已经通过反向工程accounts-oauth-X软件包解决了这个问题!处理所有极端情况的最佳解决方案是为登录创建一个故事,为显式关联创建另一个故事.这是用识字的咖啡脚本编写的解决方案.

Solved!

I've solved the problem by reverse engineering the accounts-oauth-X packages! The optimal solution that handles all the edge cases is to have one story for logins, and another for explicit associations. Here are the solutions written up in literate coffeescript.

确保您具有必需的软件包:

Make sure you have the required packages:

meteor add google
meteor add facebook
meteor add oauth

进行多服务登录的方法:

如果帐户具有相同的电子邮件,它将自动加入帐户.最好用于登录,因为它很健壮.但是,这对于显式关联不利,因为如果电子邮件地址不同,则它将无法正常工作. (并且手动合并将注销用户并迫使您重新登录).要明确关联帐户,即使该帐户有其他电子邮件,也请参阅下面的解决方案.

Accounts.onCreateUser (options, user) ->
  user.city = null
  user.networks = []
  user.attending =[]
  user.profile ?= {}

如果用户通过oauth服务注册,我们需要采取额外的逻辑,以便 我们可以标准化姓名和电子邮件的位置.

We need to act extra logic if the user registered via an oauth service, so that we can standardize the location of name and email.

  if user.services?
    service = _.keys(user.services)[0]

检查现有帐户是否已有与该帐户相关联的电子邮件 服务.如果是这样,只需合并用户信息即可.

Check if any existing account already has the email associated with the service. If so, just incorporate the user information in.

    email = user.services[service].email
    if email?
      oldUser = Meteor.users.findOne({"emails.address": email})

确保旧帐户具有必需的服务对象.

Make sure the old account has the required services object.

      if oldUser?
        oldUser.services ?= {}
        if service == "google" or service == "facebook"

将新服务密钥合并到我们的旧用户中.我们还会检查是否有新的 电子邮件添加到我们的用户.然后从数据库中删除旧用户,然后 再次返回即可直接创建它.假定的新用户 被创建会被丢弃.

Merge the new service key into our old user. We also check if there are new emails to add to our user. Then delete the old user from the DB, and just return it again to create it again directly. The supposed new user that was to be created is discarded.

          oldUser.services[service] = user.services[service]
          Meteor.users.remove(oldUser._id)
          user = oldUser

否则,只需正常创建用户,即可标准化电子邮件和姓名字段.

Otherwise just create the user as normal, standardizing the email and name fields.

      else
        if service == "google" or service == "facebook"
          if user.services[service].email?
            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

显式关联方法:

这会将服务添加到用户记录上的服务哈希中,就像由内置哈希系统创建的一样.该代码需要在客户端(以获取服务oauth令牌),在服务器端(以进行进一步的API调用以获取用户数据并将其与用户记录相关联)

此功能是向我们的帐户添加功能的切入点.

This function is the entrypoint to adding functions onto our account.

addUserService = (service) ->

如果他们选择电子邮件,我们需要使用Meteor的内置电子邮件验证系统.

We need to use Meteor's built in email verification system if they choose email.

  if service == "email"

  else
    switch service

对于标准的oauth服务,我们在客户端请求凭据,并且 然后将它们传递给服务器以进行进一步的API调用以收集 必要的信息并将其添加到我们的帐户中.

For standard oauth services, we request the credentials on the client side, and then pass them off to the server to do the further API calls to gather the requisite information and to add that information to our account.

      when "facebook"
        Facebook.requestCredential(
          requestPermissions: ["email", "user_friends", "manage_notifications"],
        , (token) ->
          Meteor.call "userAddOauthCredentials", token, Meteor.userId(), service, (err, resp) ->
            if err?
              Meteor.userError.throwError(err.reason)
        )
      when "google"
        Google.requestCredential
          requestPermissions: ["email", "https://www.googleapis.com/auth/calendar"]
          requestOfflineToken: true,
        , (token) ->
          Meteor.call "userAddOauthCredentials", token, Meteor.userId(), service, (err, resp) ->
            if err?
              Meteor.userError.throwError(err.reason)

我们只需要设置一个简单的绑定即可将其粘合在一起.

we just need to set up a simple binding to glue it together.

Template.userAddServices.events
  "click button": (e) ->
    e.preventDefault()
    service = $(event.target).data("service")
    addUserService(service)

服务器端代码:

我们在这里定义与用户模型相关的服务器端方法.

Server-side code:

Here we define server side methods related to the user model.

Meteor.methods

这将从客户端传递数据,该数据获取了访问令牌 已经.使用令牌发现有关用户的其余信息 在该服务上.然后,它检查该帐户是否已经注册, 否则-将其添加到当前帐户中.

This gets passed the data from the clientside, which grabbed the access token already. Uses the token to discover the rest of the information about the user on that service. It then checks to see if that account is already registered, and if not - adds it to the current account.

  userAddOauthCredentials: (token, userId, service) ->
    switch service
      when "facebook"
        data = Facebook.retrieveCredential(token).serviceData
      when "google"
        data = Google.retrieveCredential(token).serviceData

    selector = "services.#{service}.id"
    oldUser = Meteor.users.findOne({selector: data.id})
    if oldUser?
      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 }})

我们还可以浏览此帐户发送的电子邮件.如果尚未在 当前用户,我们可以抓取并添加它.

We can also gleam at the email from this account. If it isn't already on the current user, we can grab it and add it.

    if not _.contains(Meteor.user().emails, data.email)
      Meteor.users.update(userId, {$push: {"emails": {address: data.email, verified: true} }})

这篇关于使用“流星帐户"包链接多个服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆