2014-12-11 50 views
5

我對如何正確配置CanCanCan有點困惑。如何正確設置我的CanCanCan權限?

對於初學者,我必須將load_and_authorize_resource添加到我想限制訪問的每個控制器資源嗎?

這是我想要做什麼:

  • 管理員可以管理和訪問所有控制器和動作
  • 編輯器可以讀取所有,管理:編輯部,並能管理所有帖子
  • 成員都可以閱讀每一篇文章,並可以創建&更新文章(不編輯/刪除/其他任何內容),不能訪問新聞編輯室。我們業務規則中的更新&編輯帖子之間的區別在於更新正在創建一個新帖子,該帖子是當前帖子的子帖子。所以這不是一個編輯。只是一個祖先協會的新紀錄。
  • 訪客可以閱讀每篇文章,但無法創建文章或訪問新聞室。

這是我ability.rb是什麼樣子:

class Ability 
    include CanCan::Ability 
    def initialize(user) 
    user ||= User.new # guest user (not logged in) 
    #Admin 
    if user.has_role? :admin 
     can :manage, :all 
     can :manage, :newsroom 
    # Editor 
    elsif user.has_role? :editor 
     can :read, :all 
     can :manage, :newsroom 
     can :manage, Post 
    #Member 
    elsif user.has_role? :member 
     can :read, :all 
     can :create, Post 
     can :status, Post 
     can :update, Post do |post| 
      post.try(:user) == user 
     end 
    #Guest 
    else 
     can :read, :all 
     can :create, Post 
     can :status, Post 
    end  
    end 
end 

在我routes.rb我有這樣的:

authenticate :user, lambda { |u| u.has_role? :admin or :editor } do 
    get 'newsroom', to: 'newsroom#index', as: "newsroom" 
    get 'newsroom/published', to: 'newsroom#published' 
    get 'newsroom/unpublished', to: 'newsroom#unpublished'  
    end 

什麼,雖然發生的事情,當我登錄與用戶是尚未分配任何角色(即我想成爲「訪客」),他們可以訪問新聞室。

當我嘗試編輯角色爲:member的帖子時,它給了我一個「未授權編輯帖子」的錯誤(這是正確的)。

我只是不能完全鎖定Newsroom,我不知道爲什麼。

回答

2

對於它的價值,我必須設置我NewsroomController這樣的:

class NewsroomController < ApplicationController 
    authorize_resource :class => false 

這是我的ability.rb的工作版本的樣子後,我得到了它與我所需要的權限的工作:

#Roles 
#Admin 
if user.has_role? :admin 
     can :manage, :all 
# Editor 
    elsif user.has_role? :editor 
    can :manage, :newsroom 
    can :manage, Post 
    #Member 
    elsif user.has_role? :member 
     can [:read, :create, :status], Post 
     can :update, Post do |post| 
     post.try(:user) == user 
     end 
    #Guest 
    else 
     can [:read, :status], Post 
    end 
1

對於初學者,我必須將load_and_authorize_resource添加到我想限制訪問的每個控制器資源嗎?

是的。

什麼,雖然發生的事情,就是當我與已 沒有分配任何角色(即我想成爲一個「客戶」),他們 可以訪問新聞用戶登錄。

從上面的客串角色:

... 
#Guest 
else 
    can :read, :all 
    can :create, Post 
    can :status, Post 
end  

這給出了一個客人閱讀獲得的一切,並創造職位的能力。 如果你希望你的客人只能夠閱讀的職位應該是:

... 
#Guest 
else 
    can :read, Post 
    # can :status, Post # maybe you want this aswell 
end 
+0

此外,@marcamillion可以擺脫路由中的身份驗證,因爲CanCanCan會拒絕訪問新聞編輯室,如果can:read::all被從Guest刪除。很好地消除重複。 – Tim 2014-12-16 08:29:59

+0

我希望'Guest'能夠讀取所有帖子,創建帖子和狀態帖子。但我不希望他們能夠訪問'Newsroom',我不希望他們能夠編輯/更新/刪除任何'Post'。 – marcamillion 2014-12-17 21:37:57

9

你不需要在每個控制器使用load_and_authorize_resource。這是一個方便的宏,它有兩件事。首先,它爲當前控制器和操作分配一個實例變量和假定的記錄。然後授權資源。對於某些控制器操作,第一步可能是錯誤的,因此您需要加載資源然後手動授權。從Railscasts episode about CanCan一個例子是這樣的:

def edit 
    @article = Article.find(params[:id]) 
    unauthorized! if cannot? :edit, @article 
end 

你也可以像在上CanCan Wiki for authorizing controllers的例子:

def show 
    @project = Project.find(params[:project]) 
    authorize! :show, @project 
end 

或者你也可以只使用authorize_resource,並採取裝載的照顧它自己。最後,您必須確保CanCan以某種方式用於授權(控制器宏或每個操作)。關於你的能力,我想你想是這樣的:

class Ability 
    include CanCan::Ability 
    def initialize(user) 
    user ||= User.new # guest user (not logged in) 
    #Admin 
    if user.has_role? :admin 
     can :manage, :all 
    # Editor 
    elsif user.has_role? :editor 
     can :read, :all 
     can :manage, :newsroom 
     can :manage, Post 
    #Member 
    elsif user.has_role? :member 
     can :read, :all 
     can :create, Post 
     can :status, Post 
     can :update, Post do |post| 
     post.try(:user) == user 
     end 
    #Guest 
    else 
     can :read, :all 
     cannot [:index, :published, :unpublished], :newsroom 
    end 
    end 
end 

這裏就像你如何能夠授權您的新聞編輯室的例子:

class ToolsController < ApplicationController 
    authorize_resource :class => false 
    def show 
    # automatically calls authorize!(:show, :tool) 
    end 
end 

約慘慘最後一個個人注意的是,我不會爲新項目提出建議,因爲它不再被主動維護,而且在定義能力時我發現它有點違反直覺。也就是說,CanCan是我合作過的最好的記錄寶石之一,尤其是the wiki有大量的例子和解釋。

+1

現在有一個名爲CanCanCan的社區版本正在積極維護 - https://github.com/CanCanCommunity/cancancan。感謝這個答案,但會嘗試一下,讓你知道。唯一有點奇怪的是你的最後一個例子:授權新聞編輯室。所以我應該使用'authorize_resource:class => false'來授權我的'Newsroom'類? – marcamillion 2014-12-16 22:22:15

+0

這個答案實際上並不能解決我的問題。主要問題是我仍然可以通過我不應該擁有的角色訪問「新聞室」。例如。我不想讓一個具有':member'角色的用戶能夠訪問它,他們仍然可以。 – marcamillion 2014-12-17 21:36:56

+0

對不起,直到現在看不到您的意見。感謝鏈接到維護的CanCan項目。我看到你終於明白自己在工作了,對嗎? – 2015-01-08 08:59:59

2
can :read, :all 

表示用戶有權讀取應用程序的所有資源。它應該是

can :read, Post 

還添加

cannot :manage, :newsroom 

,你不想訪問編輯部。您指定權限的順序很重要。正如其他人已經提到的那樣,'load_and_authorize_resource'是可選的。只需授權資源即可授權控制器的所有操作。如果你跳過這些,那麼你可以'授權'單獨的控制器操作。

除非絕對必要,否則應避免使用阻擋技能。例如,如果帖子中有一個user_ID的,那麼你可以做

can :update, Post, user_id: user.id 

最後,「階級=>假」被用在你沒有一個模型支持您的控制器。 即你沒有叫'新聞室'的模型,但你有一個名爲'NewsroomsController'的控制器。