2016-02-21 5 views
6

ich eine App mit Rails 4.Rails 4 - Pundit mit Rolify - eine Gruppe von Rollen ermöglicht

Ich habe eine Reihe von Rollen mit Rolify gem definiert zu machen versuche.

Jetzt möchte ich Pandit verwenden, um Benutzern mit einer Rolle bestimmte Dinge zu ermöglichen. Wenn mehr als eine Art von Rolle etwas bewirken kann, habe ich eine Gruppe von Rollen definiert.

In meiner application_policy habe ich private Methoden definiert, die die Rollengruppen festlegen, die ich in den Pandit-Berechtigungen verwenden möchte.

Meine Anwendungsrichtlinie instanziiert Benutzer und Datensatz. Ich definiere dann Datensatz als den Namen des relevanten Modells (derselbe Name wie die Richtlinie für dieses Modell).

ich habe:

class ApplicationPolicy 
    attr_reader :user, :record 

    def initialize(user, record) 
    @user = user 
    @record = record 
    end 

    def index? 
    false 
    end 

    def show? 
    scope.where(:id => record.id).exists? 
    end 

    def create? 
    false 
    end 

    def new? 
    create? 
    end 

    def update? 
    false 
    end 

    def edit? 
    update? 
    end 

    def destroy? 
    false 
    end 

    def scope 
    Pundit.policy_scope!(user, record.class) 
    end 

    class Scope 
    attr_reader :user, :scope 

    def initialize(user, scope) 
     @user = user 
     @scope = scope 
    end 

    def resolve 
     scope 
    end 
    end 

    private 


    def cf_legal 
     [ :Admin, :CF_Legal, :CF_Policy_Manager ] 
    end 

    def cf_content 
     [ :Admin, :CF_Author, :CF_Editor ] 
    end 


end 

Da ist in meinem Content-Richtlinien, möchte ich sagen:

def record 
    content 
end 

def create 
    user.has_role? :cf_content 
end 

Wenn ich diese speichern und versuchen Sie es, ich das Ding nicht sehen kann, was ich bin (als Benutzer mit der Rolle Autor sehen, soll

Kann jemand sehen, wie dies zu tun

Antwort

2

tl; dr:.? Verwenden Sie query mich thods in Ihrer Policy-Klasse.

Zunächst sollte das Modell über eine eigene Policy-Klasse verfügen, die (optional) die ApplicationPolicy-Klasse erweitert. Nehmen wir an, Ihr Modell heißt Post. Dann könnten Sie so etwas wie:

class PostPolicy < ApplicationPolicy 

    attr_reader :user, :post 

    def initialize(user,post) 
    @user = user 
    @post = post 
    end 

    def create? 
    cf_content.all? { |role| user.has_role?(role) } 
    end 

    private 

    def cf_content 
    [ :Admin, :Author, :Editor ] 
    end 
end 


class PostsController 
    def create 
    @post = Post.new(params[:post]) 
    authorize @post, :create? 
    # @post.save and redirect, etc. 
    end 
end 

Und das Autorisieren Aufruf der create? Abfragemethode und prüfen wird berufen, wenn der Benutzer die Rollen in cf_content hat.

Sie können nicht einmal das zweite Argument hinzufügen müssen, create? als Pandit documentation sagt:

Die authorise Methode folgert automatisch, dass Stellen Sie eine passende PostPolicy Klasse haben wird, und instanziiert diese Klasse, Gabe im aktuellen Benutzer und dem angegebenen Datensatz. Er leitet dann von der Aktion Name, dass es update aufrufen soll? für diese Instanz der Richtlinie.

Oder in Ihrem Fall, create? statt update?.

+0

Hallo Josh, ich verstehe nichts von dem, was Sie geschrieben haben. Ich werde meinen Beitrag bearbeiten, um meine Frage zu klären. – Mel

0

Ich glaube, Sie

has_any_role? 

verwenden müssen Welche vergangen zwei oder mehr Argumente als Symbole nimmt. Aber Ihre cf_content-Methode gibt ein Array zurück.Wenn der Benutzer die drei Rollen muss man in cf_create definiert haben müssen Sie etwas tun, eher wie

def create 
    cf_content.all? { |role| user.has_role?(role) } 
end 

UPDATE:

Wenn Sie nur eine Rolle als einfache Änderung:

def create 
    cf_content.any? { |role| user.has_role?(role) } 
end 

Außerdem bin ich mir nicht sicher, was diese darstellen, aber wenn sie die Namen Ihrer Rollen sind, würde ich vorschlagen, Kleinbuchstaben zu verwenden. Anstatt also

[ :Admin, :CF_Author, :CF_Editor ] 

Sie könnten verwenden:

[: admin,: cf_author,: cf_editor]

UPDATE 2:

Die has_role? akzeptiert kein Array. Also, wenn du has_role überprüfen willst? auf einem Array müssen Sie has_role iterieren? über jedes Element im Array. Seit: cf_content Methode zurückgibt und Anordnung von Rollen, dann von ändern:

def create 
    user.has_role? :cf_content 
end 

An:

def create 
    :cf_content.any? { |role| user.has_role?(role) } 
end 

Aber Sie haben nicht erklärt, wo Sie Ihre „Content-Richtlinie“ versuchen zu setzen.

+0

Der Benutzer benötigt nicht drei Rollen, er kann eine beliebige Rolle im Array haben. Die Rollen funktionieren in anderen Teilen der App im Titelfall. Wenn es also keinen punditspezifischen Grund gibt, alles in Kleinbuchstaben umzubenennen, behalte ich das so, wie es ist. Nicht sicher über die Show-Methode, es funktioniert gut, wie ich es habe. Mein Problem ist, wie man ein Array von Rollen als wahr an den Pandit übergeben kann, wenn der Benutzer eine der Rollen im Array hat. – Mel

+0

Siehe meine aktualisierte Antwort. Im Fall von Rollennamen empfahl ich die Benennungskonventionen von ruby ​​/ rails. Im Allgemeinen verwenden nur Klassen- oder Modulnamen Großbuchstaben, daher wurde ich von ihnen verwirrt und sogar die Stack-Überlaufsyntax hervorgehoben: Admin als wäre es ein Klassenname. Siehe https://github.com/bbatsov/ruby-style-guide#naming – lacostenycoder

+0

Hallo - Ihre Antwort macht immer noch keinen Sinn für mich (Entschuldigung, wenn ich den Punkt vermisse). Meine Show-Aktion funktioniert gut - darum bitte ich nicht. Ich möchte wissen, wie man ein Array von Rollen definiert, so dass, wenn der aktuelle Benutzer eine der Rollen im Array hat, die Pandit-Aktion erlaubt wird. Weißt du, wie ich meinen Code reparieren kann, um das zu ermöglichen? – Mel

1

Sie können, wie dies für mehrere Rollen überprüfen:

user.admin? oder user.author?

Wenn Sie aus einem Array für Rolle überprüfen möchten Sie auch mit überprüfen: cf_content.include (user.role) OR cf_content.include (user.role.title) je nachdem, was die scenairio passt?.

Sie können auch prüfen, ob eine gebundene Rolle mit -> user.applied_roles vorhanden ist und ob die zurückgegebenen Rollen die erwartete Rolle enthalten.

Verwandte Themen