我有两个布局Admin
和Domain
。我不需要在Admin布局中进行任何额外配置。但如果用户尝试访问Domain
布局,则他们必须位于有效域中。
这意味着,我需要自定义我的所有Domain
政策,以同时包含current_user
和current_domain
。我发现可以使用UserContext
和pundit_user
完成此操作...所以这就是我所做的:
application_controller.rb
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def pundit_user
UserContext.new(current_user, current_domain)
end
def after_sign_out_path_for(resource)
root_path
end
def current_domain
@current_domain ||= Domain.where(name: requested_domain).first
end
helper_method :current_domain
private
def requested_domain
return request.env["SERVER_NAME"]
end
def user_not_authorized
# reset_session
flash[:alert] = "You are not authorized to perform this action"
redirect_to(request.referrer || root_path)
end
end
请注意,当我访问Admin
布局时,current_domain将为nil
,如果我访问Domain
布局的任何路由,则current_domain
将设置为当前访问域
user_context.rb
class UserContext
attr_reader :current_user, :current_domain
def initialize(current_user, current_domain)
@current_user = current_user
@current_domain = current_domain
end
end
假设我有这个政策:
user_policy.rb
class UserPolicy < ApplicationPolicy
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def index?
binding.pry # debugging
current_user.admin? ||
current_user.domain == current_domain
end
private
def current_user
# return user.is_a?(User) ? user : user.current_user
user.current_user
end
def current_domain
# return user.is_a?(User) ? nil : user.current_domain
user.current_domain
end
end
当应用程序运行current_user
时,必须根据文档(https://github.com/elabs/pundit#additional-context)在UserPolicy中提供current_domain
。
但我得到了
undefined method `current_user' for #<User:0x007fcefbc2b150>
这意味着,我仍然有用户对象,而不是user.current_user
和user.current_domain
如果您需要进一步说明,请告诉我。我在这里缺少什么?
答案 0 :(得分:0)
这是我自己的愚蠢错误。
<强> 问题 强>
我在before_filter
中拨打domain/base_controller.rb
电话:
class Domain::BaseController < ApplicationController
before_action :authenticate_user!
before_action :domain_exists?
before_action :verify_domain!
private
def verify_domain!
# PROBLEM: this line was updating pundit_user again to user object
raise Pundit::NotAuthorizedError unless DomainConsolePolicy.new(current_user, current_domain).authorized?
end
def domain_exists?
if current_domain.blank?
redirect_to root_path, alert: 'Domain that you provided is not valid or is permanently removed!'
end
end
end
解决方案:
我已使用headless
政策,因为现在current_user
current_domain
和pundit_user
都设有application_controller
domain/base_controller.rb
class Domain::BaseController < ApplicationController
before_action :authenticate_user!
before_action :domain_exists?
before_action :verify_domain!
private
def verify_domain!
# SOLUTION
authorize :domain_console, :has_access?
end
def domain_exists?
if current_domain.blank?
redirect_to root_path, alert: 'Domain that you provided is not valid or is permanently removed!'
end
end
end
policy/domain_console_policy.rb
class DomainConsolePolicy < Struct.new(:user, :domain_console)
def has_access?
user.current_user.admin? ||
user.current_user.domain_id == user.current_domain.id
end
end
由于