Skip to content

Instantly share code, notes, and snippets.

@kivanio
Forked from Fire-Dragon-DoL/ability.rb
Last active August 29, 2015 14:16
Show Gist options
  • Save kivanio/b11f398fb75c606a6c97 to your computer and use it in GitHub Desktop.
Save kivanio/b11f398fb75c606a6c97 to your computer and use it in GitHub Desktop.
class Ability
include CanCan::Ability
attr_reader :current_user
def initialize(user)
alias_action :create, :update, :destroy, :to => :write
@current_user = user || User.new
public_send(current_user.role)
end
def guest
end
def user
end
def manager
can :read, ActiveAdmin::Page, name: 'Dashboard'
can [:read, :update], User, User.where(id: current_user.id) do |user|
user.id == current_user.id
end
end
def publisher
can :read, ActiveAdmin::Page, name: 'Dashboard'
can [
:create,
:read,
:update
], User, User.accessibles_for(current_user) do |user|
user.accessible_for? current_user
end
can :destroy, User, User.where.not(id: current_user.id) do |user|
user.id != current_user.id
end
end
def developer
can :read, ActiveAdmin::Page, name: 'Dashboard'
can :manage, User
cannot :destroy, User
can :destroy, User, User.where.not(id: current_user.id) do |user|
user.id != current_user.id
end
end
end
ActiveAdmin.register User do
permit_params do
[:email].tap do |allowed_params|
if params[:user] && current_user.has_access_for?(params[:user][:role])
allowed_params << :role
end
if [:new, :create].include?(params[:action].try(:to_sym))
allowed_params << :password
allowed_params << :password_confirmation
else
if params[:user] && params[:user][:password].present?
allowed_params << :password
allowed_params << :password_confirmation
end
end
end
end
config.filters = false
# XXX: Very important, disable batch actions because they don't check cancan
# permissions. It probably can be worked around, check the following
# links:
# http://www.activeadmin.info/docs/9-batch-actions.html
# https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities-with-Blocks
# https://github.com/CanCanCommunity/cancancan/wiki/Fetching-Records
config.batch_actions = false
index download_links: false do
column :email do |user|
link_to user.email, admin_user_path(user)
end
column :role do |user|
I18n.t(user.role, scope: 'authorization.roles')
end
column :current_sign_in_at
column :sign_in_count
actions
end
form do |f|
f.inputs I18n.t('admin.resources.user.details') do
f.input :email
if user.accessible_for?(current_user) && current_user.id != user.id
f.input :role, as: :select,
collection: User.i18n_roles,
include_blank: false
end
f.input :password
f.input :password_confirmation
end
f.actions
end
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable, :lockable
ROLES = %i(guest user manager publisher developer).freeze
ROLES_ACCESSIBILITY = HashWithIndifferentAccess.new({
guest: [].freeze,
user: [].freeze,
manager: %i(guest user manager).freeze,
publisher: %i(guest user manager publisher).freeze,
developer: %i(guest user manager publisher developer).freeze
}).freeze
enum role: ROLES
validates :email, presence: true, uniqueness: true, email: true
validates :password, presence: true, if: -> { new_record? }
validates :password_confirmation, presence: true, if: -> { new_record? }
def has_access_for?(other_role)
ROLES_ACCESSIBILITY[role].include?(other_role.try(:to_sym))
end
def accessible_for?(user)
ROLES_ACCESSIBILITY[user.role].include?(role.try(:to_sym))
end
class << self
extend Memoist
def roles_accessiblity_values(role)
ROLES_ACCESSIBILITY[role].map { |accessible_role| roles[accessible_role] }
end
memoize :roles_accessiblity_values
def i18n_roles
User.roles.keys.inject({}) do |result, role|
# XXX: Must use string for enum values
result[I18n.t(role, scope: 'authorization.roles')] = role
result
end
end
memoize :i18n_roles
def accessibles_for(user)
where(role: roles_accessiblity_values(user.role))
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment