【问题标题】:pundit_user: undefined method `current_user' for #<User:0x007fcefbc2b150>pundit_user:#<User:0x007fcefbc2b150> 的未定义方法“current_user”
【发布时间】:2015-11-26 08:43:03
【问题描述】:

我有两个布局 AdminDomain。而且我不需要在管理布局中进行任何额外的配置。但如果用户尝试访问 Domain 布局,则他们必须在其有效域中。

这意味着,我需要自定义我的所有 Domain 策略以包括 current_usercurrent_domain。我发现这可以用UserContextpundit_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_usercurrent_domain 必须根据文档在 UserPolicy 中可用 (https://github.com/elabs/pundit#additional-context)。

但我得到了

undefined method `current_user' for #<User:0x007fcefbc2b150>

也就是说,我仍然有用户对象,而不是 user.current_useruser.current_domain

如果您需要进一步的描述,请告诉我。我在这里错过了什么?

【问题讨论】:

  • 您使用的是哪个版本的 Pundit?
  • 它是pundit (1.0.1)

标签: ruby-on-rails ruby ruby-on-rails-4 devise pundit


【解决方案1】:

这是我自己的愚蠢错误。

问题

我在domain/base_controller.rb 打了一个before_filter 电话,类似于:

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 策略,因为现在我在application_controller 中同时设置了current_usercurrent_domainpundit_user

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

谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 2014-11-17
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    相关资源
    最近更新 更多