为没有STI的多个模型设计Omniauth

时间:2012-07-02 00:00:10

标签: ruby-on-rails devise omniauth

有没有办法为没有STI的多个模型配置Devise Omniauth?

我们有模特学生和教授,我们不想使用STI,但现在我们意识到Devise with Omniauth不适合多种模式。

.rvm/gems/ruby-1.9.3-p125/gems/devise-2.1.0/lib/devise/rails/routes.rb:384:in `devise_omniauth_callback': Wrong OmniAuth configuration. If you are getting this exception, it means that either: (RuntimeError)

1) You are manually setting OmniAuth.config.path_prefix and it doesn't match the Devise one
2) You are setting :omniauthable in more than one model
3) You changed your Devise routes/OmniAuth setting and haven't restarted your server

4 个答案:

答案 0 :(得分:3)

您好我来到这里有类似的问题,我遇到了这个解决方案,也许我会帮助下一个。 在我的情况下,我有两个设计模型,我以不同的方式使用omniauth,我的第一个模型是一个用户可以使用普通设计注册或使用omniauth,第二个是艺术家,他只需要定期注册唱歌形式,但我仍然需要omniauth来验证来自twitter的值,经过验证的字段(对twitters配置文件的一点检查,这意味着如果一个着名的用户真的是那个人)。

因此,当我来到时,我不能拥有两个设计的omniauthable模型,我只是决定使用相同的omniauth。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def all
    if artist_signed_in? and session["devise.authorize"] == current_artist.email
      session["devise.authorize"] = nil
      if current_artist.artist_profile.update_from_omniauth(request.env["omniauth.auth"])
        if current_artist.artist_profile.verified
          flash[:notice] = "You were verified"
        else
          flash[:alert] = "Twitter go well but you aren't verified there"
        end
        redirect_to edit_artist_profile_path(current_artist.artist_profile)
      else
        flash[:error] = "We can't connect with #{request.env["omniauth.auth"].provider.titleize.split(" ").first}"
        redirect_to edit_artist_profile_path(current_artist.artist_profile)
      end
    elsif !user_signed_in?
      user = User.from_omniauth(request.env["omniauth.auth"])
      if user.persisted?
        flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => user.provider.titleize.split(" ").first
        user.user_profile.from_omniauth(request.env["omniauth.auth"])
        sign_in_and_redirect user, :event => :authentication
      else
        session["count_errors"] = 0 if session["devise.user_attributes"] == nil
        session["devise.user_attributes"] = user.attributes
        redirect_to new_user_registration_url
      end
    else
      flash[:notice] = "You are already log in #{current_user.email}"
      redirect_to root_path
    end
  end

  def after_omniauth_failure_path_for(scope)
    if artist_signed_in? and session["devise.authorize"] == current_artist.email
      session["devise.authorize"] = nil
      edit_artist_profile_path(current_artist.artist_profile)
    else
      super
    end
  end

  alias_method :twitter, :all
end

对于第一种情况,普通用户,我们有

elsif !user_signed_in?

它将执行正常的过程,一切都像每个指南一样,但对于第二种情况(经过验证的字段和艺术家配置文件),我发送一个带有一些随机值的会话

session["devise.authorize"]

我用我的艺术家个人资料控制器

用新路线调用链接
<%= link_to "Verify with Twitter", artist_profiles_integrate_twitter_path %>

加载会话并重定向到用户omniauth路径

class ArtistProfilesController < ApplicationController
   ...
   def integrate_twitter
      session["devise.authorize"] = current_artist.email
      redirect_to user_omniauth_authorize_path(:twitter)
   end
 end

然后我在每个类中定义了几个方法来处理omniauth,第一个创建用户(基于railscast剧集“devise-omniauth-revised”),第二个只是更新我的艺术家档案模型上的字段,你应该覆盖after_omniauth_failure_path_for(范围),这只返回登录失败的路径,使用相同的技术更改后错误路径(例如,无法连接到Twitter时,它将重定向到用户注册路径,以及会话将会有一段时间)我们可以有正常的行为,并在所有情况下清理会话。

希望有所帮助,问候!

答案 1 :(得分:2)

目前,Devise的Omniauthable模块不适用于多种型号。不用担心,因为Omniauthable模块只是OmniAuth的简单包装。

https://github.com/plataformatec/devise/wiki/OmniAuth-with-multiple-models

答案 2 :(得分:1)

我认为而不是将:omniauthable写入个人Student&amp; Professor model。您应该生成第三个模型,例如Omniuser,并为其添加:omniauthable设置。

class Student < ActiveRecord::Base
  has_one :omniuser
end

class Professor < ActiveRecord::Base
  has_one :omniuser
end

答案 3 :(得分:1)

目前,Devise的Omniauthable模块不适用于多种型号。 (https://github.com/plataformatec/devise/wiki/OmniAuth-with-multiple-models) 简而言之,你需要停止依靠设计通过“omniauthable”来实现它的魔力,并且手动完成。它并不复杂,一旦你得到第一个模型来处理middelware,那么很明显如何扩展多个模型,因为它归结为完全相同的代码,只有不同的模型名称。

需要的步骤:

  1. 从devise.rb和使用的模型中删除omniauthable和devise omniauth设置
  2. 将oauth作为middelware包含在内(因此您可以在它遇到Rails之前捕获请求)
  3. 编写手动路线 - 轻松自如
  4. 处理响应 - 使用与您现在相同的代码
  5. 处理故障情况(在oauth提供商处拒绝) - middelware设置中的另一个阻止
  6. 我解决了类似的问题,我在这里有详细解释:https://blog.kodius.io/2016/12/20/devise-omniauth-multiple-models/ 中间件oauth设置代码在这里:https://github.com/kodius/oauth-example-multiple-models