我正在尝试将pundit与我的主动管理员集成并设计配置。但该应用程序很奇怪。它将模型/记录作为current_user。
我的政策文件:
class AdminUserPolicy
attr_reader :current_user, :model
def initialize(current_user, model)
Rails.logger.info '--------------- initialize called-------------------'
Rails.logger.info current_user
Rails.logger.info model
@current_user = current_user
@record = model
end
def index?
@current_user.admin?
end
end
控制器:
controller do
include Pundit
protect_from_forgery
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
before_action :authenticate_admin_user!
def index
authorize current_admin_user
super
end
private
def user_not_authorized
flash[:alert]="Access denied"
redirect_to (request.referrer || admin_root_path)
end
end
日志如下:
--------------- initialize called----------------------------------------
#<AdminUser:0x007f27733f8a80>
Completed 500 Internal Server Error in 364ms (ActiveRecord: 312.8ms)
NoMethodError (undefined method `admin?' for nil:NilClass):
app/policies/admin_user_policy.rb:13:in `index?'
app/admin/dashboard.rb:19:in `index'
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (4.8ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.5ms)
Rendering /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.1ms)
Rendered /usr/local/rvm/gems/ruby-2.3.4/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (39.5ms)
根据日志current_user=nil
和model=#<AdminUser:0x007f27733f8a80>
我将current_user与我的策略文件模型交换为
def index?
@record.admin?
end
它有效! 我不明白这种奇怪的行为。
答案 0 :(得分:1)
Pundit policy doc表示它调用current_user
方法来检索要发送到Policy类中initialize
方法的第一个参数的内容。如果您已使用current_admin_user
配置ActiveAdmin以检索当前登录用户,则必须覆盖ApplicationController
类中的权威默认方法,如下所示:Ref
class ApplicationController < ActionController::Base
// ...
def pundit_user
current_admin_user // or whatever based on ActiveAdmin initializer config
end
end
为了使定义的策略有效,您必须使用相应策略模型的实例在控制器操作中调用authorize
。因此,如果您有PostPolicy
并且想要授权update
操作,则必须执行以下操作:
controller do
def update
@post = Post.find(params[:id])
authorize @post // the current user will be automatically sent to the PostPolicy
super
end
end
authorize
方法自动推断Post
将具有匹配的PostPolicy
类,并实例化此类,交付当前用户和给定记录。然后从动作名称推断出它应该在此策略实例上调用update?
。在这种情况下,你可以想象authorize
会做这样的事情:
unless PostPolicy.new(current_user, @post).update?
raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
end
拥有所有这些,在您的情况下,如果您希望在查看所有用户列表之前授权用户,您可以像已经完成的那样定义AdminUserPolicy
。然后在index
的{{1}}操作中,
AdminUserController
如果要检查的权限名称与操作名称不匹配,则可以将第二个参数传递给controller do
def index
@users = AdminUser.all
authorize @users // NOT `authorize current_admin_user`
super
end
end
。例如:
authorize