Rails API/Pundit:ActiveModelSerializers的强参数



Pundit部分的这一部分说我们可以控制哪些属性被授权更新。但是在使用active_model_seriallizers宝石的情况下它会失败:

def post_params
# originally geneated by scaffold
#params.require(:post).permit(:title, :body, :user_id)
#To deserialize with active_model_serializers
ActiveModelSerializers::Deserialization.jsonapi_parse!(
params,
only: [:title, :body, :user]
)
end

如果我按照权威人士的建议修改PostsControllerupdate操作:

def update
if @post.update(permitted_attributes(@post))
render jsonapi: @post
else
render jsonapi: @post.errors, status: :unprocessable_entity
end
end

它失败并显示错误:

ActionController::ParameterMissing (param is missing or the value is empty: post):
app/controllers/posts_controller.rb:29:in `update'

我还按如下方式创建PostPolicy

class PostPolicy < ApplicationPolicy
def permitted_attributes
if user.admin? || user.national?
[:title, :body]
else
[:body]
end
end
end

但它对上述错误没有影响。

关于我们如何做到这一点的任何想法?

我得出的解决方案(感谢@max提供的一些提示和技巧)如下:

  1. 将以下行添加到config/application.rb
config.action_controller.action_on_unpermitted_parameters = :raise
  1. rescue_from添加到AplicationController或您完全感兴趣的:
class ApplicationController < ActionController::API
include ActionController::MimeResponds
include Pundit
rescue_from Pundit::NotAuthorizedError, ActionController::UnpermittedParameters, with: :user_not_authorized
...
private
def user_not_authorized
render jsonapi: errors_response, status: :unathorized
end
def errors_response
{
errors:
[
{ message: 'You are not authorized to perform this action.' }
]
}
end
end

然后将pundit_params_for方法添加到PostsController并更改update操作(就我而言,我只想限制update操作中的某些属性:)

class PostsController < ApplicationController
...
def update
if @post.update(permitted_attributes(@post))
render jsonapi: @post
else
render jsonapi: @post.errors, status: :unprocessable_entity
end
end
private
def post_params
ActiveModelSerializers::Deserialization.jsonapi_parse!(
params,
only: [:title, :body, :user]
)
end
def pundit_params_for(_record)
params.fetch(:data, {}).fetch(:attributes, {})
end
end

瞧。现在,如果将为update操作提交不允许的属性,则响应将具有500状态,并包含ApplicationController#errors_response method中指定的错误。

注意:如果您与请求一起发布了一些关系,它仍然会失败(例如,您可以将Author作为与Post的关系belongs_to)。像以前一样使用pundit_params_for将无法提取相应的author_id值。为了看到方法,这是我的另一篇文章,我解释了如何使用它。

希望这有帮助。

相关内容

  • 没有找到相关文章

最新更新