【问题标题】:using session variables in CanCan with ActiveAdmin在 CanCan 中使用 ActiveAdmin 中的会话变量
【发布时间】:2016-10-04 04:02:03
【问题描述】:

使用 Rails 4.2.1、ActiveAdmin 1.0.0pre2、CanCanCan 1.13.1

我需要使用会话变量作为我的 CanCan 授权的一部分。我想要这个(而不是将变量存储在数据库中)的原因是使管理员能够在多个同时会话中拥有不同的角色。

根据this post 可以或曾经可以单独使用 CanCan。但是,CanCan 本身无法访问会话变量,因此在初始化能力时它们应该作为附加参数传入。

我可以成功修改 CanCan 适配器以将其他参数传递给 Ability.new 方法,但我在 ruby​​/rails 方面没有受过教育,无法创建正确的上下文来访问会话变量。

这是我尝试过的:

config/initializers/active_admin.rb

#the usual
config.authorization_adapter = ActiveAdmin::CanCanAdapter  
:
:
#at end of file, modify the standard CanCanAdapter class:
module ActiveAdmin
  class CanCanAdapter < ActiveAdmin::AuthorizationAdapter
    def initialize_cancan_ability
      klass = resource.namespace.cancan_ability_class
      klass = klass.constantize if klass.is_a? String
      klass.new user, session   
    end
  end
end

关键修改(相对于原始 CanCanAdapter 模块)是“klass.new user, session[:admin_role]”行,我在其中添加了第二个参数 session[:admin_role]。

app/models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user, session) 
    user ||= User.new # guest user (not logged in)
    if user.is_admin? && session[:admin_role]==User.ROLE_ADMINISTERING
      can :manage, :all
    end
    :
    #other types of authorizations
    :
  end
end

虽然此方法原则上成功地将第二个变量传递给 Ability 初始化,但它会引发异常,因为 CanCanAdapter 类无法访问 session 对象。

(即用文字常量替换 klass.new user, session[:admin_role] 行,我可以验证该常量是否已传递给 Ability 方法)。

那么,问题就变成了如何访问 CanCan 适配器中的会话? 根据this post 的说法,可以使用 ActionDispatch::Request.new(ENV),但我无法充分理解讨论以完成这项工作。

也有过修改ActionController方法相关的帖子如下:

def current_ability
  @current_ability ||= Ability.new(current_user, session) #added session parameter
end

但我无法找到放置此代码的地方。

如果对我的方法有任何帮助,或者对完成同样事情的另一种方法提出建议,我们将不胜感激。

【问题讨论】:

    标签: ruby-on-rails session session-variables activeadmin cancancan


    【解决方案1】:

    我不知道这是否是执行此操作的“正确”方式,但它对我有用:

    首先,我添加了来自https://github.com/steveklabnik/request_store的request_store gem

    gem 'request_store'
    

    其次,我将此添加到我的 application_controller.rb 以保存会话数据。

      before_filter :store_session_data
    
      def store_session_data
        RequestStore.store[:session] = session
      end
    

    第三,我修改了你修改后的适配器:

    module ActiveAdmin
      class CanCanAdapter < ActiveAdmin::AuthorizationAdapter
        def initialize_cancan_ability
          klass = resource.namespace.cancan_ability_class
          klass = klass.constantize if klass.is_a? String
          klass.new user, RequestStore.store[:session]   
        end
      end
    end
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-15
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多