2014-12-11 12 views
5

Ich bin ein wenig verwirrt darüber, wie man CanCanCan richtig konfiguriert.Wie richte ich meine CanCanCan-Berechtigungen richtig ein?

Für den Anfang, muss ich hinzufügen load_and_authorize_resource zu jeder Controller-Ressource, die ich den Zugriff beschränken möchte?

Dies ist, was würde ich tun:

  • Admin verwalten und alle Controller und Aktionen alle
  • Editor lesen zugreifen können, verwalten: Nachrichten, und können alle Beiträge
  • Mitglied verwalten können jeden Beitrag lesen und kann & Update-Beiträge erstellen (nicht bearbeiten/löschen/irgendetwas anderes), kann nicht auf den Newsroom zugreifen. Der Unterschied zwischen einem Update-Post & in unseren Geschäftsregeln besteht darin, dass ein Update einen neuen Post erstellt, der ein untergeordneter Post des aktuellen Posts ist. Es ist also keine Bearbeitung. Nur ein neuer Rekord mit einer Vorfahrenvereinigung.
  • Gäste können jeden Beitrag lesen, aber keine Beiträge erstellen oder auf den Newsroom zugreifen.

Dies ist, was mein ability.rb wie folgt aussieht:

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 

In meinem routes.rb Ich habe dies:

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 

Was allerdings passiert, ist, wenn ich mit einem Benutzer bin angemeldet, dass Mir wurden keine Rollen zugewiesen (dh ich möchte ein "Gast" sein), sie können auf den Newsroom zugreifen.

Wenn ich versuche, einen Beitrag mit der Rolle :member zu bearbeiten, gibt es mir einen Fehler "nicht autorisiert, Beitrag zu bearbeiten" (was korrekt ist).

Ich kann einfach nicht ganz die Newsroom sperren und ich bin mir nicht sicher warum.

Antwort

2

Für das, was es wert ist, ich Setup hatte meine NewsroomController wie folgt aus:

class NewsroomController < ApplicationController 
    authorize_resource :class => false 

Dies ist, was die Arbeits Version meiner ability.rb aussieht, nachdem ich es bekommen habe mit den Berechtigungen zur Arbeit musste ich:

#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

Muss ich als Erstes load_and_authorize_resource zu jeder Controller-Ressource hinzufügen, auf die ich den Zugriff beschränken möchte?

Ja.

Was allerdings passiert, ist, wenn ich mit einem Benutzer bin angemeldet, das hat keine Rollen zugewiesen wurde (das heißt, was ich will ein „Gast“ sein), sie können die Nachrichten zugreifen.

Von der Gastrolle oben:

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

Dies gibt einen Gast Zugriff auf alles und die Möglichkeit, Beiträge erstellen lesen. Wenn Sie Ihre Gäste wollen nur in der Lage sein, Beiträge zu lesen, sollte es sein:

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

Außerdem kann @marcamillion die Authentifizierung in den Routen löschen, da CanCanCan den Zugriff auf den Newsroom verweigert, wenn 'can: read,: all' aus dem Guest entfernt wird. Gut um Duplikate zu entfernen. – Tim

+0

Ich möchte, dass ein Gast alle Beiträge lesen, Beiträge verfassen und Statusbeiträge schreiben kann. Aber ich möchte nicht, dass sie auf den 'Newsroom' zugreifen können und ich möchte nicht, dass sie irgendwelche' Post' bearbeiten/aktualisieren/löschen können. – marcamillion

9

Sie brauchen nicht load_and_authorize_resource in jedem Controller zu verwenden. Das ist ein Komfortmakro, das zwei Dinge tut. Zuerst weist er eine Instanzvariable mit den für den aktuellen Controller und die Aktion angenommenen Datensätzen zu. Es autorisiert dann die Ressource.Bei einigen Controller-Aktionen ist der erste Schritt möglicherweise falsch, daher möchten Sie Ihre Ressource laden und sie dann manuell autorisieren. Ein Beispiel aus der Railscasts episode about CanCan ist wie folgt:

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

Sie können es auch tun wie im Beispiel auf der CanCan Wiki for authorizing controllers:

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

Oder Sie können authorize_resource einfach und kümmern sich es von Laden verwenden. Am Ende müssen Sie sicherstellen, dass CanCan irgendwie für die Autorisierung verwendet wird (Controller-Makro oder in jeder Aktion). In Bezug auf Ihre Fähigkeiten, ich glaube, Sie so etwas wie dies will:

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 

Und hier ist ein Beispiel, wie, wie Sie Ihre Nachrichtenredaktion autorisiert möglicherweise in der Lage:

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

Eine letzte persönliche Notiz CanCan ist, dass ich Ich würde es nicht für neue Projekte vorschlagen, da es nicht mehr aktiv gepflegt wird und ich es etwas kontraintuitiv fand, wenn ich Fähigkeiten definiere. Das heißt, CanCan ist einer der am besten dokumentierten Edelsteine, mit denen ich gearbeitet habe, besonders the wiki hat viele Beispiele und Erklärungen.

+1

Es gibt jetzt eine Community-Version namens CanCanCan, die aktiv gepflegt wird - https://github.com/CanCanCommunity/cancancan. Danke für diese Antwort, werde es ausprobieren und Sie wissen lassen.Das Einzige, was irgendwie komisch ist, ist Ihr letztes Beispiel für die Autorisierung des Newsrooms. Also sollte ich 'authome_resource: class => false 'verwenden, um meine' Newsroom' Klasse zu autorisieren? – marcamillion

+0

Diese Antwort löst mein Problem nicht wirklich. Das Hauptproblem ist, dass ich immer noch Zugang zum "Newsroom" bekomme mit einer Rolle, die ich nicht kann. Z.B. Ich möchte nicht, dass ein Benutzer mit einer Rolle von ': member' darauf zugreifen kann, und sie können es immer noch tun. – marcamillion

+0

Es tut uns leid, dass Sie Ihre Kommentare bisher nicht gesehen haben. Danke für den Link zum gepflegten CanCan-Projekt. Ich sehe, dass du es endlich selbst funktionierst, richtig? –

2
can :read, :all 

bedeutet Benutzer die Berechtigung, alle Ressourcen Ihrer App zu lesen hat. Es sollte

can :read, Post 
sein

auch

cannot :manage, :newsroom 

hinzufügen, wo Sie keinen Zugriff auf Nachrichtenredaktion wollen. Die Reihenfolge, in der Sie Berechtigungen angeben, ist wichtig. Wie andere bereits erwähnt haben, ist 'load_and_authorize_resource' optional. Nur autorisierte Ressourcen sind erforderlich, um alle Aktionen eines Controllers zu autorisieren. Wenn Sie diese überspringen, können Sie einzelne Controller-Aktionen "autorisieren".

Vermeiden Sie Block für die Fähigkeit, es sei denn, absolut notwendig. Zum Beispiel, wenn ein Beitrag User_id drin hat, dann könnten Sie

can :update, Post, user_id: user.id 

Schließlich tun ‚class => false‘ verwendet wird, in dem Sie die Sicherung Ihrer Controller kein Modell haben. Sie haben kein Modell namens "Newsroom", aber Sie haben einen Controller namens "NewsroomsController".

Verwandte Themen