行动' linkedin'无法找到OmniauthCallbacksController

时间:2014-07-21 00:38:02

标签: ruby-on-rails ruby-on-rails-4 devise routes omniauth

我有一个应用程序,我正在尝试使用twitter,linkedin和facebook添加身份验证以及使用设计我的自定义身份验证

我的 Gemfile 如下

gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-linkedin'
gem 'omniauth-twitter'
gem 'oauth2'
gem 'figaro'

我正在使用设计3.2.4

我有一个 user.rb 模型,如下所示

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook, :twitter, :linkedin]

  TEMP_EMAIL_PREFIX = 'change@me'
  TEMP_EMAIL_REGEX = /\Achange@me/

  validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update

  def self.find_for_oauth(auth, signed_in_resource = nil)

    # Get the identity and user if they exist
    identity = Identity.find_for_oauth(auth)

    # If a signed_in_resource is provided it always overrides the existing user
    # to prevent the identity being locked with accidentally created accounts.
    # Note that this may leave zombie accounts (with no associated identity) which
    # can be cleaned up at a later date.
    user = signed_in_resource ? signed_in_resource : identity.user

    # Create the user if needed
    if user.nil?

      # Get the existing user by email if the provider gives us a verified email.
      # If no verified email was provided we assign a temporary email and ask the
      # user to verify it on the next step via UsersController.finish_signup
      email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
      email = auth.info.email if email_is_verified
      user = User.where(:email => email).first if email

      # Create the user if it's a new registration
      if user.nil?
        user = User.new(
          username: auth.extra.raw_info.name,
          #username: auth.info.nickname || auth.uid,
          email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
          password: Devise.friendly_token[0,20]
        )
        user.skip_confirmation!
        user.save!
      end
    end

    # Associate the identity with the user if needed
    if identity.user != user
      identity.user = user
      identity.save!
    end
    user
  end

  def email_verified?
    self.email && self.email !~ TEMP_EMAIL_REGEX
  end
end

我的 identity.rb 如下

class Identity < ActiveRecord::Base
  belongs_to :user

  validates_presence_of :uid, :provider
  validates_uniqueness_of :uid, :scope => :provider

  def self.find_for_oauth(auth)
    identity = find_by(provider: auth.provider, uid: auth.uid)
    identity = create(uid: auth.uid, provider: auth.provider) if identity.nil?
    identity
  end
end

users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, :finish_signup
  before_filter :ensure_signup_complete, only: [:new, :create, :update, :destroy]

  def finish_signup
    if request.patch? && params[:user] #&& params[:user][:email]
      if current_user.update(user_params)
        current_user.skip_reconfirmation!
        sign_in(current_user, :bypass => true)
        redirect_to current_user, notice: 'Your profile was successfully updated.'
      else
        @show_errors = true
      end
    end
  end

  private
    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      accessible = [ :username, :email ] # extend with your own params
      accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
      params.require(:user).permit(accessible)
    end
end

omniauth_callbacks_controller.rb

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
    def self.provides_callback_for(provider)
      class_eval %Q{
        def #{provider}
          @user = User.find_for_oauth(env["omniauth.auth"], current_user)

          if @user.persisted?
            sign_in_and_redirect @user, event: :authentication
            set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
          else
            session["devise.#{provider}_data"] = env["omniauth.auth"]
            redirect_to new_user_registration_url
          end
        end
      }
    end

    [:twitter, :facebook, :linked_in].each do |provider|
      provides_callback_for provider
    end

    def after_sign_in_path_for(resource)
      if resource.email_verified?
        super resource
      else
        finish_signup_path(resource)
      end
    end
end

/config/routes.rb

  devise_for :users, :controllers => { omniauth_callbacks: 'omniauth_callbacks' }

  match '/profile/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup
  get 'home/index'
  root to: "home#index"

配置/初始化/ devise.rb

Devise.setup do |config|
  config.omniauth :facebook, ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"]
  config.omniauth :twitter, ENV["TWITTER_KEY"], ENV["TWITTER_SECRET"]
  config.omniauth :linked_in, ENV["LINKEDIN_KEY"], ENV["LINKEDIN_SECRET"]

  ...
end

application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  def ensure_signup_complete
    # Ensure we don't go into an infinite loop
    return if action_name == 'finish_signup'

    # Redirect to the 'finish_signup' page if the user
    # email hasn't been verified yet
    if current_user && !current_user.email_verified?
      redirect_to finish_signup_path(current_user)
    end
  end
end

我尝试将 routes.rb 更改为

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }

从我的应用程序的根目录

mkdir app / controllers / users mv app / controllers / omniauth_callbacks_controller.rb app / controllers / users

然后我从

更改了omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

在我的routes.rb中,我改变了

devise_for :users, :controllers => { omniauth_callbacks: 'omniauth_callbacks' }

devise_for :users, :controllers => { omniauth_callbacks: 'users/omniauth_callbacks' }

然后我重新启动了我的服务器,当我尝试使用linkedin登录时,我收到了错误,

The action 'linkedin' could not be found for Users::OmniauthCallbacksController

我错过了什么?

佣金路线的输出为

                  Prefix Verb      URI Pattern                            Controller#Action
        new_user_session GET       /users/sign_in(.:format)               devise/sessions#new
            user_session POST      /users/sign_in(.:format)               devise/sessions#create
    destroy_user_session DELETE    /users/sign_out(.:format)              devise/sessions#destroy
 user_omniauth_authorize GET|POST  /users/auth/:provider(.:format)        users/omniauth_callbacks#passthru {:provider=>/facebook|twitter|linkedin/}
  user_omniauth_callback GET|POST  /users/auth/:action/callback(.:format) users/omniauth_callbacks#(?-mix:facebook|twitter|linkedin)
           user_password POST      /users/password(.:format)              devise/passwords#create
       new_user_password GET       /users/password/new(.:format)          devise/passwords#new
      edit_user_password GET       /users/password/edit(.:format)         devise/passwords#edit
                         PATCH     /users/password(.:format)              devise/passwords#update
                         PUT       /users/password(.:format)              devise/passwords#update
cancel_user_registration GET       /users/cancel(.:format)                devise/registrations#cancel
       user_registration POST      /users(.:format)                       devise/registrations#create
   new_user_registration GET       /users/sign_up(.:format)               devise/registrations#new
  edit_user_registration GET       /users/edit(.:format)                  devise/registrations#edit
                         PATCH     /users(.:format)                       devise/registrations#update
                         PUT       /users(.:format)                       devise/registrations#update
                         DELETE    /users(.:format)                       devise/registrations#destroy
           finish_signup GET|PATCH /profile/:id/finish_signup(.:format)   users#finish_signup
              home_index GET       /home/index(.:format)                  home#index
                    root GET       /                                      home#index

1 个答案:

答案 0 :(得分:4)

您必须指定正确的提供商名称。在您的代码中,我可以看到您使用的名称linked_in不正确,您必须将所有这些名称更改为linkedin

此致