我使用pundit来处理我的API策略,我有一个项目显示,可以在某些情况下禁止用户,在其他情况下只是限制。通过限制我的意思是它现在被禁止,但如果他支付,他可以访问它。所以我需要我的API响应一个特定的代码(402 Payment Required
),这样客户端就可以邀请用户支付,以解锁显示。
这是我目前的代码,当pundit返回false时,它只响应403
。
在哪里实现一个条件返回403
或402
以获得DRY和清洁是最好的?
class Api::V1::ItemController < Api::V1::BaseController
def show
@item = Item.find(params[:id])
authorize @item
end
end
class ItemPolicy < ApplicationPolicy
def show?
return true if record.public?
# 403 will be generated, that's ok.
return false if !record.band.members.include?(user)
# If that condition is false I want to generate a 402 error at the end, not a 403.
user.premium?
end
end
class Api::V1::BaseController < ActionController::API
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def user_not_authorized(_exception)
# Here I've got the exception with :policy, :record and :query,
# also I can access :current_user so I could go for a condition,
# but that would include duplicated code from ItemPolicy#show?.
render json: { error: { message: "Access denied" } }, status: :forbidden
end
end
2条答案
按热度按时间vs91vp4v1#
不幸的是,
Pundit
不能处理不同的错误类型。并且它被构建为总是期望策略的方法返回true
或falsefalse
。因此,在控制器中引发另一个自定义错误并从该错误中恢复将不起作用,因为它也会破坏视图方法。我建议一个变通方案来引入不同的错误类型。类似这样的东西可能会起作用:
我不认为使用全局
CurrentAttributes
是一个好的实践,但它们是Rails的一部分,在这种情况下,使用这个全局数据存储避免了覆盖pundit内部。您可能需要阅读有关
CurrentAttributes
的API文档。wtzytmuj2#
在app/controllers/concerns/response.rb中创建Response模块
在app/controllers/concerns/exception_handler.rb中创建ExceptionHandler
在app/controllers/application_controller.rb中
就是这样