2016-09-21 3 views
0

Je suis novice en matière d'auteur et j'essaie de trouver la meilleure approche pour gérer les ressources imbriquées pour l'action d'index. J'ai trouvé un similar question mais il ne traite pas des privilèges d'administrateur et je ne suis pas sûr si ma solution semble tout à fait raison. Disons que j'ai deux modèles, un User peut avoir beaucoup de notes et un Note qui appartient à un seul utilisateur.Privilèges d'administrateur dans Pundit avec des ressources imbriquées et comment gérer l'action d'index

Les utilisateurs ne peuvent pas regarder les notes d'autres utilisateurs à moins qu'ils ne soient un administrateur. En même temps, les administrateurs sont capables de créer leurs propres notes et doivent donc avoir la possibilité d'en récupérer une liste via leur propre action d'index.

routes.rb

resources :users, only: :show do 
    resources :notes 
end 

notes_controller.rb

class NotesController < ApplicationController 

    #would probably move to application_controller.rb 
    after_action :verify_authorized 
    after_action :verify_policy_scoped 

    def index 
    user = User.find(params[:user_id]) 
    @notes = policy_scope(user.notes) 
    authorize user 
    end 

    #additional code 
end 

note_policy.rb

class NotePolicy < ApplicationPolicy 

    class Scope < Scope 
    def resolve 
     if user.admin? && scope != user.notes 
     scope 
     else 
     user.notes 
     end 
    end 
    end 

    #additional code 
end 

user_policy.rb

class UserPolicy < ApplicationPolicy 

    def index? 
    user == record || user.admin? 
    end 

    #additional code 
end 

Répondre

0

Vous Overthinking il:

class NotePolicy < ApplicationPolicy 

    class Scope < Scope 
    def resolve 
     scope.where(user: user) 
    end 
    end 

    def index? 
    record == user || user.admin? 
    end 

    # ... 
end 

Notez ici que son une bonne idée de la chaîne du champ d'application étant passée à partir de policy_scope. Il permet à votre contrôleur de configurer toutes les étendues non liées à l'autorisation comme par exemple la pagination.

Toujours dans index? nous trichons légèrement. Au lieu de passer une instance de note, nous ne faisons que passer l'utilisateur.

class NotesController < ApplicationController 

    before_action :set_user!, only: [:index] # ... 
    before_action :set_note!, only: [:show, :edit, :update, :destroy] 

    def index 
    @notes = policy_scope(Note.all) 
    authorize(@user) 
    end 

    # ... 

    private 
    def set_user! 
     @user = User.find(params[:user_id]) 
    end 

    def set_note! 
     @note = authorize(Note.find(params[:id])) 
    end 
end 

L'utilisation before_action de cette façon est un modèle assez bon car il met en place toutes les actions « membres » d'autorisation.

+0

Merci pour la réponse max et j'apprécie l'exemple. Le principal problème avec lequel je me bats est de savoir comment donner à un administrateur la possibilité d'afficher des notes d'autres utilisateurs (en plus des leurs) lors de la visite de différentes pages d'index. Je préfère ne pas polluer le contrôleur avec cette logique si possible, mais il ne semble pas y avoir de moyen simple de transmettre à pundit une variable params supplémentaire à vérifier. Je comprends, c'est par la conception, mais il y a probablement un moyen plus propre de l'atteindre que ce que j'ai trouvé jusqu'à présent. Je manque probablement quelque chose. – Dom