我们的产品是Rails应用程序;身份验证由Devise和OmniAuth处理。总共~2000个用户。我们最近有一些用户无法登录的报告,但我们无法弄清楚原因。没有任何服务器错误或我们的生产日志中的任何内容提出任何建议都是错误的。
让我们看看一些代码......
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
...
def twitter
oauthorize "twitter"
end
private
def oauthorize(provider)
if env['omniauth.auth']
@identity = Identity.from_omniauth(env['omniauth.auth'])
@person = @identity.person
# 1. failing here? Maybe?
if @person
PersonMeta.create_for_person(@person, session[:referrer], session[:landing_page]) if @person.first_visit?
# 2. PersonMetas *aren't* being created.
flash[:notice] = I18n.t("devise.omniauth_callbacks.success", kind: provider)
sign_in_and_redirect(@person, :event => :authentication)
# 3. Definitely failing by here…
else
redirect_to root_url
end
else
redirect_to root_url
end
end
end
class Identity < ActiveRecord::Base
belongs_to :person, counter_cache: true, touch: true
after_create :check_person
def self.from_omniauth(auth)
where(auth.slice("provider", "uid")).first_or_initialize.tap do |identity|
identity.oauth_token = auth['credentials']['token']
identity.oauth_secret = auth['credentials']['secret']
case auth['provider']
when "twitter"
identity.name = auth['info']['name']
identity.nickname = auth['info']['nickname']
identity.bio = auth['info']['description']
identity.avatar_address = auth['info']['image']
else
raise "Provider #{provider} not handled"
end
identity.save
end
end
def check_person
if person_id.nil?
p = create_person(nickname: nickname, name: name, remote_avatar_url: biggest_avatar)
p.identities << self
end
end
def biggest_avatar
avatar_address.gsub('_bigger', '').gsub('_normal', '') if avatar_address
end
end
class PersonMeta < ActiveRecord::Base
attr_accessible :landing_page, :mixpanel_id, :referrer_url, :person_id
belongs_to :person
def self.create_for_person(person, referrer, landing_page)
PersonMeta.create!(referrer_url: referrer, landing_page: landing_page, person_id: person.id)
end
end
所以我们有这个,我们在生产中没有任何错误。
我们从哪里开始?好吧,让我们看看失败点是否是Identity.from_omniauth
此方法搜索现有标识(我们为更多提供程序编写了额外代码,但尚未在客户端实现)。如果未找到任何标识,则会创建一个标识,然后创建关联的Person模型。如果这是失败的原因,我们将能够在生产控制台中看到一些可疑的空字段。但不 - 人与人所有标识模型都使用所有正确的字段创建,并且应用程序的相关位已经看到它们(例如,它们的“用户配置文件页面”都已创建)。
我刚刚在if @person
添加了#oauthorize - 我们有一个500 @identity.person
nil
,但无法复制。
无论如何,有问题的真实用户做拥有完整的关联模型。向下移动该方法,我们创建一个PersonMeta
记录来记录简单的内容,如登录页面。我已经在after_create
上以Person
完成了此操作,但我认为将会话数据传递给模型是不对的。
这不是为有问题的用户创建的。在这一点上,我有点难过。我不确定创建!(带有爆炸声)是如何进入的,但如果某事被破坏,这不应该抛出异常吗?事实并非如此。
只有当这是一个人的第一次访问时才会被调用 - 后续登录应绕过它。其中一个有问题的用户是朋友,所以我一直让他尝试各种其他的东西,包括再次登录,尝试不同的浏览器等,并且一直在发生
其中一位用户通过Twitter撤销了对该应用的访问权限并重新进行了身份验证。现在一切都有效。
到底是什么?
他的旧身份 他的OAuth令牌等正确存储。
幸运的是,一个用户已经解决了这个问题,但这显然是一个持续存在的问题。
我们做什么?
答案 0 :(得分:0)
identity.save
中的Identity.from_omniauth
行是否可能无声地失败?如果是这样,您的after_create
挂钩将无法运行,@identity.person
将为nil
,您只会(默默地)重定向。
试试identity.save!
?