2016-02-21 23 views
6

che sto cercando di fare un app con Rails 4.Rails 4 - Pundit con Rolify - permettendole di un gruppo di ruoli

Ho definito una serie di ruoli con Rolify gioiello.

Ora, voglio usare pundit per consentire agli utenti con un ruolo di fare determinate cose. Dove più di un tipo di ruolo può fare una cosa, ho definito un gruppo di ruoli.

Nella mia application_policy, ho definito metodi privati ​​che definiscono i gruppi di ruoli che voglio usare nelle autorizzazioni pundit.

La mia politica dell'applicazione consente di creare un'istanza dell'utente e registrare. Quindi definisco il record come nome del modello rilevante (lo stesso nome del criterio per quel modello).

ho:

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 

Poi nella mia politica di contenuti, voglio dire:

def record 
    content 
end 

def create 
    user.has_role? :cf_content 
end 

Quando ho salvare questo e provarlo, non riesco a vedere la cosa che io sono suppone di vedere (come utente con il ruolo Autore

qualcuno può vedere come fare questo

risposta

2

tl; dr:.? usarmi interrogare Thods sulla tua classe politica.

In primo luogo, il modello deve avere la propria classe politica che (facoltativamente) estende la classe ApplicationPolicy. Diciamo che il tuo modello si chiama Post. Allora si potrebbe fare qualcosa di simile:

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 

e la chiamata autorizzare richiamerà il metodo di query create? e verificare se l'utente ha i ruoli in cf_content.

Si può anche non essere necessario aggiungere il secondo argomento, create?, come il commentatore documentation dice:

Il metodo autorizzano ne deduce automaticamente che la Posta avrà una classe PostPolicy corrispondenza, e crea un'istanza di questa classe, consegna nell'utente attuale e nel record specificato. Quindi viene dal nome dell'azione , che dovrebbe chiamare l'aggiornamento? su questa istanza della politica.

O nel tuo caso, create? anziché update?.

+0

Ciao Josh, non capisco niente di quello che hai scritto. Modificherò il mio post per chiarire la mia domanda. – Mel

0

penso che è necessario utilizzare

has_any_role? 

che richiede due o più argomenti passati come simboli. Ma il tuo metodo cf_content sta restituendo un array.Se l'utente ha bisogno dei 3 ruoli che avete definito in cf_create Hai bisogno di fare qualcosa di più come

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

UPDATE:

Se avete solo bisogno un ruolo di semplice cambiamento:

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

Inoltre, non sono sicuro di ciò che rappresentano, ma se fossero i nomi dei tuoi ruoli, ti suggerirei di utilizzare lettere minuscole. Così, invece di

[ :Admin, :CF_Author, :CF_Editor ] 

È possibile utilizzare:

[: admin,: cf_author,: cf_editor]

UPDATE 2:

Il has_role? non accetterà un array. Quindi se vuoi controllare has_role? su un array devi iterare has_role? su ogni elemento dell'array. Dal: cf_content metodo restituisce e varietà di ruoli, quindi passa da:

def create 
    user.has_role? :cf_content 
end 

A:

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

Ma non hai spiegato cui si sta tentando di mettere la vostra "politica di contenuti".

+0

L'utente non ha bisogno di tre ruoli, può avere uno qualsiasi dei ruoli nell'array. I ruoli funzionano in altre parti dell'app in title case, quindi a meno che non ci sia un motivo specifico per rinominare tutto in lettere minuscole, allora lo terrò così com'è. Non sono sicuro del metodo show, funziona bene così come l'ho. Il mio problema è come ottenere un array di ruoli da passare come true a pundit se l'utente ha uno dei ruoli nell'array. – Mel

+0

Vedere la mia risposta aggiornata. Per quanto riguarda i nomi dei ruoli, raccomandavo l'uso delle convenzioni di denominazione di ruby ​​/ rails. Generalmente solo i nomi di classi o moduli usano maiuscole, quindi sono stato confuso da loro e anche la sintassi di overflow dello stack evidenziata: Admin come se fosse un nome di classe. Vedi https://github.com/bbatsov/ruby-style-guide#naming – lacostenycoder

+0

Ciao - la tua risposta non ha ancora senso per me (scusa se mi manca il punto). La mia azione mostra funziona bene - non è quello che sto chiedendo aiuto. Voglio sapere come definire un array di ruoli, in modo che se l'utente corrente ha uno dei ruoli nell'array, allora l'azione pundit sarà consentita. Sai come risolvere il mio codice per farlo accadere? – Mel

1

È possibile verificare la presenza di più ruoli come questo:

user.admin? o user.author?

Se si desidera verificare la presenza di ruolo da una matrice si può anche verificare con:? Cf_content.include (user.role) OR cf_content.include (user.role.title) a seconda di quale si adatta al scenairio?.

È anche possibile verificare i ruoli associati all'istanza con -> user.applied_roles e verificare se i ruoli restituiti includono il ruolo previsto.