所以Meteor有这个很棒的帐户包,可以通过密码或其他服务轻松登录.但是,我目前正在创建一个需要多种服务的网络服务(facebook/twitter/etc).此处的链接:如何将外部服务登录添加到Meteor中现有的帐户?通过创建重复的帐户并仅合并数据来建议"黑客",但对我来说似乎非常不满意.
所以我的问题是:
谢谢你的帮助.
Xiv*_*Xiv 27
我通过逆向工程accounts-oauth-X包解决了这个问题!处理所有边缘情况的最佳解决方案是有一个用于登录的故事,另一个用于显式关联.以下是用文字coffeescript编写的解决方案.
确保您拥有所需的包:
meteor add google
meteor add facebook
meteor add oauth
Run Code Online (Sandbox Code Playgroud)
如果他们拥有相同的电子邮件,则会自动加入帐户.最适合登录,因为它很强大.但是,对于显式关联不好,因为如果电子邮件地址不同,那么它将无效.(并且手动合并会将用户注销并强制您重新登录).要明确关联帐户,即使它有不同的电子邮件,请参阅下面的解决方案.
Accounts.onCreateUser (options, user) ->
user.city = null
user.networks = []
user.attending =[]
user.profile ?= {}
Run Code Online (Sandbox Code Playgroud)
如果用户通过oauth服务注册,我们需要采取额外的逻辑,以便我们可以标准化名称和电子邮件的位置.
if user.services?
service = _.keys(user.services)[0]
Run Code Online (Sandbox Code Playgroud)
检查是否有任何现有帐户已与该服务关联的电子邮件.如果是这样,只需将用户信息合并到.
email = user.services[service].email
if email?
oldUser = Meteor.users.findOne({"emails.address": email})
Run Code Online (Sandbox Code Playgroud)
确保旧帐户具有所需的服务对象.
if oldUser?
oldUser.services ?= {}
if service == "google" or service == "facebook"
Run Code Online (Sandbox Code Playgroud)
将新服务密钥合并到我们的旧用户中.我们还会检查是否有新的电子邮件要添加到我们的用户.然后从数据库中删除旧用户,然后再次返回以直接再次创建它.将要创建的假定新用户被丢弃.
oldUser.services[service] = user.services[service]
Meteor.users.remove(oldUser._id)
user = oldUser
Run Code Online (Sandbox Code Playgroud)
否则只需正常创建用户,标准化电子邮件和名称字段.
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
Run Code Online (Sandbox Code Playgroud)
这会将服务添加到用户记录上的服务哈希,就像它是由内置哈希系统创建的一样.代码需要是客户端(获取服务oauth令牌)和部分服务器端(进行进一步的API调用以获取用户数据并将其与用户记录相关联)
此功能是在我们的帐户中添加功能的入口点.
addUserService = (service) ->
Run Code Online (Sandbox Code Playgroud)
如果他们选择电子邮件,我们需要使用Meteor的内置电子邮件验证系统.
if service == "email"
else
switch service
Run Code Online (Sandbox Code Playgroud)
对于标准的oauth服务,我们在客户端请求凭据,然后将它们传递给服务器以进行进一步的API调用以收集必要的信息并将该信息添加到我们的帐户.
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)
Run Code Online (Sandbox Code Playgroud)
我们只需要设置一个简单的绑定将它粘合在一起.
Template.userAddServices.events
"click button": (e) ->
e.preventDefault()
service = $(event.target).data("service")
addUserService(service)
Run Code Online (Sandbox Code Playgroud)
在这里,我们定义与用户模型相关的服务器端方法.
Meteor.methods
Run Code Online (Sandbox Code Playgroud)
这将从客户端传递数据,后者已经获取了访问令牌.使用令牌发现有关该服务上用户的其余信息.然后检查该帐户是否已经注册,如果没有 - 将其添加到当前帐户.
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 }})
Run Code Online (Sandbox Code Playgroud)
我们也可以通过此帐户发送电子邮件.如果它还没有在当前用户上,我们可以抓住并添加它.
if not _.contains(Meteor.user().emails, data.email)
Meteor.users.update(userId, {$push: {"emails": {address: data.email, verified: true} }})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5478 次 |
| 最近记录: |