Rails 专家用户范围 Minitest 不会 运行

Rails pundit user scope Minitest won't run

在我的应用程序中,只有 status == 'active' 的用户才能访问所有应用程序页面。我已经为该操作创建了一个范围策略和一个单独的中间控制器,我在其中设置了所有全局策略。如下:

class UserPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      return raise(Pundit::NotAuthorizedError) unless user.status == 'active'

      scope.all
    end
  end
end

class BaseController < ApplicationController
  before_action :authorized_user
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  def authorized_user
    policy_scope(current_user)
  end

  private

  def user_not_authorized
    flash[:alert] = 'You are not authorized to perform this action.'
    redirect_to(request.referrer || root_path)
  end
end

现在我想为此范围策略创建一个 MiniTest。这就是我得到的:

需要'test_helper'

class UserPolicyTest < ActiveSupport::TestCase
  context 'when user is active' do
    def setup
      @user = user(:active)
      @properties = properties(:one)
    end

    def scope_test
      # user should have access to the show page in properties controller
      refute_equal properties, user
      assert permit(user, properties, :show)
    end
  end
end

我错过了什么?当我 运行 这显示我:

Finished in 0.185689s, 0.0000 runs/s, 0.0000 assertions/s.
0 runs, 0 assertions, 0 failures, 0 errors, 0 skips

你完全搞反了。它不是控制整体访问的作用域的工作。

class ApplicationPolicy

  class Scope
    def resolve
      @user.active?
        scope.all
      else
        scope.none
      end
    end
  end

  # ...

  def show?
    @user.active?
  end 

  def index?
    @user.active?
  end


  private

  def active?
    user.active? # user.status == 'active' is iffy. Don't let the logic leak outside of the object
  end
end

如果您想授权控制器的操作,您可以这样做:

def show
  authorize(Thing.find(params[:id]))
end

def index
  authorize(Thing) # controlls overall access - often skipped
  @things = policy_scope(Thing)
end

如果您真的想向 show 方法添加范围,您可以这样做:

def show
  authorize(policy_scope(Thing).find(params[:id]))
end

您的作用域不应控制整体访问的原因是它不知道上下文(调用哪个操作)。因此,虽然这现在可能“有效”,但当事情变得更加复杂时,它会在你面前爆炸。

如果您随后想要测试特定的政策,您可以这样做:

assert ThingPolicy.new(thing, user).show?

如果您想测试一个范围,您可以解析该范围并测试预期的记录是否包含 included/not。