3

我正在使用其他人的代码,而且我对 Rails 相当缺乏经验,而且我遇到了 CanCan & Devise 的问题。

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

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

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

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

谢谢

4

2 回答 2

3

Github 上的 CanCan wiki 指出:

“添加 authorize_resource 将创建一个调用 authorize! 的前置过滤器,如果存在则传递资源实例变量。如果未设置实例变量(例如在 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)。检查你是否有这个设置,如果没有,那么设置它并将 :admin 更改为 @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

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

于 2012-11-15T03:41:43.187 回答
0

您可以尝试更改为:

class AdminController < ApplicationController

  def index
    authorize! :index, :super_admin (#line 4)
  end
于 2012-11-14T17:50:18.940 回答