使用active_model_serializers序列化权限(例如CanCan)

11

如何使用active_model_serializers序列化权限?我在模型和序列化器中没有访问current_usercan?方法的权限。

3个回答

23

首先,在序列化器上下文中获取current_user的访问权限,可以使用新的作用域特性:

class ApplicationController < ActionController::Base
  ...
  serialization_scope :current_user
end

如果您手动实例化序列化器,请确保传递作用域参数:

model.active_model_serializer.new(model, scope: serialization_scope)

然后在序列化器中,添加自定义方法来添加您自己的授权伪属性,使用 scope(当前用户)来确定权限。

如果您正在使用 CanCan,则可以实例化 Ability 类以访问 can? 方法:

attributes :can_update, :can_delete

def can_update
  # `scope` is current_user
  Ability.new(scope).can?(:update, object)
end

def can_delete
  Ability.new(scope).can?(:delete, object)
end

我不明白 - 你是不是立刻回答了自己的问题? - Jesse Wolgamott
2
是的,我做到了 - 请参阅此文章。 我想要保留这个知识片段,但发现它太琐碎/专业化,不适合在我的博客上发布,所以我用问答的形式发布在这里。 - Jo Liss
1
作为“super.merge”风格的替代方案,您可以使用attributes:can_update,:can_delete,然后在序列化器中定义can_update和can_delete作为方法。两种方法都可以。 - tee
您还可以将can?方法委托给您的模型,以获得更好的可读性 - 请参见https://dev59.com/1nA75IYBdhLWcg3wdIl0#3293522。 - pierrea

3

2

我认为你可以将任何想要的内容传递给serialization_scope,所以我只是传递了Ability。

class ApplicationController < ActionController::Base
 ...
 serialization_scope :current_ability

 def current_ability
   @current_ability ||= Ability.new(current_user)
 end

end


class CommentSerializer < ActiveModel::Serializer
  attributes :id, :content, :created_at, :can_update

  def can_update
    scope.can?(:update, object)
  end

end

由于我的能力实际上基于两个变量(不在上面的示例中),所以我无法做其他事情。
如果您仍然需要访问current_user,您可以在Ability上设置一个实例变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接