CanCan和数据集

时间:2010-12-13 06:51:01

标签: ruby-on-rails authorization cancan

我一直在努力解决这个问题,我终于到了CanCan似乎不允许你授权收集记录的地步。例如:

ads_controller.rb

def index
    @ads = Ad.where("ads.published_at >= ?", 30.days.ago).order("ads.published_at DESC")
    authorize! :read, @ads
end

ability.rb

def initialize(user)
  user ||= User.new # Guest user

  if user
    if user.role? :admin  # Logged in as admin
      can :manage, :all
    else                  # Logged in as general user
      can :read, Ad
      can :read_own, Ad, :user_id => user.id
      can :create, Ad
    end
  else                    # Not logged in (Guest)
    can :read, Ad
  end
end

这会在尝试访问索引操作时导致未经授权的访问消息。

You are not authorized to access this page.

但是,如果您在索引操作中更改授权调用以检查Ad类而不是像这样的集合

def index
    @ads = Ad.where("ads.published_at >= ?", 30.days.ago)
    authorize! :read, Ad
end

......工作正常。

非常感谢任何帮助解释这一点。

提前致谢。

PS。在尝试解决这个问题时,我最初获得了重定向循环。事实证明,你在应用程序控制器中提供了一个推荐的rescue_from,它给你提供了很好的错误信息。如果您的root_path设置为您授权的同一个地方!如果调用不正确(或失败),您将获得重定向循环。评论出来救援人员从困难中了解到这一点。

2 个答案:

答案 0 :(得分:2)

CanCan的设计并非如此。您可以检查用户是否拥有模型类(例如Ad)或单个实例(例如@ad)的权限。

我建议您使用accessible_by来过滤您的收藏:

@ads = Ad.where("ads.published_at >= ?", 30.days.ago).accessible_by(current_ability) 
# @ads will be empty if none are accessible by current user

raise CanCan::AccessDenied if @ads.empty?  # handle however you like

另一种方法是根据用于检索集合的条件定义自定义权限:

# ability.rb
can :read_ads_from_past_month, Ad, ["ads.published_at >= ?", 30.days.ago]

# in your controller
def index
  authorize! :read_ads_from_past_month, Ad
  @ads = Ad.where("ads.published_at >= ?", 30.days.ago)
end

答案 1 :(得分:2)

我使用splats解决了这个问题。在此代码示例中,我尝试在TimeOffRequests集合上授权用户。如果用户是管理员,经理或休假请求属于他们,则应授权他们。

# time_off_requests_controller.rb
authorize! :read, *@time_off_requests

# Ability.rb
can :manage, TimeOffRequest do |*time_off_requests|
  membership.has_any_role?(:admin, :manager) ||
    time_off_requests.all? { |tor| membership.id == tor.employee_id }
end

如果您有兴趣,我在这里详细介绍了它:http://zacstewart.com/2012/01/08/defining-abilities-for-collections-of-records-using-cancan.html