Using Rails 4.2.1, ActiveAdmin 1.0.0pre2, CanCanCan 1.13.1
I need to use session variables as part of my CanCan authorization. The reason I want this (instead of storing the variable in the database) is to enable an admin to have different roles on multiple simultaneous sessions.
According to this post it is or was possible using CanCan alone. But, CanCan itself does not have access to the session variables and so they should be passed in as an additional parameter when initializing an Ability.
I got to where I can successfully modify the CanCan adapter to pass additional parameters to the Ability.new method, but I am too uneducated in ruby/rails to create the correct context to access the session variables.
Here's what I tried:
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
The key modification (relative to original CanCanAdapter Module) is the line "klass.new user, session[:admin_role]" in which I added the second parameter 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
Although this method was successful in principle to pass a second variable to the Ability initialization, it throws up an exception because the session object is not accessible to the CanCanAdapter class.
(i.e. replace the line klass.new user, session[:admin_role] with e.g. a literal constant, and I can verify that the constant is passed to the Ability method).
So, the question becomes how can I access the session in the CanCan Adapter? According to this post, it is possible using ActionDispatch::Request.new(ENV), but I was unable to understand the discussion enough to make this work.
There have also been posts related to modifying the ActionController method as follows:
def current_ability
@current_ability ||= Ability.new(current_user, session) #added session parameter
end
but I was not able to find a place to put this code that made a difference.
Any help with my method, or suggestions for another method to accomplish the same thing, would be greatly appreciated.