CanCan错误地拒绝管理员访问

时间:2012-11-14 13:19:48

标签: ruby-on-rails ruby-on-rails-3 devise cancan

我正在使用其他人的代码,而且我对Rails缺乏经验,而且我对CanCan&设计。

当尝试登录时(使用我知道的凭据,因为他们以前工作过,我已经检查了数据库并成功使用了重置功能),我收到一个错误屏幕说明。

CanCan::AccessDenied in AdminController#index

You are not authorized to access this page.

app/controllers/admin_controller.rb:4:in `index'
config/initializers/quiet_assets.rb:6:in `call_with_quiet_assets'

并在终端

Started POST "/users/sign_in" for 127.0.0.1 at 2012-11-14 13:13:01 +0000
  Processing by Devise::SessionsController#create as HTML
  Parameters: {"utf8"=>"✓",  "authenticity_token"=>"T8CJkCIEA3r7ROiknVp/vbEgeKCBZEjl3uYd+46G7no=", "user"=>{"email"=>"pass@user.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
WARNING: Can't verify CSRF token authenticity
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'pass@user.com' LIMIT 1
(0.2ms)  BEGIN
(0.3ms)  UPDATE `users` SET `last_sign_in_at` = '2012-11-14 11:10:56', `current_sign_in_at` = '2012-11-14 13:13:01', `sign_in_count` = 219, `updated_at` = '2012-11-14 13:13:01' WHERE `users`.`id` = 1
(0.1ms)  COMMIT
Redirected to http://core.lvh.me:3000/admin
Completed 302 Found in 355ms


Started GET "/admin" for 127.0.0.1 at 2012-11-14 13:13:02 +0000
  Processing by AdminController#index as HTML
Completed 500 Internal Server Error in 265ms

CanCan::AccessDenied (You are not authorized to access this page.):
  app/controllers/admin_controller.rb:4:in `index'
  config/initializers/quiet_assets.rb:6:in `call_with_quiet_assets'

admin_controller.rb

class AdminController < ApplicationController

  def index
   authorize! :index, :admin (#line 4)
  end

ability.rb

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 "franchise_admin"
      can [:read, :search, :all, :up_down_index], Article
      can [:old_feed, :sites, :new_feed], MobileFeed
      can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
      can [:index, :new_site_essentials], :admin


    when "franchise_editor"
      can [:new, :read, :update], SiteSpecificArticle { |ssa| ssa.site.customer.sites.include?(user.site) }
      can [:old_feed, :sites, :new_feed], MobileFeed
      can [:read, :search, :all, :up_down_index], Article

    when "site_admin"
      # can CRUD users for their site
      can :manage, User, site_id: user.site_id
      # can edit content for their site
      can [:read, :update], ArticleSitePermission, site_id: user.site_id
      can [:read, :update], CoreArticleSiteVisibility, site_id: user.site_id
      can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
      can [:new, :read, :update], FrontPageCampaign, site_id: user.site_id
      can [:new, :read, :update], FrontPageTimeBasedArticle, site_id: user.site_id
      can [:new, :read, :update], FrontpageArticle, site_id: user.site_id
      can [:index, :new_site_essentials], :admin
      can [:read, :search, :all, :up_down_index, :hidden_in_this_site], Article
      can [:old_feed, :sites, :new_feed], MobileFeed
      can [:index, :create], TrackMood
      can :site_styles, Site

    when "editor"
      # can edit content for their site
      can [:read, :update], ArticleSitePermission, site_id: user.site_id
      can [:read, :update], CoreArticleSiteVisibility, site_id: user.site_id
      can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
      can :manage, FrontPageCampaign, site_id: user.site_id
      can :manage, User, site_id: user.site_id
      can [:new, :read, :update], FrontPageTimeBasedArticle, site_id: user.site_id
      can [:new, :read, :update], FrontpageArticle, site_id: user.site_id
      can [:old_feed, :sites, :new_feed], MobileFeed
      can [:index, :new_site_essentials], :admin
      can [:read, :search, :all, :up_down_index, :hidden_in_this_site], Article
      can [:index, :create], TrackMood
      can :site_styles, Site

    else
      # guest user (not logged in)
      can [:read, :search, :up_down_index], Article
      can [:old_feed, :sites, :new_feed], MobileFeed
      can [:index, :create], TrackMood
      can :site_styles, Site
    end
  end
end

对此事的任何帮助将不胜感激。即使这只是尝试调试问题的另一个步骤。

谢谢

2 个答案:

答案 0 :(得分:2)

Github上的CanCan wiki声明:

“添加authorize_resource会生成一个调用authorize!的before过滤器,如果存在则传递资源实例变量。如果未设置实例变量(例如在index操作中),它将传入类名。例如,如果我们有一个ProductsController,它将在每个动作之前执行此操作。“

authorize!(params[:action], @product || Product)

您的问题是,当您实际必须授权管理对象或模型时,您尝试授权:admin符号的:index操作,如下所示:

authorize!(:index, @admin)

我觉得你误解了授权!方法并试图为角色:admin授权索引操作,但是所有CanCan的东西都是基于current_ability授权的,这应该是用户会话上设置的第一件事。 CanCan可以使用这个默认的ApplicationController方法为你做这个:

def current_ability
    @current_ability ||= Ability.new(current_user)
end

但这意味着你需要另一个名为current_user的方法来返回当前用户(doh)。检查你是否有这个设置,如果没有,那么设置它并更改:ad​​min到@admin(你必须实例化,我认为是current_user.admin(?))。

还有一件事:如果你正在进行这样的授权只是为了调试,好吧,没问题,但是如果你正在考虑实际授权每个动作都是这样的,请不要。 CanCan有一个名为load_and_authorize_resource的方法,它既为控制器的每个动作授权current_user,也将变量@model(例如@products)实例化为:Product.accessible_by(current_ability)。当您拥有用户在某些情况下只能查看或管理的内容(例如编辑自己的个人资料)时,此功能非常有效。当然,你必须在ability.rb文件中设置它。这种方法是这样的:

class AdminController < ApplicationController

    load_and_authorize_resource

    def index
        # @admins here will have every admin that the user can see
    end

end

如果你有一些不需要授权的行动,你可以说:

load_and_authorize_resource, :only => [:action1, :action2]
load_and_authorize_resource, :except => [:action1, :action2]

或者:

load_and_authorize_resource
skip_authorize_resource, :only => [:action1]
skip_authorize_resource, :except => :action2 #can be both an array or single symbol

我希望这可以帮助你和任何有这个问题的人:)

答案 1 :(得分:0)

您可以尝试更改为:

class AdminController < ApplicationController

  def index
    authorize! :index, :super_admin (#line 4)
  end