2016-02-21 13 views
6

Próbuję zrobić aplikację z szynami 4.Szyny 4 - Pundit z Rolify - pozwalające grupę ról

I zdefiniowano szereg ról z Rolify gem.

Teraz chcę użyć pundit, aby umożliwić użytkownikom wykonywanie pewnych zadań. Tam, gdzie więcej niż jeden typ roli może coś zrobić, zdefiniowałem grupę ról.

W mojej application_policy zdefiniowałem prywatne metody, które określają grupy ról, które chcę użyć w uprawnieniach pseudonimu.

Moja polityka aplikacji tworzy instancję użytkownika i rekord. Następnie definiuję rekord jako nazwę odpowiedniego modelu (taką samą jak nazwa profilu dla tego modelu).

mam:

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 

Następnie w polityce zawartości, chcę powiedzieć:

def record 
    content 
end 

def create 
    user.has_role? :cf_content 
end 

Kiedy to zapisać i spróbować, nie widzę rzeczy, że jestem powinien zobaczyć (jako użytkownik z rolą Autor

Czy ktoś może zobaczyć, jak to zrobić

Odpowiedz

2

tl; dr:.? Wykorzystanie zapytań mnie thods na twojej klasie zasad.

Po pierwsze, model powinien mieć własną klasę zasad, która (opcjonalnie) rozszerza twoją klasę ApplicationPolicy. Załóżmy, że Twój model nazywa się Post. Następnie można zrobić coś takiego:

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 

a połączenie autoryzacji będzie wywołać metodę zapytania create? i sprawdzić, czy użytkownik ma role w cf_content.

Nie może nawet trzeba dodać drugi argument, create? jako pundit documentation mówi:

Metoda autoryzacji automatycznie wnioskuje, że post będzie mieć pasujący klasę PostPolicy oraz instancję tej klasy, wręczając w bieżącym użytkowniku i danym rekordzie. Następnie podaje nazwę działania, która powinna wywoływać aktualizację? w tym przypadku zasad.

Lub w twoim przypadku, create? zamiast update?.

+0

Cześć Josh, nie rozumiem żadnego z tego, co napisałeś. Będę edytować mój post, aby wyjaśnić moje pytanie. – Mel

0

Myślę, że trzeba użyć

has_any_role? 

który trwa dwa lub więcej args przekazany jako symbole. Ale twoja metoda cf_content zwraca tablicę.Jeśli użytkownik potrzebuje 3 role już zdefiniowane w cf_create trzeba zrobić coś więcej jak

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

UPDATE:

jeśli trzeba tylko jedną rolę niż prostą zmianę:

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

Ponadto, nie jestem pewien, co one reprezentują, ale jeśli są to nazwy twoich ról, sugerowałbym używanie małych liter. Więc zamiast

[ :Admin, :CF_Author, :CF_Editor ] 

Można użyć:

[: admin,: cf_author,: cf_editor]

UPDATE 2:

has_role? nie zaakceptuje tablicy. Więc jeśli chcesz sprawdzić has_role? w tablicy musisz iterować has_role? nad każdym elementem w tablicy. Od: cf_content metoda zwraca tablicę i ról, a następnie zmienić od:

def create 
    user.has_role? :cf_content 
end 

Do:

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

Ale nie wyjaśnił, gdzie staramy się umieścić swoją „politykę treści”.

+0

Użytkownik nie potrzebuje trzech ról, może mieć jedną z ról w tablicy. Role działają w innych częściach aplikacji w tytule, więc jeśli nie ma konkretnej przyczyny zmiany nazwy na małe, to zachowam to tak, jak jest. Nie jestem pewien co do metody show, działa dobrze, jak ja to mam. Mój problem polega na tym, jak uzyskać szereg ról, które można przekazać jako prawdziwe do pundit, jeśli użytkownik ma jakąkolwiek rolę w tablicy. – Mel

+0

Zobacz moją zaktualizowaną odpowiedź. Jeśli chodzi o nazwy ról, zalecałem stosowanie konwencji nazewnictwa ruby ​​/ rails. Ogólnie tylko nazwy klas lub modułów używają wielkich liter, więc pomyliłem się przez nie, a nawet podświetlono składnię przepełnienia stosu: Admin tak, jakby była nazwą klasy. Zobacz https://github.com/bbatsov/ruby-style-guide#naming – lacostenycoder

+0

Witam - odpowiedź nadal nie ma dla mnie sensu (przepraszam, jeśli brakuje mi punktu). Moja akcja pokazowa działa dobrze - nie o to proszę. Chcę wiedzieć, jak zdefiniować tablicę ról, więc jeśli bieżący użytkownik ma jedną z ról w tablicy - akcja pseuditowa będzie dozwolona. Czy wiesz, jak naprawić mój kod, aby tak się stało? – Mel

1

Możesz sprawdzić wiele ról tak:

user.admin? lub user.author?

Jeśli chcesz sprawdzić roli z tablicy można również skontaktować się z: cf_content.include (user.role) OR cf_content.include (user.role.title) cokolwiek jest scenairio?.

Można również sprawdzić role związane z instancją za pomocą -> user.applied_roles i sprawdzić, czy zwrócone role zawierają oczekiwaną rolę.