在控制器中明确允许 Doorkeeper 范围

Explicitly allow Doorkeeper scope in controller

在我当前的应用程序中,我有两个门卫范围,useradmin。在 doorkeeper documentation 中用于在 API 中设置范围,它显示

class Api::V1::ProductsController < Api::V1::ApiController
  before_action -> { doorkeeper_authorize! :public }, only: :index
  before_action only: [:create, :update, :destroy] do
    doorkeeper_authorize! :admin, :write
  end

  ...
end

我不想在每个控制器中调用 doorkeeper,所以在我的 ApplicationController 中我有

module API
  module V1
    class ApplicationController < ActionController::API
      before_action { doorkeeper_authorize! :user, :project }
      ...

    end
  end
end

但我不想让 :project 访问每个控制器。有没有办法让我在我们的应用程序控制器 before_action { doorkeeper_authorize! :user } 中允许 user 并在每个控制器的基础上允许 project?即:

module API
  module V1
    class SomeController < ApplicationController
      before_action only: [:index, :show] { doorkeeper_authorize! :project }

      ...
    end
  end
end

controller_name 使用条件语句 - smith 是这样的:

before_action { doorkeeper_authorize! :project }, if: -> { controller_name == 'some' }

检查您是否应该将参数传递给 lambda,例如:

if: ->(instance) { instance.controller_name == 'some' }

我可以通过在 API::V1::ApplicationController

中执行以下操作来解决此问题
module API
  module V1
    class ApplicationController < ActionController::API
      WHITELISTED_PROJECT_CONTROLLERS = %w( projects pre_task_plans
                                            job_hazard_analyses ).freeze

      before_action :authorize!

      def authorize!
        if project_scope?
          if !WHITELISTED_PROJECT_CONTROLLERS.include?(controller_name)
            return user_not_authorized
          end
        end
        doorkeeper_authorize! :user, :project
      end

      def project_scope?
        doorkeeper_token&.scopes&.any? { |s| s == 'project' }
      end

     ...

    end
  end
end

也许创建自己的过滤器是一种选择

before_action :doorkeeper_user_authorize!,  only: [:create, :update, :destroy]
protected 

def doorkeeper_user_authorize!
  doorkeeper_authorize!( :user )
end 

def doorkeeper_project_authorize!
  doorkeeper_authorize!( :user, :project )
end 

然后在应该允许项目的控制器中

skip_before_action :doorkeeper_user_authorize!
before_action :doorkeeper_project_authorize!