Instantly share code, notes, and snippets.

Embed
What would you like to do?
Active Admin CanCan integration with shared front/backend User model and multi-level autherization
# app/models/ability.rb
# All front end users are authorized using this class
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
can :read, :all
end
end
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
# You don't need to modify any settings here to get CanCan to work
# Just remember to add CanCan to your Gemfile
# ...
end
# Below the ActiveAdmin.setup block, I've opened up the ActiveAdmin::ResourceController
# and modified the current_ability method to use a special AdminAbility class.
# Technically you can put this code almost anywere, but I've added it here because
# I think it belongs together with the other Active Admin initializer code.
ActiveAdmin::ResourceController.class_eval do
protected
def current_ability
@current_ability ||= AdminAbility.new(current_user)
end
end
# app/models/admin_ability.rb
# All back end users (i.e. Active Admin users) are authorized using this class
class AdminAbility
include CanCan::Ability
def initialize(user)
user ||= User.new
# We operate with three role levels:
# - Editor
# - Moderator
# - Manager
# An editor can do the following:
can :manage, Foobar
can :read, SomeOtherModel
# A moderator can do the following:
if user.role?('moderator')
can :manage, SomeOtherModel
end
# A manager can do the following:
if user.role?('manager')
can :manage, SomeThirdModel
end
end
end
# app/admin/foobars.rb
ActiveAdmin.register Foobar do
# This will authorize the Foobar class
# The authorization is done using the AdminAbility class
controller.authorize_resource
end
# app/models/user.rb
class User < ActiveRecord::Base
# The order of the ROLES array is important!
# All privileges are inherited from left to right
ROLES = %w(editor moderator manager)
# Privileges are inherited between roles in the order specified in the ROLES
# array. E.g. A moderator can do the same as an editor + more.
#
# This method understands that and will therefore return true for moderator
# users even if you call `role?('editor')`.
def role?(base_role)
return false unless role # A user have a role attribute. If not set, the user does not have any roles.
ROLES.index(base_role.to_s) <= ROLES.index(role)
end
end
@amalagaura

This comment has been minimized.

Show comment
Hide comment
@amalagaura

amalagaura Dec 1, 2011

This is very helpful, but didn't you have to customize the routes.rb?

amalagaura commented Dec 1, 2011

This is very helpful, but didn't you have to customize the routes.rb?

@watson

This comment has been minimized.

Show comment
Hide comment
@watson

watson Jan 19, 2012

Sorry about the late reply - no I don't think I did. I have a customization, but that is just for using a login form. Don't think it matters in this case.

Owner

watson commented Jan 19, 2012

Sorry about the late reply - no I don't think I did. I have a customization, but that is just for using a login form. Don't think it matters in this case.

@stigi

This comment has been minimized.

Show comment
Hide comment
@stigi

stigi Feb 25, 2012

I added config.before_filter :check_admin_role to ActiveAdmin.setup and implemented a filter like this inside ActiveAdmin::ResourceController.class_eval do

  def check_admin_role
    return if current_user.role?(:admin)
    flash[:notice] = "You need to be an admin to access this part of the application"
    redirect_to root_path
  end

stigi commented Feb 25, 2012

I added config.before_filter :check_admin_role to ActiveAdmin.setup and implemented a filter like this inside ActiveAdmin::ResourceController.class_eval do

  def check_admin_role
    return if current_user.role?(:admin)
    flash[:notice] = "You need to be an admin to access this part of the application"
    redirect_to root_path
  end
@dlupu

This comment has been minimized.

Show comment
Hide comment
@dlupu

dlupu Mar 14, 2012

Thanks @stigi. Your solution is perfect for my needs !

dlupu commented Mar 14, 2012

Thanks @stigi. Your solution is perfect for my needs !

@stigi

This comment has been minimized.

Show comment
Hide comment
@stigi

stigi Mar 14, 2012

