在CanCan中使用ActiveAdmin中的会话变量

时间:2016-06-04 01:03:22

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

使用Rails 4.2.1,ActiveAdmin 1.0.0pre2,CanCanCan 1.13.1

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

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

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

这是我尝试的内容:

配置/初始化/ 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模块)是行&#34; klass.new用户,会话[:admin_role]&#34;我在其中添加了第二个参数session [:admin_role]。

应用程序/模型/ 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类无法访问会话对象。

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

那么,问题是如何在CanCan适配器中访问会话? 根据{{​​3}},可以使用ActionDispatch :: Request.new(ENV),但我无法理解这个讨论足以使其发挥作用。

还有一些与修改ActionController方法相关的帖子如下:

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

但是我无法找到一个能让这个代码有所作为的地方。

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

1 个答案:

答案 0 :(得分:0)

我不知道这是否是“正确”的方法,但它对我有用:

首先,我从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

希望这有帮助。