4

我已经为此苦苦挣扎了一段时间,终于到了 CanCan 似乎不允许您授权记录集合的地步。例如:

ads_controller.rb

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

能力.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.

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

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

...它工作正常。

任何帮助解释这一点将不胜感激。

提前致谢。

附言。当我试图解决这个问题时,我最初得到了重定向循环。事实证明,有一个带有推荐的 rescue_from 的 gotchya,您将其放入应用程序控制器中,以便为您提供很好的错误消息。如果您的 root_path 设置为您授权的相同位置!call 不正确(或失败),您将获得重定向循环。注释掉rescue_from 学到了一个艰难的方法。

4

2 回答 2

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
于 2010-12-13T09:03:38.363 回答
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

于 2012-05-03T15:54:03.363 回答