Cancan - 当用户限制在某些网站时,新表单会失败

时间:2012-05-24 09:56:43

标签: ruby-on-rails cancan

我有用户

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

这适用于super_admin上展示和编辑的role_name editor以及front_page_campaigns用户。但是当editor尝试创建新的front_page_campaign时,我会收到一封禁止加入的cancan

You are not authorized to access this page.

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

1 个答案:

答案 0 :(得分:1)

您的授权问题可以通过添加:

来解决
can :new, FrontPageCampaign

到cancan ability init的编辑部分。 要在new和create对象上设置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

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

在您的表单中(如果您对superadmin和编辑器使用相同的内容),请在current_user.role_name == 'editor'时将网站下拉列表选择为只读或隐藏。

请注意,如果有人篡改表单并发送外星人site_id作为编辑器,它将被前置过滤器更正,这不太好。如果你拿出: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)将网站所有者检查添加到模型验证中。这是我的首选方式,为非法访问现有资源保留授权错误。

希望这能回答你的问题