Module: Dunlop::Ability

Extended by:
ActiveSupport::Concern
Includes:
CanCan::Ability
Included in:
Ability
Defined in:
app/services/dunlop/ability.rb

Defined Under Namespace

Modules: ClassMethods Classes: AdminRole, UserRole

Instance Method Summary collapse

Instance Method Details

#admin_rolesObject



31
32
33
# File 'app/services/dunlop/ability.rb', line 31

def admin_roles
  @admin_roles ||= all_roles.select(&:admin_role?)
end

#all_class_rolesObject



53
54
55
# File 'app/services/dunlop/ability.rb', line 53

def all_class_roles
  @all_class_roles ||= all_roles.select(&:class_role?)
end

#all_rolesObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/services/dunlop/ability.rb', line 35

def all_roles
  return @all_roles if @all_roles
  @all_roles = []
  user.role_names.each do |role_name|
    next unless role_name =~ /\w+-\w+-[\w:]+/
    ability, type, class_name = role_name.split('-')
    next unless self.class.allowed_authorization_classes.include?(class_name)
    @all_roles.push Dunlop::Ability::UserRole.new(ability, type, class_name)
  end
  user.role_names_admin.each do |role_name|
    next unless role_name =~ /\w+-\w+-[\w:]+/
    ability, type, class_name = role_name.split('-')
    #NOTE: no user class limiting security here
    @all_roles.push Dunlop::Ability::AdminRole.new(ability, type, class_name)
  end
  @all_roles
end

#initialize(user) ⇒ Object



9
10
11
12
13
# File 'app/services/dunlop/ability.rb', line 9

def initialize(user)
  return unless user.present?
  @user = user
  setup_abilities
end

#setup_abilitiesObject

This method should be implemented in the application app/models/ability.rb to implement custom authorization logic



77
78
79
# File 'app/services/dunlop/ability.rb', line 77

def setup_abilities
  setup_dunlop_abilities
end

#setup_dunlop_abilitiesObject



15
16
17
18
19
20
21
22
23
24
25
# File 'app/services/dunlop/ability.rb', line 15

def setup_dunlop_abilities
  if user.admin?
    can :manage, :all
    # Extra permissions, not assigned
    # can :backtrace, Dunlop::LogEntry
    # can :report, :index
    # can :report, :system
  else
    setup_dunlop_class_based_abilities
  end
end

#setup_dunlop_class_based_abilitiesObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'app/services/dunlop/ability.rb', line 57

def setup_dunlop_class_based_abilities
  all_class_roles.each do |role|
    can role.ability, role.target_class
  end

  # One usecase is to build a topmenu having the right menu structure based on the permissions. If there
  # is a permission on class A::B::C::D then there will be no permission on the A class, but I still have
  # to show the A toplevel menu, otherwise the user never arrives at the A::B::C::D class to perform it's
  # action through the UI. The current solution is to set an :index ability on the top level class A, so
  # in the _navigation_links.html.slim you can use
  #   can? :index, A
  # or even:
  #   can? :index, A::B
  # since a top level ability gives it to all subclasses (CanCanCan)
  all_class_roles.map{|role| role.class_name.split('::').first }.uniq.each do |top_level_class_name|
    can :index, top_level_class_name.constantize
  end
end

#user_rolesObject



27
28
29
# File 'app/services/dunlop/ability.rb', line 27

def user_roles
  @user_roles ||= all_roles.select(&:user_role?)
end