1

我有用户

class User < ActiveRecord::Base
  devise :database_authenticatable,
         :recoverable, :rememberable, :trackable, :validatable


  attr_accessible :email, :password, :password_confirmation,
                  :remember_me, :site_id, :role_name

  belongs_to :site

end

网站

class Site < ActiveRecord::Base
  has_many :users
  has_one :front_page_campaign
end

和 front_page_campaigns

class FrontPageCampaign < ActiveRecord::Base
  belongs_to :site
end

我正在使用 cancan 来限制访问,因此用户只能为自己的站点管理 front_page_campaigns:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)

    case user.role_name

    when "super_admin"
      # can do everything
      can :manage, :all

    when "editor"
      # can edit content for their site
      can [:create, :read, :update], FrontPageCampaign, site_id: user.site_id

    end
  end
end

这对于具有 role_name 的用户super_admin以及editoron show 和 edit on非常有效front_page_campaigns。但是当一个editor尝试创建一个新的front_page_campaign时,我收到了一个cancan禁止通知

You are not authorized to access this page.

标准表单提供了所有站点的下拉框,我想我需要将其限制为用户自己的站点。我该怎么做呢?

4

1 回答 1

1

通过添加以下内容可以解决您的授权问题:

can :new, FrontPageCampaign

到cancan能力init的编辑器部分。要在新对象上设置 site_id 并创建对象,您可以设置 before_filter:

# FrontPageCampaignsController
before_filter :set_site_id, :only => [:new, :create]

protected

def set_site_id
  @resource.site_id = current_user.site_id if current_user && current_user.role_name == 'editor'
end

您必须确保在创建资源之后但在可以授权之前触发它。

在您的表单中(如果您对超级管理员和编辑器使用相同)将站点下拉选择设置为只读或隐藏 if current_user.role_name == 'editor'

请注意,如果有人篡改了表单并发送了一个陌生的 site_id 作为编辑器,它将被 before 过滤器更正,这不是很好。如果你把 if 拿出来,:only => :new然后他们会得到 cancan 的授权错误。如果你是超级学究,你应该得到一个带有验证错误的有效响应。您可以通过 1) 仅将 before_filter 应用于 new 和 2) 在能力初始化中说来实现这一点

when "editor"
  # can edit content for their site
  can [:read, :update], FrontPageCampaign, site_id: user.site_id
  can [:create, :new], FrontPageCampaign
end

3) 将站点所有者检查添加到模型验证中。这是我的首选方式,保留对现有资源的非法访问的授权错误。

希望这能回答你的问题

于 2012-05-24T10:50:34.080 回答