Module: EffectiveRoles

Defined in:
lib/effective_roles.rb,
lib/effective_roles/engine.rb,
lib/effective_roles/version.rb,
lib/effective_roles/set_current_user.rb,
lib/generators/effective_roles/install_generator.rb

Defined Under Namespace

Modules: Generators, SetCurrentUser Classes: Engine

Constant Summary collapse

VERSION =
'2.0.5'.freeze

Class Method Summary collapse

Class Method Details

.assignable_roles_collection(resource, current_user = nil, multiple: nil) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/effective_roles.rb', line 94

def self.assignable_roles_collection(resource, current_user = nil, multiple: nil)
  return roles unless assignable_roles_present?(resource)

  current_user ||= (EffectiveRoles.current_user || (EffectiveLogging.current_user if defined?(EffectiveLogging)))

  if current_user && !current_user.respond_to?(:is_role_restricted?)
    raise('expected current_user to respond to is_role_restricted?') 
  end

  if !resource.respond_to?(:is_role_restricted?)
    raise('expected current_user to respond to is_role_restricted?') 
  end

  assigned_roles = if assignable_roles.kind_of?(Hash)
    assignable = (assignable_roles[resource.class.to_s] || assignable_roles || {})
    assigned = [] # our return value

    if current_user.blank?
      assigned = assignable.values.flatten
    end

    if current_user.present?
      assigned = current_user.roles.map { |role| assignable[role] }.flatten.compact
    end

    if assignable[:new_record] && resource.new_record?
      assigned += Array(assignable[:new_record])
    end

    if assignable[:persisted] && resource.persisted?
      assigned += Array(assignable[:persisted])
    end

    assigned
  elsif assignable_roles.kind_of?(Array)
    assignable_roles
  end.uniq

  # Check boxes
  multiple = resource.acts_as_role_restricted_options[:multiple] if multiple.nil?
  return assigned_roles if multiple

  # Radios
  (resource.roles - assigned_roles).present? ? [] : assigned_roles
end

.assignable_roles_present?(resource) ⇒ Boolean

Returns:

  • (Boolean)


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/effective_roles.rb', line 140

def self.assignable_roles_present?(resource)
  return false if assignable_roles.nil?

  raise 'EffectiveRoles config.assignable_roles_for must be a Hash, Array or nil' unless [Hash, Array].include?(assignable_roles.class)
  raise('expected resource to respond to is_role_restricted?') unless resource.respond_to?(:is_role_restricted?)

  return assignable_roles.present? if assignable_roles.kind_of?(Array)

  if assignable_roles.kind_of?(Array)
    assignable_roles
  elsif assignable_roles.key?(resource.class.to_s)
    assignable_roles[resource.class.to_s]
  else
    assignable_roles
  end.present?
end

.authorization_level(controller, role, resource) ⇒ Object

This is used by the effective_roles_summary_table helper method



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/effective_roles.rb', line 158

def self.authorization_level(controller, role, resource)
  return :unknown unless (authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol))
  return :unknown unless (controller.current_user rescue nil).respond_to?(:roles=)

  # Store the current ability (cancan support) and roles
  current_ability = controller.instance_variable_get(:@current_ability)
  current_user = controller.instance_variable_get(:@current_user)
  current_user_roles = controller.current_user.roles

  # Set up the user, so the check is done with the desired permission level
  controller.instance_variable_set(:@current_ability, nil)

  level = nil

  case role
  when :signed_in
    controller.current_user.roles = []
  when :public
    controller.instance_variable_set(:@current_user, nil)

    if defined?(EffectiveLogging)
      EffectiveLogging.supressed { (controller.request.env['warden'].set_user(false) rescue nil) }
    else
      (controller.request.env['warden'].set_user(false) rescue nil)
    end
  else
    controller.current_user.roles = [role]
  end

  # Find the actual authorization level
  level = _authorization_level(controller, role, resource, authorization_method)

  # Restore the existing current_user stuff
  if role == :public
    ActiveRecord::Base.transaction do
      if defined?(EffectiveLogging)
        EffectiveLogging.supressed { (controller.request.env['warden'].set_user(current_user) rescue nil) }
      else
        (controller.request.env['warden'].set_user(current_user) rescue nil)
      end

      raise ActiveRecord::Rollback
    end
  end

  controller.instance_variable_set(:@current_ability, current_ability)
  controller.instance_variable_set(:@current_user, current_user)
  controller.current_user.roles = current_user_roles

  level
