2013-06-30 79 views
0

我们的产品是Rails应用程序;认证由Devise和OmniAuth处理。总共约2000个用户。我们最近收到了一些用户无法登录的报告,但我们无法弄清楚原因。没有得到任何服务器错误或我们的生产日志中的任何东西来表明任何错误。Devise/OmniAuth未登录某些用户

让我们看看一些代码...

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.personnil,但一直无法复制。

无论如何,有问题的真实世界用户有完整的模型与完整的关联。向下移动该方法,我们创建一个PersonMeta记录来记录诸如登录页面之类的简单内容。我在Person上以after_create的身份完成了这项工作,但我认为将会话数据传递给模型是不对的。

这不是为我们有问题的用户创建的。在这一点上,我很难过。我不知道如何创建(砰的一声)进去了,但是如果有什么东西坏了,不应该抛出异常吗?事实并非如此。

只有当它是一个人的第一次访问时才被调用 - 后续登录应该绕过它。一个有问题的用户是朋友,所以我一直让他尝试各种其他的东西,包括再次登录,尝试不同的浏览器等,它持续发生

所以,无论如何,花45分钟写入后这篇文章...

其中一个用户通过Twitter取消了对应用程序的访问并重新进行了认证。现在一切正常。

到底是什么?

他的老身份他OAuth凭证等妥善保存。

幸运的是这解决了一个用户,但它显然一直存在的问题。

我们该怎么办?

回答

0

是否有可能在identity.save线Identity.from_omniauth默默地失败?如果是这样,你的after_create挂钩将不会运行,@identity.personnil,你会(无声)重定向。

尝试identity.save!

+0

我不这么认为 - 就像我说的,对于每个受影响的用户,他们都有有效和完整的身份和人员字段=/ –

+0

您是否有任何具有'nil'的PersonMeta' person_id在数据库中? – nickgrim

+0

不是 - 它们要么被正确创建,要么不存在。 –

相关问题