Devise and Knock gem current_user

时间:2018-09-19 14:14:40

标签: ruby-on-rails ruby devise jwt

我有一个同时使用Devise和Knock的应用程序。它使用Devise为Active Admin提供身份验证,而Knock gem为我的API提供身份验证

我的问题是Knock似乎找不到current_user,我相信这很可能是因为我在同一项目中使用了Devise。

我有以下设置:

Api控制器

class ApiController < ActionController::API
  include Knock::Authenticable
end

用户控制器(对于API,不是ActiveAdmin)

module Api
  module V1
    class UsersController < ApiController      
      before_action :set_user, only: [:show, :update, :destroy]

      # GET /users/1
      def show
        render json: @user
      end

      # POST /users
      def create        
        @user = User.new(user_params)               

        if @user.save
          render json: @user.id, status: :created
        else
          render json: @user.errors, status: :unprocessable_entity
        end
      end

      # PATCH/PUT /users/1
      def update
        if @user.update(user_params)
          render json: @user
        else
          render json: @user.errors, status: :unprocessable_entity
        end
      end

      # DELETE /users/1
      def destroy
        @user.destroy
      end

      private
      # Use callbacks to share common setup or constraints between actions.
      def set_user
        @user = User.find(params[:id])
      end

      # Only allow a trusted parameter "white list" through.
      def user_params
        params.require(:user).permit(:email, :password, :password_confirmation)
      end
    end
  end
end

身份验证控制器

module Api
  module V1
    class AuthController < ApiController      
      def auth        
        render json: { status: 200, user: current_user }
      end
    end
  end
end
在此Auth控制器中的

Current User不返回任何内容,但是在我拥有的另一个项目中,如果没有设计,这将正确地返回用户。

是否有一种方法可以重新定义current_user或将其分配给不同的对象以用于使用Knock?

1 个答案:

答案 0 :(得分:0)

在您的ApplicationController中尝试

   # JWT: Knock defines it's own current_user method unless one is already
  # defined. As controller class is cached between requests, this method
  # stays and interferes with a browser-originated requests which rely on
  # Devise's implementation of current_user. As we define the method here,
  # Knock does not reimplement it anymore but we have to do its thing
  # manually.
  def current_user
    if token
      @_current_user ||= begin
        Knock::AuthToken.new(token: token).entity_for(User)
      rescue
        nil
      end
    else
      super
    end
  end

  private

  # JWT: No need to try and load session as there is none in an API request
  def skip_session
    request.session_options[:skip] = true if token
  end

  # JWT: overriding Knock's method to manually trigger Devise's auth.
  # When there is no token we assume the request comes from the browser so
  # has a session (potentially with warden key) attached.
  def authenticate_entity(entity_name)
    if token
      super(entity_name)
    else
      current_user
    end
  end