Skip to content

Instantly share code, notes, and snippets.

@bbonamin
Forked from watson/ability.rb
Created October 5, 2011 15:02
Show Gist options
  • Save bbonamin/1264650 to your computer and use it in GitHub Desktop.
Save bbonamin/1264650 to your computer and use it in GitHub Desktop.
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 to the following:
can :manage, Foobar
can :read, SomeOtherModel
# A moderator can to the following:
if user.role?('moderator')
can :manage, SomeOtherModel
end
# A manager can to the following:
if user.role?('manager')
can :manage, SomeThirdModel
end
end
end
# app/admin/foobars.rb
ActiveAdmin.register Foobar do
# This will authorize the SomeModel 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment