Question Comment utiliser les portées Pundit?


Je viens de passer à Pundit de CanCan. Je ne suis pas sûr de deux choses et de la meilleure façon d'utiliser Pundit. Par exemple.

Si vous avez une ressource pouvant avoir plusieurs objets parents, par exemple, supposons qu'un objectif appartient à un élève et à un instructeur. Ainsi, un étudiant peut avoir de nombreux objectifs et un instructeur peut avoir de nombreux objectifs. Dans une action d'index de contrôleur, vous pouvez effectuer:

if params[:student_id].present?
  @account = Student.find(params[:student_id])
  @goals = @account.goals
elsif params[:instructor_id].present?
  @account Instructor.find(params[:instructor_id])
  @goals = @account.goals
end

les paramètres ne sont pas utilisables dans les politiques, donc la logique doit être faite ici. Je pense. Pour ce que je peux dire, si vous ignorez le policy_scope, vous obtiendrez une erreur non autorisée lors de l'affichage de la page d'index pour les objectifs.

Voudriez-vous:

@goals = policy_scope(@account.goals)

OU

@goals = policy_scope(Goal.scoped).where( account_id: @account.id)

Que se passe-t-il lorsque vous lancez un tas d'inclusions dans le mix?

  @example = policy_scoped(@school.courses.includes(:account => :user, :teacher ))

Ou au besoin de commander ... est-ce correct?      policy_scope (Issue.scoped) .order ("created_at desc")

Lors de l'utilisation de scopes: Qu'est-ce que: scope ici? Est-ce que: scope est une instance du modèle en cours d'évaluation? J'ai essayé d'accéder à ses attributs via: scope, mais n'a pas fonctionné.

  class Scope < Struct.new(:user, :scope)

11
2018-01-31 00:47


origine


Réponses:


En lisant cela d'un point de vue de la sécurité, je peux voir quelques choses qui méritent d'être mentionnées. Par exemple, si vous autorisez les utilisateurs à spécifier le student_id et instructor_id les champs param, qu'est-ce qui les empêche de transmettre un identifiant à quelqu'un d'autre? Vous ne voulez jamais laisser un utilisateur spécifier qui il est, en particulier lorsque vous fondez des stratégies sur le type d'utilisateurs.

Pour commencer, j'implémenterais Devise et ajouterais un champ booléen supplémentaire appelé instructor ce serait true lorsque l'utilisateur était un instructeur, mais par défaut false pour les étudiants.

Alors votre Users aurait automatiquement un instructor? méthode définie, qui retournera true si la valeur dans le instructor la colonne est true.

Vous pourriez alors ajouter une aide pour les étudiants:

def student?
  !instructor?
end

Maintenant, en utilisant Devise (ce qui nous donne accès à un current_user variable) nous pouvons faire des choses comme current_user.instructor? qui reviendra true s'ils sont instructeur.

Passons maintenant à la politique elle-même. Je viens de commencer à utiliser Pundit il y a quelques semaines, mais c'est ce que je ferais dans votre situation:

class GoalPolicy < ApplicationPolicy
  class Scope < GoalPolicy
    attr_reader :user, :scope

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

    def resolve
      @scope.where(user: @user)
    end
  end
end

Alors votre (je suppose) GoalsController classe et index méthode) peut ressembler à:

def index
  policy_scope(Goal) # To answer your question, Goal is the scope
end

Si vous vouliez commander, vous pourriez aussi faire

def index
  policy_scope(Goal).order(:created_at)
end

Je viens de réaliser que vous avez posé cette question il y a six mois, mais bon! Peut-être répondra-t-il à certaines questions d'autres personnes et peut-être que j'aurai un retour sur mes propres compétences Pundit.


18
2017-08-20 00:09