如何处理Grape中特定操作的过滤器之前?

Eki*_*bal 5 ruby ruby-on-rails ruby-grape grape-api

我正在我的Rails项目中安装Grape来构建RESTful API.

现在一些端点有需要身份验证的操作和其他不需要身份验证的端点.

例如,我有users一个看起来像这样的终点:

module Backend
  module V1
    class Users < Grape::API
      include Backend::V1::Defaults

      before { authenticate! }

      resource :users do

        desc "Return a user"
        params do
          requires :id, type: Integer, desc: 'User id'
        end
        get ':id' do
          UsersService::Fetch.new(current_user,params).call
        end

        desc "Update a user"
        params do
          requires :id, type: Integer, desc: 'User id'
          requires :display_name, type: String, desc: 'Display name'
          requires :email, type: String, desc: 'Email'
        end
        post ':id' do
          UsersService::Save.new(current_user,params).call
        end

        desc "Reset user password"
        params do
          requires :old_password, type: String, desc: 'old password'
          requires :password, type: String, desc: 'new password'
        end
        post 'password/reset' do
          PasswordService::Reset.new(current_user,params).call
        end

        desc "Forget password"
        params do
          requires :email, type: String
        end
        post 'password/forget' do
          PasswordService::Forget.new(current_user,params).call
        end            

      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

现在您可以看到,除了password/forget需要用户登录/验证之外的所有操作.创建一个新的终点也没有意义,让我们说passwords,只是从password/forget逻辑上讲删除它,这个终点应该与用户资源相关.

问题是Grape before过滤器没有选项except, only,我可以说应用过滤器进行某些操作.

你如何以干净的方式处理这种情况?

M P*_*ima 6

我能想到的一种方法是使用route_setting为你想要绕过auth的路由添加自定义属性.在调用之前检查before过滤器中的这些属性authenticate!.像下面这样的东西应该工作:

module Backend
  module V1
    class Users < Grape::API
      include Backend::V1::Defaults

      before { authenticate! unless route.settings[:auth] && route.settings[:auth][:disabled] }

      resource :users do

        desc "Return a user"
        params do
          requires :id, type: Integer, desc: 'User id'
        end
        get ':id' do
          UsersService::Fetch.new(current_user,params).call
        end

        desc "Update a user"
        params do
          requires :id, type: Integer, desc: 'User id'
          requires :display_name, type: String, desc: 'Display name'
          requires :email, type: String, desc: 'Email'
        end
        post ':id' do
          UsersService::Save.new(current_user,params).call
        end

        desc "Reset user password"
        params do
          requires :old_password, type: String, desc: 'old password'
          requires :password, type: String, desc: 'new password'
        end
        post 'password/reset' do
          PasswordService::Reset.new(current_user,params).call
        end

        desc "Forget password"
        route_setting :auth, disabled: true
        params do
          requires :email, type: String
        end
        post 'password/forget' do
          PasswordService::Forget.new(current_user,params).call
        end            

      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)


Eki*_*bal 3

一种肮脏的帮助方式是使用namespace,例如:

module Backend
  module V1
    class Users < Grape::API
      include Backend::V1::Defaults

      namespace :users do
        desc "Forget password"
        params do
          requires :email, type: String
        end
        post 'password/forget' do
          PasswordService::Forget.new(current_user,params).call
        end

        namespace do
          before { authenticate! }

          desc "Return a user"
          params do
            requires :id, type: Integer, desc: 'User id'
          end
          get ':id' do
            UsersService::Fetch.new(current_user,params).call
          end

          desc "Update a user"
          params do
            requires :id, type: Integer, desc: 'User id'
            requires :display_name, type: String, desc: 'Display name'
            requires :email, type: String, desc: 'Email'
          end
          post ':id' do
            UsersService::Save.new(current_user,params).call
          end

          desc "Reset user password"
          params do
            requires :old_password, type: String, desc: 'old password'
            requires :password, type: String, desc: 'new password'
          end
          post 'password/reset' do
            PasswordService::Reset.new(current_user,params).call
          end            

        end
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这样我们就不会在过滤器之前运行,users/password/forget但对于其余的我们将运行before { authenticate! }