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。
在我的应用程序中,只有 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。