如何使用权威范围?

hel*_*ion 11 authorization ruby-on-rails-4 pundit

我刚刚从CanCan切换到Pundit.我不确定有几件事,以及如何最好地使用Pundit.例如.

如果您有一个可以有多个父对象的资源,例如可以说一个目标属于一个学生和教师.因此,学生可以有很多目标,教师可以有很多目标.在控制器索引操作中,您可能会:

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
Run Code Online (Sandbox Code Playgroud)

params在策略中不可用,因此逻辑需要在这里完成.我认为.据我所知,如果您跳过policy_scope,在查看目标索引页时会出现未经授权的错误.

你会:

@goals = policy_scope(@account.goals)
Run Code Online (Sandbox Code Playgroud)

要么

@goals = policy_scope(Goal.scoped).where( account_id: @account.id)
Run Code Online (Sandbox Code Playgroud)

当你在混合中抛出一堆包含时会发生什么?

  @example = policy_scoped(@school.courses.includes(:account => :user, :teacher ))
Run Code Online (Sandbox Code Playgroud)

或者当需要订购时......这是正确的吗?policy_scope(Issue.scoped).order("created_at desc")

使用范围时:什么是:范围在这里?是:范围正在评估的模型的实例?我试过通过:scope访问它的属性,但是没有用.

 policy_scope(Issue.scoped).order("created_at desc")
Run Code Online (Sandbox Code Playgroud)

Sau*_*aul 19

从安全角度来看,我可以看到一些值得一提的东西.例如,如果您允许用户指定student_idinstructor_idparam字段,那么阻止他们为其他人传递ID的是什么?您不希望让用户指定他们是谁,尤其是当您基于用户类型制定策略时.

对于初学者,我会实现Devise并添加一个额外的布尔字段instructor,true当用户是教师但默认false为学生时.

那么你的Users会自动instructor?定义一个方法,true如果instructor列中的值是,则会返回true.

然后,您可以为学生添加帮助:

def student?
  !instructor?
end
Run Code Online (Sandbox Code Playgroud)

现在使用Devise(它允许我们访问一个current_user变量),我们可以做一些事情current_user.instructor?,true如果他们是一个教练,将会返回.

现在谈谈政策本身.几周前我刚刚开始使用Pundit,但这就是我在你的情况下所做的事情:

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
Run Code Online (Sandbox Code Playgroud)

然后你的(我假设GoalsController类和index方法)方法可以看起来像:

def index
  policy_scope(Goal) # To answer your question, Goal is the scope
end
Run Code Online (Sandbox Code Playgroud)

如果你想订购,你也可以

def index
  policy_scope(Goal).order(:created_at)
end
Run Code Online (Sandbox Code Playgroud)

我才意识到半年前你问过这个问题,但是嘿!也许它会回答其他人的一些问题,也许我会得到一些关于我自己萌芽的Pundit技能的反馈.