end

.authorize!(controller, action, resource) ⇒ Object



33
34
35
# File 'lib/effective_roles.rb', line 33

def self.authorize!(controller, action, resource)
  raise Effective::AccessDenied unless authorized?(controller, action, resource)
end

.authorized?(controller, action, resource) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/effective_roles.rb', line 20

def self.authorized?(controller, action, resource)
  @_exceptions ||= [Effective::AccessDenied, (CanCan::AccessDenied if defined?(CanCan)), (Pundit::NotAuthorizedError if defined?(Pundit))].compact

  return !!authorization_method unless authorization_method.respond_to?(:call)
  controller = controller.controller if controller.respond_to?(:controller)

  begin
    !!(controller || self).instance_exec((controller || self), action, resource, &authorization_method)
  rescue *@_exceptions
    false
  end
end

.current_userObject



42
43
44
# File 'lib/effective_roles.rb', line 42

def self.current_user
  @effective_roles_current_user
end

.current_user=(user) ⇒ Object

This is set by the “set_effective_roles_current_user” before_filter.



38
39
40
# File 'lib/effective_roles.rb', line 38

def self.current_user=(user)
  @effective_roles_current_user = user
end

.permitted_paramsObject



16
17
18
# File 'lib/effective_roles.rb', line 16

def self.permitted_params
  { roles: [] }
end

.roles_collection(resource, current_user = nil, only: nil, except: nil, multiple: nil) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/effective_roles.rb', line 71

def self.roles_collection(resource, current_user = nil, only: nil, except: nil, multiple: nil)
  if assignable_roles.present?
    raise('expected object to respond to is_role_restricted?') unless resource.respond_to?(:is_role_restricted?)
    raise('expected current_user to respond to is_role_restricted?') if current_user && !current_user.respond_to?(:is_role_restricted?)
  end

  only = Array(only).compact
  except = Array(except).compact
  multiple = resource.acts_as_role_restricted_options[:multiple] if multiple.nil?
  assignable = assignable_roles_collection(resource, current_user, multiple: multiple)

  roles.map do |role|
    next if only.present? && !only.include?(role)
    next if except.present? && except.include?(role)

    [
      "#{role}<p class='help-block text-muted'>#{role_description(role, resource)}</p>".html_safe,
      role,
      ({:disabled => :disabled} unless assignable.include?(role))
    ]
  end.compact
end

.roles_for(obj) ⇒ Object

This method converts whatever is given into its roles Pass an object, Integer, or Symbol to find corresponding role



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/effective_roles.rb', line 48

def self.roles_for(obj)
  if obj.respond_to?(:is_role_restricted?)
   obj.roles
  elsif obj.kind_of?(Integer)
    roles.reject { |r| (obj & 2**roles.index(r)).zero? }
  elsif obj.kind_of?(Symbol)
    [roles.find { |role| role == obj }].compact
  elsif obj.kind_of?(String)
    [roles.find { |role| role == obj.to_sym }].compact
  elsif obj.kind_of?(Array)
    obj.map { |obj| roles_for(obj) }.flatten.compact
  elsif obj.nil?
    []
  else
    raise 'unsupported object passed to EffectiveRoles.roles_for method. Expecting an acts_as_role_restricted object or a roles_mask integer'
  end
end

.roles_mask_for(*roles) ⇒ Object

EffectiveRoles.roles_mask_for(:admin, :member)



67
68
69
# File 'lib/effective_roles.rb', line 67

def self.roles_mask_for(*roles)
  roles_for(roles).map { |r| 2**EffectiveRoles.roles.index(r) }.sum
end

.setup {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:



12
13
14
# File 'lib/effective_roles.rb', line 12

def self.setup
  yield self
end