了解如何使用Pundit

时间:2015-06-14 22:42:10

标签: ruby-on-rails ruby devise pundit

我一直试图围绕政策的概念,这似乎很简单 - 政策是一套规则,通过它们可以确定对系统权限和资源的访问权。

足够简单。

因此,为了让系统内的用户访问该系统中的每个其他用户的列表,他们需要必要的凭据(例如,可能是管理员或仅仅是作为注册登录用户)。即使是最基本的层面,我正在努力理解的是如何实际使用Pundit来实现这一目标。就像我试图学习的许多开源软件的文档一样,Pundit文档似乎充其量地提到了该工具应该如何工作,但没有提供一个基本的完整和具体的例子。用例。我在这里寻找的只是一个“你好世界”的例子,所以我不会花费三到四天的时间将一个混乱和半工作的实现拼凑在一起这样的小事。此外,Pundit提供的例子只会让事情更加混乱。

我基本上创建了一个测试应用程序,试图使用Devise(我似乎理解并能够使用得很好)和Pundit的组合。到目前为止:

  • 用户可以在网站上注册。
  • 用户可以登录并注销。

现在,我想要做的事情 - 这是一个非常基本的事情,可能不应该让我的眉头如此迅速 - 是限制用户根据他们是否被记录访问用户索引页面进入系统,就在这里,我完全陷入困境。

到目前为止我尝试了什么?

  • 我按照文档安装了Pundit。
  • 我在我的application_controller.rb
  • 中包含了Pundit
  • 我已经生成了一个用户政策,如下所示:

    class UserPolicy < ApplicationPolicy
      class Scope < Scope
        puts "Inside UserPolicy scope."
        attr_reader :user
    
        def initialize(user)
          @user = user
        end
    
        def index
          puts "You've hit the index."
        end
    
        def resolve
          scope
        end
      end
    end
    
    
    class UsersController < ApplicationController
      before_filter :authenticate_user!
      after_action :verify_authorized
      def index
        @users = User.all
        authorize current_user
      end
    end
    

此时,我完全迷失了如何将两者联系起来 - UserPolicy类和UsersController。

我似乎至少能够在我的控制台上打印消息“Inside UserPolicy scope”。但否则只能在浏览器中看到以下错误消息:

“不允许索引?这个#”

我缺少什么,如果没有别的,我自己知道的差距在哪里使得这个和其他与Rails相关的工具难以学习?我是一名专业的软件工程师(历史上,我曾经是一名前端工程师,并且在过去几年里一直致力于成为一名全栈工程师),但我发现自己经常被打开 - 像这样的源工具。

2 个答案:

答案 0 :(得分:2)

您的实施有一些问题:

  1. 操作授权(例如index?)进入父UserPolicy类,而不是内部Scope类。
  2. 授权电话的结果需要返回truefalse。您的index?调用会返回puts "You've hit the index.",其评估结果为nil
  3. 根据用户是否登录来控制访问权限是身份验证,而不是授权。 Pundit只应在用户通过身份验证后接管。

答案 1 :(得分:1)

Pundit实际上只是简单的红宝石对象,设置在类似于结构的轨道中。

我认为您的困惑是试图授权用户,从资源的角度考虑更多。您通过特定的休息操作限制用户访问某个对象。范围限制了他们可以看到的内容,例如,admin可能会执行scope.all,可能不允许单个用户或只能在用户控制器上自行调整范围。

在我的应用程序策略中,我定义帮助程序以对某些类型的用户进行分组。这是一个例子。

class TicketPolicy < ApplicationPolicy
  class Scope < Struct.new(:user, :scope)
     def resolve
       #Allows government to see their organization
       # only allows citizens to see nothing
       if user.government?
         scope.where(:organization_id => user.organization_id)
       else
         scope.where(:id => 0)
       end
     end
  end


  def index?
    is_government
  end

  def show?
    is_government && is_inside_organization(@record)
  end

  def create?
    is_government && is_inside_organization(@record)
  end

  def new?
    is_government && is_inside_organization(@record)
  end

  def update?
    is_government && is_inside_organization(@record)
  end

  def edit?
    if user.employee?
      return is_mine(@record) && is_inside_organization(@record)
    end
    is_government && is_inside_organization(@record)
  end

  def destroy?
    false
  end
end

这限制了对组/角色的访问,然后在我的控制器中我只需要调用

authorize @thing

然后权威人员将根据政策处理访问权限。