【问题标题】:cancancan row based filtercancancan 基于行的过滤器
【发布时间】:2017-05-12 19:25:04
【问题描述】:

我已经在 cancancan gem 中声明了一个角色能力(rails 5、postgres、devise):

can [:update, :show, :destroy, :index], SalesDatum do |datum|
  datum.try(:user_id) == user.id #the ids just access the id's from the user object that is passed into can can and from the table
end

SalesDatum 有一个 user_id 字段。

这适用于显示操作,因为我只能 show 登录了 user_id 的 SalesDatum 例如:

http://localhost:8080/projects/19/sales_data/961 正确获得身份验证,因为登录的 user_id 与 sales_data 上的 user_id 匹配

http://localhost:8080/projects/19/sales_data/800 由于登录的 user_id 与 sales_data 上的 user_id 不匹配,因此无法正确验证

但是,当我进行获取索引操作时: http://localhost:8080/projects/19/sales_data 它显示了来自@sales_data 变量的所有销售数据。因此,它将显示 data.id 800 和 961。

销售数据控制者:

load_and_authorize_resource
def index
  @sales_data = SalesDatum.where(project_id:params[:project_id])
end

如何让索引操作仅显示具有相关 user_id 的数据? cancan 不应该根据user_id 过滤吗?

【问题讨论】:

  • 我可以将控制器查询编辑为SalesDatum.where(project_id:params[:project_id]).where(user_id:current_user.id),但这似乎是一种非常糟糕的身份验证方式?
  • 这就是我放弃 CanCanCan 转而支持 Pundit 的真正原因 - 看似简单的 DSL 在定义身份验证范围或处理任何不重要的事情方面表现不佳。

标签: ruby-on-rails cancan cancancan


【解决方案1】:

您需要使用哈希语法定义规则。

can [:update, :show, :destroy, :index], SalesDatum, user_id: user.id

您可能还想定义 edit 操作,因此:

can [:edit, :update, :show, :destroy, :index], SalesDatum, user_id: user.id

可以简化为:

can :manage, SalesDatum, user_id: user.id

如果 SalesDatum 定义了 belongs_to :user,您也可以这样写:

can :manage, SalesDatum, user: user

【讨论】:

  • 这太好了,有没有用块语法做这件事的好方法?
  • 块语法应该始终是最后的选择,因为它只适用于实例而不适用于集合。对于集合,您需要使用哈希语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
  • 2021-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多