【问题标题】:Omniauth: "Missing Template Error" - Ruby on RailsOmniauth:“缺少模板错误”——Ruby on Rails
【发布时间】:2015-04-20 02:16:14
【问题描述】:

我正在构建一个 API,它通过 LinkedIn 进行身份验证,然后将我们的令牌返回给客户端。

客户端将使用 AngularJS 编写并单独运行。

授权网址:http://example.com/users/auth/linkedin

身份验证后出现以下错误:

Missing template users/omniauth_callbacks/linkedin, 
devise/omniauth_callbacks/linkedin, devise/linkedin,
application/linkedin with {
    :locale=>[:en],
    :formats=>[:html],
    :variants=>[],
    :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]
}.

Searched in: * "/usr/local/lib/ruby/gems/2.2.0/gems/web-console-2.0.0/lib/action_dispatch/templates" * "/usr/local/Cellar/ruby/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.4.1/app/views"

我使用以下特殊宝石:

# Authentication
gem 'devise'
gem 'devise-token_authenticatable'
gem 'omniauth'
gem 'omniauth-oauth'
gem 'omniauth-linkedin'

# API Wrappers
gem 'linkedin'

源代码

config/routes.rb

# filename: routes.rb
# encoding: utf-8

Rails.application.routes.draw do

  #
  # API v1 Endpoints
  #

  scope '/api' do
    ## Authentication
    devise_for :users,
      :skip => [:sessions, :password, :registrations, :confirmation],
      :controllers => {
        :omniauth_callbacks => "users/omniauth_callbacks",
        :registrations      => "users/registrations",
        :sessions           => "users/sessions"
      }

    ## User specific routes
    scope '/users' do
      devise_scope :user do
        post '/check'   => 'users/users#is_user', as: 'is_user'
        post '/current' => 'users/sessions#get_current_user', as: 'current_user'
      end
    end
  end
end

app/controllers/application_controller.rb

# filename: application_controller.rb
# encoding: utf-8

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

  before_filter :set_cors_headers
  before_filter :cors_preflight

  def set_cors_headers
    headers['Access-Control-Allow-Origin']  = AppConfig.client['origin']
    headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS'
    headers['Access-Control-Allow-Headers'] = '*'
    headers['Access-Control-Max-Age']       = "3628800"
  end

  def cors_preflight
    head(:ok) if request.method == :options
  end
end

app/controllers/users/omniauth_callbacks_controller.rb

# filename: omniauth_callbacks_controller.rb
# encoding: utf-8

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  ## Sign in / up with LinkedIn
  def linkedin
    auth_hash = request.env["omniauth.auth"]

    auth = Authorization.find_by_provider_and_uid("linkedin", auth_hash['uid'])

    if auth
      ## User already exists
      user = auth.user
    else
      ## User already signed in
      unless current_user
        unless user = User.find_by_email(auth_hash['info']['email'])
          user = User.create({
            first_name: auth_hash['info']['first_name'],
            last_name:  auth_hash['info']['last_name'],
            email:      auth_hash['info']['email'],
            password:   Devise.friendly_token[0,8]
          })
        end
      ## Sign user in
      else
        user = current_user
      end

      # Create an authorization for the current user
      unless auth = user.authorizations.find_by_provider(auth_hash["provider"])
        auth = user.authorizations.build(provider: auth_hash["provider"])
        user.authorizations << auth
      end

      auth.update_attributes({
          uid:    auth_hash['uid'],
          token:  auth_hash['credentials']['token'],
          secret: auth_hash['credentials']['secret'],
        })

      # Return user
      user
    end
  end
end

app/controllers/users/registrations_controller.rb

# filename: registrations_controller.rb
# encoding: utf-8

class Users::RegistrationsController < Devise::RegistrationsControllerú
  skip_before_filter :verify_authenticity_token

  respond_to :json

  def create
    # Create the user
    build_resource(sign_up_params)

    # Try to save them
    if resource.save
      sign_in resource
      render status: 200,
        json: {
          success: true,
          info: "Registered",
          data: {
            user: resource,
            auth_token: current_user.authentication_token
          }
        }
    else
      # Otherwise fail
      render status: :unprocessable_entity,
        json: {
          success: false,
          info: resource.errors,
          data: {}
        }
  end

end

app/controllers/users/sessions_controller.rb

# filename: omniauth_callbacks_controller.rb
# encoding: utf-8

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  ## Sign in / up with LinkedIn
  def linkedin
    auth_hash = request.env["omniauth.auth"]

    auth = Authorization.find_by_provider_and_uid("linkedin", auth_hash['uid'])

    if auth
      ## User already exists
      user = auth.user
    else
      ## User already signed in
      unless current_user
        unless user = User.find_by_email(auth_hash['info']['email'])
          user = User.create({
            first_name: auth_hash['info']['first_name'],
            last_name:  auth_hash['info']['last_name'],
            email:      auth_hash['info']['email'],
            password:   Devise.friendly_token[0,8]
          })
        end
      ## Sign user in
      else
        user = current_user
      end

      # Create an authorization for the current user
      unless auth = user.authorizations.find_by_provider(auth_hash["provider"])
        auth = user.authorizations.build(provider: auth_hash["provider"])
        user.authorizations << auth
      end

      auth.update_attributes({
          uid:    auth_hash['uid'],
          token:  auth_hash['credentials']['token'],
          secret: auth_hash['credentials']['secret'],
        })

      # Return user
      user
    end
  end
end

 app/controllers/users/users_controller.rb

# filename: users_controller.rb
# encoding: utf-8

class Users::UsersController < Devise::SessionsController
  protect_from_forgery with: :exception, except: [:is_user]

  respond_to :json

  ## Check if user exists by email
  def is_user
    #authenticate_user!
    render status: 200, json: {
        success: !User.find_by_email(params[:email]).blank?
      }
  end

end

【问题讨论】:

    标签: ruby-on-rails ruby angularjs omniauth omniauth-linkedin


    【解决方案1】:

    Users::OmniauthCallbacksController 类中的linkedin 方法没有明确地renderredirect,因此它试图隐式渲染linkedin 模板(通常是linkedin.html.erb

    根据您的代码,您可能希望 render user.to_json 或在您的代码中产生类似效果的内容,以便 angular api 接收它可以使用的内容。

    【讨论】:

    • 现在我尝试了两件事: - 将respond_to :json 添加到类的顶部和 - 将render user.to_json 添加到末尾,但我得到了同样的错误。 :(
    • 我是根据“Riding Rails with AngularJS”的第 3 章制作的(这是必要的信息吗?)。
    • 确保rendering 满足if/else 语句的两个条件。
    • 谢谢。 :) 我刚刚发现我把user 放在了错误的语句中。我不得不把它移到下一个结尾,我写了类似render status: 200, json: { success: true, info: 'Authentication', data: { user: user } }
    • 现在我只需要了解如何在客户端使用它... :)
    猜你喜欢
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 2017-12-06
    • 2013-05-30
    • 1970-01-01
    • 2012-02-08
    • 2015-09-08
    • 1970-01-01
    相关资源
    最近更新 更多