@dlupu: glad I could help. will think about how all the valuable information in this git can be presented better. don't remember how I found it in the first place ;)

stigi commented Mar 14, 2012

@dlupu: glad I could help. will think about how all the valuable information in this git can be presented better. don't remember how I found it in the first place ;)

@pedroassumpcao

This comment has been minimized.

Show comment
Hide comment
@pedroassumpcao

pedroassumpcao Apr 20, 2012

I think we need to use the current_admin_user in the active_admin initializer:

 def current_ability
   @current_ability ||= AdminAbility.new(current_admin_user)
 end

pedroassumpcao commented Apr 20, 2012

I think we need to use the current_admin_user in the active_admin initializer:

 def current_ability
   @current_ability ||= AdminAbility.new(current_admin_user)
 end
@amiel

This comment has been minimized.

Show comment
Hide comment
@amiel

amiel Apr 28, 2012

@watson: Thanks, this is very helpful.

amiel commented Apr 28, 2012

@watson: Thanks, this is very helpful.

@imderek

This comment has been minimized.

Show comment
Hide comment
@imderek

imderek Jun 20, 2012

Once again, very helpful. Thanks!

imderek commented Jun 20, 2012

Once again, very helpful. Thanks!

@yorch

This comment has been minimized.

Show comment
Hide comment
@yorch

yorch Jul 27, 2012

Thanks @stigi, works great.. just a minor fix (rolify 3.1.0):

def check_admin_role
  return if current_user.has_role?(:admin)
  flash[:notice] = "You need to be an admin to access this part of the application"
  redirect_to root_path
end

yorch commented Jul 27, 2012

Thanks @stigi, works great.. just a minor fix (rolify 3.1.0):

def check_admin_role
  return if current_user.has_role?(:admin)
  flash[:notice] = "You need to be an admin to access this part of the application"
  redirect_to root_path
end
@maxinuss

This comment has been minimized.

Show comment
Hide comment
@maxinuss

maxinuss Oct 1, 2012

Hey guys, how can add a role to a User?

maxinuss commented Oct 1, 2012

Hey guys, how can add a role to a User?

@mhuggins

This comment has been minimized.

Show comment
Hide comment
@mhuggins

mhuggins Jan 28, 2013

@maxinuss - You probably want to refer to this.

mhuggins commented Jan 28, 2013

@maxinuss - You probably want to refer to this.

@developer88

This comment has been minimized.

Show comment
Hide comment
@developer88

developer88 Feb 21, 2013

Thanks for your gist. I use it to create my own https://gist.github.com/developer88/5007569
Main difference is that i store permission in database.

developer88 commented Feb 21, 2013

Thanks for your gist. I use it to create my own https://gist.github.com/developer88/5007569
Main difference is that i store permission in database.

@murtuzakz

This comment has been minimized.

Show comment
Hide comment
@murtuzakz

murtuzakz Dec 13, 2013

I tried the above code. My index page /admin/users, still shows me list of all users, Even though for the user that is logged in, I have given him ability to only manage users from his organization.
The permissions work fine for show and edit.
Can someone please help?

murtuzakz commented Dec 13, 2013

I tried the above code. My index page /admin/users, still shows me list of all users, Even though for the user that is logged in, I have given him ability to only manage users from his organization.
The permissions work fine for show and edit.
Can someone please help?

@jackxu

This comment has been minimized.

Show comment
Hide comment
@jackxu

jackxu Aug 12, 2015

I do not know why it is not updated, but nowadays it is recommended to simple the cancan gem with Active_Admin. Here is the link http://activeadmin.info/docs/13-authorization-adapter.html#using_the_cancan_adapter

jackxu commented Aug 12, 2015

I do not know why it is not updated, but nowadays it is recommended to simple the cancan gem with Active_Admin. Here is the link http://activeadmin.info/docs/13-authorization-adapter.html#using_the_cancan_adapter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment