【问题标题】:Admin can't create items for self with CanCan?管理员无法使用 CanCan 为自己创建项目?
【发布时间】:2023-09-17 11:15:01
【问题描述】:

我正在使用CanCanCan 进行授权。管理员可以管理所有内容,因此他们没有每个用户 ID 规则。结果是默认情况下他们无法为自己创建项目。看起来我需要添加一堆额外的管道以使我的控制器中的create 对管理员的工作方式与对一般用户的工作方式相同。原因似乎是Ability#attributes_for 没有为管理员用户提供 user_id 属性。

其他人是如何解决这个问题的?您是否正在编写代码来专门处理视图或控制器中的管理用例?

技能类的相关部分

if user.admin?
  can manage, :all
else
  can manage, Purchase, user_id: user.id
end

示例交互

2.6.2 :012 > Ability.new(User.find(3)).attributes_for(:create, Purchase)
 => {:user_id=>3}
2.6.2 :013 > Ability.new(User.find(4)).attributes_for(:create, Purchase)
 => {}

用户 3 是 general_user,用户 4 是管理员

在控制器中

# relying on load_and_authorize_resource
def create
  puts @purchase.user_id # => nil for admin, 3 for general user
  # have to add this for admin use case
  @purchase.user = current_user
  ...
end

【问题讨论】:

  • 我真的不明白你想要达到什么目的?管理员可以对任何事情进行 CRUD,还是要限制他们的能力?
  • 嗯,我现在看到了你的控制器代码......我认为你不应该使用这种方法。 CanCanCan 能力用于定义访问权限,而不是用于分配用户 ID。让我快速写一个答案。

标签: ruby-on-rails ruby-on-rails-5 cancan cancancan


【解决方案1】:

我不会依赖 Ability 对象将 user_ids 分配给您的新对象。我认为最好在控制器中显式编写它。发生了什么似乎更清楚了。所以基本上只是在create方法中初始化一个新对象,不要依赖load_and_auhtorize_resource

def create
  @purchase = current_user.purchases.new(purchase_attributes)
end

如果用户没有被授权,CanCanCan 就已经干预了。

ps。我多年来一直是 CanCanCan 用户,但最近搬到了 Pundit。我认为它的设计方式比 CanCanCan 更好、更清晰。有时间就去看看吧!

【讨论】:

  • 感谢专家的回答和插件。
  • 郑重声明:我对 CanCanCan 没有任何意见,Pundit 也没有任何条件......只是作为一名 RoR 开发人员的小费 :)
【解决方案2】:

CanCanCan 中有一个错误。定义能力 can(:manage) 需要一个 id。创建记录不会。因此,功能文件不允许您创建 bc,它只寻找可以通过 id 找到的记录。如果您在上面定义:manage 的位置定义can :create, Purchase,那么您应该很好:D

if user.admin?
  can :manage, :all
else
  can :create, Purchase
  can :manage, Purchase, user_id: user.id
end

【讨论】:

    最近更新 更多