Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
This is my gist that show how we can use CanCan with ActiveAdmin and store permissions in database.
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.current_user_method = :current_user
config.authentication_method = :authenticate_user!
config.before_filter :admin_role_filter
end
# Adding all recource names to Permissions table after ActiveAdmin is loaded
ActiveAdmin.after_load do |app|
# check if Permission table exists
if ActiveRecord::Base.connection.table_exists? 'permissions'
app.namespaces.each do |name, namespace|
namespace.resources.each do |resource|
next if resource.class.name.demodulize == 'Page'
resource_name = resource.resource_class_name.demodulize.underscore
Permission.create(name: resource_name) unless Permission.where(:name => resource_name).any?
end
end
end
end
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
# restrict abilities to every user
cannot :manage, :all
cannot :read, :all
cannot :edit, :all
# check ability stored in database
if user.is? :admin
can do |action, subject_class, subject|
user.as_admin_can?(subject_class)
end
end
end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def admin_role_filter
unless current_user.is?(:admin)
return redirect_to root_url
end
end
end
# app/models/permissation.rb
class Permissation < ActiveRecord::Base
belongs_to :user
belongs_to :permission
end
# app/models/permission.rb
class Permission < ActiveRecord::Base
has_many :permissations
has_many :users, through: :permissations
end
# db/migrate/123456789_create_permissions_table.rb
class CreatePermissionsTable < ActiveRecord::Migration
def up
# Create table
create_table :permissations do |t|
t.integer :user_id
t.integer :permission_id
end
create_table :permissions do |t|
t.string :name
t.timestamps
end
# Create necessary permissions
%w{permission user}.each {|p| Permission.create(name: p)}
# By default give these permissions to everyone with 'admin' role
User.find_each(:batch_size => 5000) do |user|
next unless user.is? :admin
user.permissions << Permission.find_by_name('permission')
user.permissions << Permission.find_by_name('user')
user.save
end
end
def down
drop_table :permissions
drop_table :permissations
end
end
# app/models/user.rb
class User < ActiveRecord::Base
ROLES = %w[admin manager editor]
has_many :permissions, through: :permissations
accepts_nested_attributes_for :permissions
attr_accessible :permission_ids
# check user's permission for ActiveAdmin
def as_admin_can? obj
permissions.where(:name => obj.to_s.underscore).count > 0
end
def roles
ROLES.reject do |r|
((roles_mask || 0) & 2 ** ROLES.index(r)).zero?
end
end
def is?(role)
roles.include?(role.to_s)
end
end
# any ActiveAdmin Resource
# app/admin/users.rb
ActiveAdmin.register User do
controller.authorize_resource
menu :parent => proc{ I18n.t("active_admin.menu.users") }, :if => proc{ current_user.as_admin_can?(User) }
index do
if current_user.as_admin_can? 'permission'
column I18n.t("activerecord.models.permission") do |user|
user.permissions.collect {|p| p.name.camelize }.join(", ")
end
end
end
form do |f|
if current_user.as_admin_can? 'permission'
f.inputs I18n.t("activerecord.models.permission") do
f.input :permissions, :as => :check_boxes, :collection => f.object.permissions | Permission.all
end
end
f.actions
end
end

vanderv commented Jul 2, 2013

Hi! Where you get role_mask?

  def roles
    ROLES.reject do |r|
      ((roles_mask || 0) & 2 ** ROLES.index(r)).zero?
    end
  end 

cdesch commented Jan 9, 2014

Can you post a full working example App using this feature?

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