effective_roles 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +2 -8
- data/app/controllers/admin/roles_controller.rb +8 -3
- data/app/helpers/effective_roles_helper.rb +106 -2
- data/app/models/concerns/acts_as_role_restricted.rb +15 -14
- data/app/views/effective/roles/_summary_table.html.haml +2 -1
- data/config/effective_roles.rb +6 -29
- data/lib/effective_roles.rb +68 -151
- data/lib/effective_roles/engine.rb +2 -14
- data/lib/effective_roles/version.rb +1 -1
- metadata +20 -8
- data/app/models/effective/access_denied.rb +0 -17
- data/lib/effective_roles/set_current_user.rb +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7f392991013eeab38fcc7b6092c1014078fc2a356833bd5033b9a268987dc512
|
|
4
|
+
data.tar.gz: 38bb573be4e391b9cfd6141713bd89d29914e46148705588f1859642a5269bed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef6d332b9c6d93d8e28b61e856c93ec20e8c731b2fd02678fd1dcd8e52c2bcd12e1f5b68c891d82a265054065fe5694cc2bd59baa72ddaf2bb4553af28a93739
|
|
7
|
+
data.tar.gz: e7f10cde194b45115445a09bd99d0da254c81dd611c97cb9f1c25e8cd33181941449aaa20eb45b5b24d4bea0af8397720cf1156865ef0bf217b1798bf103225a
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -8,10 +8,6 @@ Includes a mixin for adding authentication for any model.
|
|
|
8
8
|
|
|
9
9
|
SQL Finders for returning an ActiveRecord::Relation with all permitted records.
|
|
10
10
|
|
|
11
|
-
Handy formtastic and simple_form helpers for assigning roles.
|
|
12
|
-
|
|
13
|
-
Rails 3.2.x and Rails 4
|
|
14
|
-
|
|
15
11
|
|
|
16
12
|
## Getting Started
|
|
17
13
|
|
|
@@ -158,8 +154,8 @@ When using assignable roles, you must assign the acts_as_role_restricted resourc
|
|
|
158
154
|
|
|
159
155
|
You can do this in one of three ways:
|
|
160
156
|
|
|
161
|
-
1. Setting resource.current_user = current_user in your controller directly.
|
|
162
|
-
2. Add `before_action
|
|
157
|
+
1. Setting resource.current_user = current_user in your controller update action directly.
|
|
158
|
+
2. Add `before_action -> { @thing.current_user = current_user }` to your ApplicationController
|
|
163
159
|
3. Using `Effective::CrudController` to do this automatically.
|
|
164
160
|
|
|
165
161
|
This restriction is only applied when running within the rails server. Not on rails console or db:seeds.
|
|
@@ -319,5 +315,3 @@ This model implements the https://github.com/ryanb/cancan/wiki/Role-Based-Author
|
|
|
319
315
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
320
316
|
5. Bonus points for test coverage
|
|
321
317
|
6. Create new Pull Request
|
|
322
|
-
|
|
323
|
-
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
module Admin
|
|
2
2
|
class RolesController < ApplicationController
|
|
3
|
-
before_action
|
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_roles) }
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
include Effective::CrudController
|
|
7
|
+
|
|
8
|
+
if (config = EffectiveRoles.config.layout)
|
|
9
|
+
layout(config.kind_of?(Hash) ? config[:admin] : config)
|
|
10
|
+
end
|
|
6
11
|
|
|
7
12
|
def index
|
|
8
13
|
@page_title = 'Roles'
|
|
9
|
-
EffectiveRoles.authorize!(self, :admin, :effective_roles)
|
|
10
14
|
end
|
|
15
|
+
|
|
11
16
|
end
|
|
12
17
|
end
|
|
@@ -2,7 +2,7 @@ module EffectiveRolesHelper
|
|
|
2
2
|
def effective_roles_summary(obj, options = {}) # User or a Post, any acts_as_roleable
|
|
3
3
|
raise 'expected an acts_as_roleable object' unless obj.respond_to?(:roles)
|
|
4
4
|
|
|
5
|
-
descriptions = EffectiveRoles.role_descriptions[obj.class.name] || EffectiveRoles.role_descriptions || {}
|
|
5
|
+
descriptions = EffectiveRoles.config.role_descriptions[obj.class.name] || EffectiveRoles.config.role_descriptions || {}
|
|
6
6
|
opts = { obj: obj, roles: obj.roles, descriptions: descriptions }.merge(options)
|
|
7
7
|
|
|
8
8
|
render partial: 'effective/roles/summary', locals: opts
|
|
@@ -17,7 +17,7 @@ module EffectiveRolesHelper
|
|
|
17
17
|
raise 'Expected argument to be a Hash' unless opts.kind_of?(Hash)
|
|
18
18
|
|
|
19
19
|
roles = Array(opts[:roles]).presence
|
|
20
|
-
roles ||= [:public, :signed_in] + EffectiveRoles.roles
|
|
20
|
+
roles ||= [:public, :signed_in] + EffectiveRoles.config.roles
|
|
21
21
|
|
|
22
22
|
if opts[:only].present?
|
|
23
23
|
klasses = Array(opts[:only])
|
|
@@ -101,4 +101,108 @@ module EffectiveRolesHelper
|
|
|
101
101
|
klass.respond_to?(:name) ? klass.name : klass.to_s
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
# This is used by the effective_roles_summary_table helper method
|
|
105
|
+
def effective_roles_authorization_level(controller, role, resource)
|
|
106
|
+
authorization_method = EffectiveRoles.config.authorization_method
|
|
107
|
+
|
|
108
|
+
raise('expected an authorization method') unless (authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol))
|
|
109
|
+
return :unknown unless (controller.current_user rescue nil).respond_to?(:roles=)
|
|
110
|
+
|
|
111
|
+
# Store the current ability (cancan support) and roles
|
|
112
|
+
current_ability = controller.instance_variable_get(:@current_ability)
|
|
113
|
+
current_user = controller.instance_variable_get(:@current_user)
|
|
114
|
+
current_user_roles = controller.current_user.roles
|
|
115
|
+
|
|
116
|
+
# Set up the user, so the check is done with the desired permission level
|
|
117
|
+
controller.instance_variable_set(:@current_ability, nil)
|
|
118
|
+
|
|
119
|
+
level = nil
|
|
120
|
+
|
|
121
|
+
case role
|
|
122
|
+
when :signed_in
|
|
123
|
+
controller.current_user.roles = []
|
|
124
|
+
when :public
|
|
125
|
+
controller.instance_variable_set(:@current_user, nil)
|
|
126
|
+
|
|
127
|
+
if defined?(EffectiveLogging)
|
|
128
|
+
EffectiveLogging.supressed { (controller.request.env['warden'].set_user(false) rescue nil) }
|
|
129
|
+
else
|
|
130
|
+
(controller.request.env['warden'].set_user(false) rescue nil)
|
|
131
|
+
end
|
|
132
|
+
else
|
|
133
|
+
controller.current_user.roles = [role]
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Find the actual authorization level
|
|
137
|
+
level = effective_roles_item_authorization_level(controller, role, resource, authorization_method)
|
|
138
|
+
|
|
139
|
+
# Restore the existing current_user stuff
|
|
140
|
+
if role == :public
|
|
141
|
+
ActiveRecord::Base.transaction do
|
|
142
|
+
if defined?(EffectiveLogging)
|
|
143
|
+
EffectiveLogging.supressed { (controller.request.env['warden'].set_user(current_user) rescue nil) }
|
|
144
|
+
else
|
|
145
|
+
(controller.request.env['warden'].set_user(current_user) rescue nil)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
raise ActiveRecord::Rollback
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
controller.instance_variable_set(:@current_ability, current_ability)
|
|
153
|
+
controller.instance_variable_set(:@current_user, current_user)
|
|
154
|
+
controller.current_user.roles = current_user_roles
|
|
155
|
+
|
|
156
|
+
level
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def effective_roles_item_authorization_level(controller, role, resource, auth_method)
|
|
160
|
+
resource = (resource.new() rescue resource) if resource.kind_of?(ActiveRecord::Base)
|
|
161
|
+
|
|
162
|
+
# Custom actions
|
|
163
|
+
if resource.kind_of?(Hash)
|
|
164
|
+
resource.each do |key, value|
|
|
165
|
+
return (controller.instance_exec(controller, key, value, &auth_method) rescue false) ? :yes : :no
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Check for Manage
|
|
170
|
+
return :manage if (
|
|
171
|
+
(controller.instance_exec(controller, :create, resource, &auth_method) rescue false) &&
|
|
172
|
+
(controller.instance_exec(controller, :update, resource, &auth_method) rescue false) &&
|
|
173
|
+
(controller.instance_exec(controller, :show, resource, &auth_method) rescue false) &&
|
|
174
|
+
(controller.instance_exec(controller, :destroy, resource, &auth_method) rescue false)
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Check for Update
|
|
178
|
+
return :update if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
179
|
+
|
|
180
|
+
# Check for Update Own
|
|
181
|
+
if resource.respond_to?('user=')
|
|
182
|
+
resource.user = controller.current_user
|
|
183
|
+
return :update_own if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
184
|
+
resource.user = nil
|
|
185
|
+
elsif resource.respond_to?('user_id=')
|
|
186
|
+
resource.user_id = controller.current_user.id
|
|
187
|
+
return :update_own if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
188
|
+
resource.user_id = nil
|
|
189
|
+
elsif resource.class.name.end_with?('User')
|
|
190
|
+
return :update_own if (controller.instance_exec(controller, :update, controller.current_user, &auth_method) rescue false)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Check for Create
|
|
194
|
+
return :create if (controller.instance_exec(controller, :create, resource, &auth_method) rescue false)
|
|
195
|
+
|
|
196
|
+
# Check for Show
|
|
197
|
+
return :show if (controller.instance_exec(controller, :show, resource, &auth_method) rescue false)
|
|
198
|
+
|
|
199
|
+
# Check for Index
|
|
200
|
+
return :index if (controller.instance_exec(controller, :index, resource, &auth_method) rescue false)
|
|
201
|
+
|
|
202
|
+
# Check for Destroy
|
|
203
|
+
return :destroy if (controller.instance_exec(controller, :destroy, resource, &auth_method) rescue false)
|
|
204
|
+
|
|
205
|
+
:none
|
|
206
|
+
end
|
|
207
|
+
|
|
104
208
|
end
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
module ActsAsRoleRestricted
|
|
15
15
|
extend ActiveSupport::Concern
|
|
16
16
|
|
|
17
|
-
module
|
|
17
|
+
module Base
|
|
18
18
|
def acts_as_role_restricted(multiple: false)
|
|
19
19
|
@acts_as_role_restricted_opts = { multiple: multiple }
|
|
20
20
|
include ::ActsAsRoleRestricted
|
|
@@ -29,22 +29,24 @@ module ActsAsRoleRestricted
|
|
|
29
29
|
|
|
30
30
|
validates :roles_mask, numericality: true, allow_nil: true
|
|
31
31
|
|
|
32
|
-
validate(if: -> { changes.include?(:roles_mask) }) do
|
|
33
|
-
user = current_user || EffectiveRoles.current_user || (EffectiveLogging.current_user if defined?(EffectiveLogging))
|
|
34
|
-
|
|
35
|
-
if user.blank? && EffectiveRoles.assignable_roles.present? && defined?(Rails::Server)
|
|
36
|
-
self.errors.add(:roles, 'current_user must be present when assigning roles')
|
|
37
|
-
end
|
|
38
|
-
|
|
32
|
+
validate(if: -> { changes.include?(:roles_mask) && EffectiveRoles.assignable_roles_present?(self) }) do
|
|
39
33
|
roles_was = EffectiveRoles.roles_for(changes[:roles_mask].first)
|
|
40
34
|
changed = (roles + roles_was) - (roles & roles_was) # XOR
|
|
41
35
|
|
|
42
|
-
assignable = EffectiveRoles.assignable_roles_collection(self,
|
|
36
|
+
assignable = EffectiveRoles.assignable_roles_collection(self, current_user) # Returns all roles when user is blank
|
|
43
37
|
unauthorized = changed - assignable
|
|
44
38
|
|
|
45
39
|
authorized = roles.dup
|
|
46
40
|
unauthorized.each { |role| authorized.include?(role) ? authorized.delete(role) : authorized.push(role) }
|
|
47
41
|
|
|
42
|
+
if unauthorized.present?
|
|
43
|
+
Rails.logger.info "\e[31m unassignable roles: #{unauthorized.map { |role| ":#{role}" }.to_sentence}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if unauthorized.present? && current_user.blank? && defined?(Rails::Server)
|
|
47
|
+
self.errors.add(:roles, 'current_user must be present when assigning roles')
|
|
48
|
+
end
|
|
49
|
+
|
|
48
50
|
self.roles_mask = EffectiveRoles.roles_mask_for(authorized)
|
|
49
51
|
end
|
|
50
52
|
|
|
@@ -69,18 +71,18 @@ module ActsAsRoleRestricted
|
|
|
69
71
|
def with_role_sql(*roles)
|
|
70
72
|
roles = roles.flatten.compact
|
|
71
73
|
roles = roles.first.roles if roles.length == 1 && roles.first.respond_to?(:roles)
|
|
72
|
-
roles = (roles.map { |role| role.to_sym } & EffectiveRoles.roles)
|
|
74
|
+
roles = (roles.map { |role| role.to_sym } & EffectiveRoles.config.roles)
|
|
73
75
|
|
|
74
|
-
roles.map { |role| "(#{self.table_name}.roles_mask & %d > 0)" % 2**EffectiveRoles.roles.index(role) }.join(' OR ')
|
|
76
|
+
roles.map { |role| "(#{self.table_name}.roles_mask & %d > 0)" % 2**EffectiveRoles.config.roles.index(role) }.join(' OR ')
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
def without_role(*roles)
|
|
78
80
|
roles = roles.flatten.compact
|
|
79
81
|
roles = roles.first.roles if roles.length == 1 && roles.first.respond_to?(:roles)
|
|
80
|
-
roles = (roles.map { |role| role.to_sym } & EffectiveRoles.roles)
|
|
82
|
+
roles = (roles.map { |role| role.to_sym } & EffectiveRoles.config.roles)
|
|
81
83
|
|
|
82
84
|
where(
|
|
83
|
-
roles.map { |role| "NOT(#{self.table_name}.roles_mask & %d > 0)" % 2**EffectiveRoles.roles.index(role) }.join(' AND ')
|
|
85
|
+
roles.map { |role| "NOT(#{self.table_name}.roles_mask & %d > 0)" % 2**EffectiveRoles.config.roles.index(role) }.join(' AND ')
|
|
84
86
|
).or(where(roles_mask: nil))
|
|
85
87
|
end
|
|
86
88
|
end
|
|
@@ -127,4 +129,3 @@ module ActsAsRoleRestricted
|
|
|
127
129
|
end
|
|
128
130
|
|
|
129
131
|
end
|
|
130
|
-
|
|
@@ -13,4 +13,5 @@
|
|
|
13
13
|
%td= effective_roles_authorization_label(klass)
|
|
14
14
|
- roles.each do |role|
|
|
15
15
|
%td.text-center
|
|
16
|
-
=
|
|
16
|
+
- level = effective_roles_authorization_level(controller, role, klass)
|
|
17
|
+
= effective_roles_authorization_badge(level)
|
data/config/effective_roles.rb
CHANGED
|
@@ -53,6 +53,8 @@ EffectiveRoles.setup do |config|
|
|
|
53
53
|
# :superadmin => [:superadmin, :admin, :member], # Superadmins may create Pages for any role
|
|
54
54
|
# :admin => [:admin, :member], # Admins may create Pages for admin and members
|
|
55
55
|
# :member => [:member] # Members may create Pages for members
|
|
56
|
+
# },
|
|
57
|
+
# 'Post' => false # Don't enforce assignable roles validation
|
|
56
58
|
# }
|
|
57
59
|
#
|
|
58
60
|
# Or just keep it simple, and use this Hash syntax of permissions for every resource
|
|
@@ -60,38 +62,13 @@ EffectiveRoles.setup do |config|
|
|
|
60
62
|
# config.assignable_roles = {
|
|
61
63
|
# :superadmin => [:superadmin, :admin, :member], # Superadmins may assign any resource any role
|
|
62
64
|
# :admin => [:admin, :member], # Admins may only assign the :admin or :member role
|
|
63
|
-
# :member => []
|
|
65
|
+
# :member => [], # Members may not assign any roles
|
|
66
|
+
# :new_record => [:member] # Member may be assigned to a new_record without a current_user
|
|
64
67
|
# }
|
|
65
68
|
|
|
66
69
|
# Authorization Method
|
|
67
|
-
#
|
|
68
|
-
# This doesn't have anything to do with the roles themselves.
|
|
69
|
-
# It's only used in two places:
|
|
70
|
-
# - For the effective_roles_summary_table() helper method
|
|
71
|
-
# - The /admin/roles page check
|
|
72
|
-
#
|
|
73
|
-
# It should match the authorization check used by your application
|
|
74
|
-
#
|
|
75
|
-
# This method is called by all controller actions with the appropriate action and resource
|
|
76
|
-
# If the method returns false, an Effective::AccessDenied Error will be raised (see README.md for complete info)
|
|
77
|
-
#
|
|
78
|
-
# Use via Proc (and with CanCan):
|
|
79
|
-
# config.authorization_method = Proc.new { |controller, action, resource| can?(action, resource) }
|
|
80
|
-
#
|
|
81
|
-
# Use via custom method:
|
|
82
|
-
# config.authorization_method = :my_authorization_method
|
|
83
|
-
#
|
|
84
|
-
# And then in your application_controller.rb:
|
|
85
|
-
#
|
|
86
|
-
# def my_authorization_method(action, resource)
|
|
87
|
-
# current_user.is?(:admin)
|
|
88
|
-
# end
|
|
89
|
-
#
|
|
90
|
-
# Or disable the check completely:
|
|
91
|
-
# config.authorization_method = false
|
|
92
|
-
config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) } # CanCanCan
|
|
70
|
+
# This gem serves an /admin/roles endpoint that calls EffectiveResources.authorize!
|
|
93
71
|
|
|
94
72
|
# Layout Settings
|
|
95
|
-
#
|
|
96
|
-
config.layout = 'application'
|
|
73
|
+
# config.layout = 'admin'
|
|
97
74
|
end
|
data/lib/effective_roles.rb
CHANGED
|
@@ -1,46 +1,30 @@
|
|
|
1
|
+
require 'effective_resources'
|
|
1
2
|
require 'effective_roles/engine'
|
|
2
3
|
require 'effective_roles/version'
|
|
3
4
|
|
|
4
5
|
module EffectiveRoles
|
|
5
|
-
mattr_accessor :roles
|
|
6
|
-
mattr_accessor :role_descriptions
|
|
7
|
-
mattr_accessor :assignable_roles
|
|
6
|
+
# mattr_accessor :roles
|
|
7
|
+
# mattr_accessor :role_descriptions
|
|
8
|
+
# mattr_accessor :assignable_roles
|
|
9
|
+
# mattr_accessor :layout
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
def self.config(namespace = nil)
|
|
12
|
+
@config ||= ActiveSupport::OrderedOptions.new
|
|
13
|
+
namespace ||= Tenant.current if defined?(Tenant)
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def self.permitted_params
|
|
17
|
-
{ roles: [] }
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def self.authorized?(controller, action, resource)
|
|
21
|
-
@_exceptions ||= [Effective::AccessDenied, (CanCan::AccessDenied if defined?(CanCan)), (Pundit::NotAuthorizedError if defined?(Pundit))].compact
|
|
22
|
-
|
|
23
|
-
return !!authorization_method unless authorization_method.respond_to?(:call)
|
|
24
|
-
controller = controller.controller if controller.respond_to?(:controller)
|
|
25
|
-
|
|
26
|
-
begin
|
|
27
|
-
!!(controller || self).instance_exec((controller || self), action, resource, &authorization_method)
|
|
28
|
-
rescue *@_exceptions
|
|
29
|
-
false
|
|
15
|
+
if namespace
|
|
16
|
+
@config[namespace] ||= ActiveSupport::OrderedOptions.new
|
|
17
|
+
else
|
|
18
|
+
@config
|
|
30
19
|
end
|
|
31
20
|
end
|
|
32
21
|
|
|
33
|
-
def self.
|
|
34
|
-
|
|
22
|
+
def self.setup(namespace = nil, &block)
|
|
23
|
+
yield(config(namespace))
|
|
35
24
|
end
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@effective_roles_current_user = user
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.current_user
|
|
43
|
-
@effective_roles_current_user
|
|
26
|
+
def self.permitted_params
|
|
27
|
+
{ roles: [] }
|
|
44
28
|
end
|
|
45
29
|
|
|
46
30
|
# This method converts whatever is given into its roles
|
|
@@ -49,11 +33,11 @@ module EffectiveRoles
|
|
|
49
33
|
if obj.respond_to?(:is_role_restricted?)
|
|
50
34
|
obj.roles
|
|
51
35
|
elsif obj.kind_of?(Integer)
|
|
52
|
-
roles.reject { |r| (obj & 2**roles.index(r)).zero? }
|
|
36
|
+
config.roles.reject { |r| (obj & 2 ** config.roles.index(r)).zero? }
|
|
53
37
|
elsif obj.kind_of?(Symbol)
|
|
54
|
-
|
|
38
|
+
Array(config.roles.find { |role| role == obj })
|
|
55
39
|
elsif obj.kind_of?(String)
|
|
56
|
-
|
|
40
|
+
Array(config.roles.find { |role| role == obj.to_sym })
|
|
57
41
|
elsif obj.kind_of?(Array)
|
|
58
42
|
obj.map { |obj| roles_for(obj) }.flatten.compact
|
|
59
43
|
elsif obj.nil?
|
|
@@ -65,11 +49,11 @@ module EffectiveRoles
|
|
|
65
49
|
|
|
66
50
|
# EffectiveRoles.roles_mask_for(:admin, :member)
|
|
67
51
|
def self.roles_mask_for(*roles)
|
|
68
|
-
roles_for(roles).map { |r| 2**
|
|
52
|
+
roles_for(roles).map { |r| 2 ** config.roles.index(r) }.sum
|
|
69
53
|
end
|
|
70
54
|
|
|
71
55
|
def self.roles_collection(resource, current_user = nil, only: nil, except: nil, multiple: nil)
|
|
72
|
-
if assignable_roles.present?
|
|
56
|
+
if config.assignable_roles.present?
|
|
73
57
|
raise('expected object to respond to is_role_restricted?') unless resource.respond_to?(:is_role_restricted?)
|
|
74
58
|
raise('expected current_user to respond to is_role_restricted?') if current_user && !current_user.respond_to?(:is_role_restricted?)
|
|
75
59
|
end
|
|
@@ -79,7 +63,7 @@ module EffectiveRoles
|
|
|
79
63
|
multiple = resource.acts_as_role_restricted_options[:multiple] if multiple.nil?
|
|
80
64
|
assignable = assignable_roles_collection(resource, current_user, multiple: multiple)
|
|
81
65
|
|
|
82
|
-
roles.map do |role|
|
|
66
|
+
config.roles.map do |role|
|
|
83
67
|
next if only.present? && !only.include?(role)
|
|
84
68
|
next if except.present? && except.include?(role)
|
|
85
69
|
|
|
@@ -92,139 +76,72 @@ module EffectiveRoles
|
|
|
92
76
|
end
|
|
93
77
|
|
|
94
78
|
def self.assignable_roles_collection(resource, current_user = nil, multiple: nil)
|
|
95
|
-
return roles
|
|
96
|
-
|
|
97
|
-
raise 'EffectiveRoles config.assignable_roles_for must be a Hash, Array or nil' unless [Hash, Array].include?(assignable_roles.class)
|
|
98
|
-
raise('expected resource to respond to is_role_restricted?') unless resource.respond_to?(:is_role_restricted?)
|
|
99
|
-
raise('expected current_user to respond to is_role_restricted?') if current_user && !current_user.respond_to?(:is_role_restricted?)
|
|
100
|
-
|
|
101
|
-
multiple = resource.acts_as_role_restricted_options[:multiple] if multiple.nil?
|
|
102
|
-
current_user ||= (EffectiveRoles.current_user || (EffectiveLogging.current_user if defined?(EffectiveLogging)))
|
|
79
|
+
return config.roles unless assignable_roles_present?(resource)
|
|
103
80
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
elsif current_user.present?
|
|
107
|
-
current_roles = assignable_roles[resource.class.to_s] || assignable_roles || {}
|
|
108
|
-
current_user.roles.map { |role| current_roles[role] }.flatten.compact.uniq
|
|
109
|
-
else
|
|
110
|
-
current_roles = assignable_roles[resource.class.to_s] || assignable_roles || {}
|
|
111
|
-
current_roles.values.flatten.uniq
|
|
81
|
+
if current_user && !current_user.respond_to?(:is_role_restricted?)
|
|
82
|
+
raise('expected current_user to respond to is_role_restricted?')
|
|
112
83
|
end
|
|
113
84
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# Radios
|
|
118
|
-
(resource.roles - assignable).present? ? [] : assignable
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# This is used by the effective_roles_summary_table helper method
|
|
122
|
-
def self.authorization_level(controller, role, resource)
|
|
123
|
-
return :unknown unless (authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol))
|
|
124
|
-
return :unknown unless (controller.current_user rescue nil).respond_to?(:roles=)
|
|
125
|
-
|
|
126
|
-
# Store the current ability (cancan support) and roles
|
|
127
|
-
current_ability = controller.instance_variable_get(:@current_ability)
|
|
128
|
-
current_user = controller.instance_variable_get(:@current_user)
|
|
129
|
-
current_user_roles = controller.current_user.roles
|
|
130
|
-
|
|
131
|
-
# Set up the user, so the check is done with the desired permission level
|
|
132
|
-
controller.instance_variable_set(:@current_ability, nil)
|
|
133
|
-
|
|
134
|
-
level = nil
|
|
85
|
+
if !resource.respond_to?(:is_role_restricted?)
|
|
86
|
+
raise('expected current_user to respond to is_role_restricted?')
|
|
87
|
+
end
|
|
135
88
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
when :public
|
|
140
|
-
controller.instance_variable_set(:@current_user, nil)
|
|
89
|
+
assigned_roles = if config.assignable_roles.kind_of?(Hash)
|
|
90
|
+
assignable = (config.assignable_roles[resource.class.to_s] || config.assignable_roles || {})
|
|
91
|
+
assigned = [] # our return value
|
|
141
92
|
|
|
142
|
-
if
|
|
143
|
-
|
|
144
|
-
else
|
|
145
|
-
(controller.request.env['warden'].set_user(false) rescue nil)
|
|
93
|
+
if current_user.blank?
|
|
94
|
+
assigned = assignable.values.flatten
|
|
146
95
|
end
|
|
147
|
-
else
|
|
148
|
-
controller.current_user.roles = [role]
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# Find the actual authorization level
|
|
152
|
-
level = _authorization_level(controller, role, resource, authorization_method)
|
|
153
96
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if defined?(EffectiveLogging)
|
|
158
|
-
EffectiveLogging.supressed { (controller.request.env['warden'].set_user(current_user) rescue nil) }
|
|
159
|
-
else
|
|
160
|
-
(controller.request.env['warden'].set_user(current_user) rescue nil)
|
|
161
|
-
end
|
|
97
|
+
if current_user.present?
|
|
98
|
+
assigned = current_user.roles.map { |role| assignable[role] }.flatten.compact
|
|
99
|
+
end
|
|
162
100
|
|
|
163
|
-
|
|
101
|
+
if assignable[:new_record] && resource.new_record?
|
|
102
|
+
assigned += Array(assignable[:new_record])
|
|
164
103
|
end
|
|
165
|
-
end
|
|
166
104
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
105
|
+
if assignable[:persisted] && resource.persisted?
|
|
106
|
+
assigned += Array(assignable[:persisted])
|
|
107
|
+
end
|
|
170
108
|
|
|
171
|
-
|
|
172
|
-
|
|
109
|
+
assigned
|
|
110
|
+
elsif config.assignable_roles.kind_of?(Array)
|
|
111
|
+
config.assignable_roles
|
|
112
|
+
end.uniq
|
|
173
113
|
|
|
174
|
-
|
|
114
|
+
# Check boxes
|
|
115
|
+
multiple = resource.acts_as_role_restricted_options[:multiple] if multiple.nil?
|
|
116
|
+
return assigned_roles if multiple
|
|
175
117
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
(role_descriptions[obj.try(:class).to_s] || {})[role] || role_descriptions[role] || ''
|
|
118
|
+
# Radios
|
|
119
|
+
(resource.roles - assigned_roles).present? ? [] : assigned_roles
|
|
179
120
|
end
|
|
180
121
|
|
|
181
|
-
def self.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# Custom actions
|
|
185
|
-
if resource.kind_of?(Hash)
|
|
186
|
-
resource.each do |key, value|
|
|
187
|
-
return (controller.instance_exec(controller, key, value, &auth_method) rescue false) ? :yes : :no
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
# Check for Manage
|
|
192
|
-
return :manage if (
|
|
193
|
-
(controller.instance_exec(controller, :create, resource, &auth_method) rescue false) &&
|
|
194
|
-
(controller.instance_exec(controller, :update, resource, &auth_method) rescue false) &&
|
|
195
|
-
(controller.instance_exec(controller, :show, resource, &auth_method) rescue false) &&
|
|
196
|
-
(controller.instance_exec(controller, :destroy, resource, &auth_method) rescue false)
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
# Check for Update
|
|
200
|
-
return :update if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
201
|
-
|
|
202
|
-
# Check for Update Own
|
|
203
|
-
if resource.respond_to?('user=')
|
|
204
|
-
resource.user = controller.current_user
|
|
205
|
-
return :update_own if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
206
|
-
resource.user = nil
|
|
207
|
-
elsif resource.respond_to?('user_id=')
|
|
208
|
-
resource.user_id = controller.current_user.id
|
|
209
|
-
return :update_own if (controller.instance_exec(controller, :update, resource, &auth_method) rescue false)
|
|
210
|
-
resource.user_id = nil
|
|
211
|
-
elsif resource.kind_of?(User)
|
|
212
|
-
return :update_own if (controller.instance_exec(controller, :update, controller.current_user, &auth_method) rescue false)
|
|
213
|
-
end
|
|
122
|
+
def self.assignable_roles_present?(resource)
|
|
123
|
+
return false unless config.assignable_roles.present?
|
|
214
124
|
|
|
215
|
-
|
|
216
|
-
|
|
125
|
+
raise 'EffectiveRoles config.assignable_roles_for must be a Hash or Array' unless [Hash, Array].include?(config.assignable_roles.class)
|
|
126
|
+
raise('expected resource to respond to is_role_restricted?') unless resource.respond_to?(:is_role_restricted?)
|
|
217
127
|
|
|
218
|
-
|
|
219
|
-
|
|
128
|
+
if config.assignable_roles.kind_of?(Array)
|
|
129
|
+
config.assignable_roles
|
|
130
|
+
elsif config.assignable_roles.key?(resource.class.to_s)
|
|
131
|
+
config.assignable_roles[resource.class.to_s]
|
|
132
|
+
else
|
|
133
|
+
config.assignable_roles
|
|
134
|
+
end.present?
|
|
135
|
+
end
|
|
220
136
|
|
|
221
|
-
|
|
222
|
-
return :index if (controller.instance_exec(controller, :index, resource, &auth_method) rescue false)
|
|
137
|
+
private
|
|
223
138
|
|
|
224
|
-
|
|
225
|
-
|
|
139
|
+
def self.role_description(role, obj = nil)
|
|
140
|
+
raise 'EffectiveRoles config.role_descriptions must be a Hash' unless config.role_descriptions.kind_of?(Hash)
|
|
226
141
|
|
|
227
|
-
|
|
142
|
+
description = config.role_descriptions.dig(obj.class.to_s, role) if obj.present?
|
|
143
|
+
description ||= config.role_descriptions[role]
|
|
144
|
+
description || ''
|
|
228
145
|
end
|
|
229
146
|
|
|
230
147
|
end
|
|
@@ -2,27 +2,15 @@ module EffectiveRoles
|
|
|
2
2
|
class Engine < ::Rails::Engine
|
|
3
3
|
engine_name 'effective_roles'
|
|
4
4
|
|
|
5
|
-
config.autoload_paths += Dir["#{config.root}/app/models/concerns", "#{config.root}/lib/"]
|
|
6
|
-
|
|
7
5
|
# Include acts_as_addressable concern and allow any ActiveRecord object to call it
|
|
8
6
|
initializer 'effective_roles.active_record' do |app|
|
|
9
7
|
ActiveSupport.on_load :active_record do
|
|
10
|
-
ActiveRecord::Base.extend(ActsAsRoleRestricted::
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Register the log_page_views concern so that it can be called in ActionController or elsewhere
|
|
15
|
-
initializer 'effective_logging.log_changes_action_controller' do |app|
|
|
16
|
-
Rails.application.config.to_prepare do
|
|
17
|
-
ActiveSupport.on_load :action_controller do
|
|
18
|
-
require 'effective_roles/set_current_user'
|
|
19
|
-
ActionController::Base.include(EffectiveRoles::SetCurrentUser::ActionController)
|
|
20
|
-
end
|
|
8
|
+
ActiveRecord::Base.extend(ActsAsRoleRestricted::Base)
|
|
21
9
|
end
|
|
22
10
|
end
|
|
23
11
|
|
|
24
12
|
# Set up our default configuration options.
|
|
25
|
-
initializer "effective_roles.defaults", :
|
|
13
|
+
initializer "effective_roles.defaults", before: :load_config_initializers do |app|
|
|
26
14
|
eval File.read("#{config.root}/config/effective_roles.rb")
|
|
27
15
|
end
|
|
28
16
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: effective_roles
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Code and Effect
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: 3.2.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: effective_resources
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
27
41
|
description: Assign multiple roles to any User or other ActiveRecord object. Select
|
|
28
42
|
only the appropriate objects based on intelligent, chainable ActiveRecord::Relation
|
|
29
43
|
finder methods.
|
|
@@ -38,7 +52,6 @@ files:
|
|
|
38
52
|
- app/controllers/admin/roles_controller.rb
|
|
39
53
|
- app/helpers/effective_roles_helper.rb
|
|
40
54
|
- app/models/concerns/acts_as_role_restricted.rb
|
|
41
|
-
- app/models/effective/access_denied.rb
|
|
42
55
|
- app/views/admin/roles/index.html.haml
|
|
43
56
|
- app/views/effective/roles/_summary.html.haml
|
|
44
57
|
- app/views/effective/roles/_summary_table.html.haml
|
|
@@ -46,14 +59,13 @@ files:
|
|
|
46
59
|
- config/routes.rb
|
|
47
60
|
- lib/effective_roles.rb
|
|
48
61
|
- lib/effective_roles/engine.rb
|
|
49
|
-
- lib/effective_roles/set_current_user.rb
|
|
50
62
|
- lib/effective_roles/version.rb
|
|
51
63
|
- lib/generators/effective_roles/install_generator.rb
|
|
52
64
|
homepage: https://github.com/code-and-effect/effective_roles
|
|
53
65
|
licenses:
|
|
54
66
|
- MIT
|
|
55
67
|
metadata: {}
|
|
56
|
-
post_install_message:
|
|
68
|
+
post_install_message:
|
|
57
69
|
rdoc_options: []
|
|
58
70
|
require_paths:
|
|
59
71
|
- lib
|
|
@@ -68,8 +80,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
68
80
|
- !ruby/object:Gem::Version
|
|
69
81
|
version: '0'
|
|
70
82
|
requirements: []
|
|
71
|
-
rubygems_version: 3.
|
|
72
|
-
signing_key:
|
|
83
|
+
rubygems_version: 3.1.2
|
|
84
|
+
signing_key:
|
|
73
85
|
specification_version: 4
|
|
74
86
|
summary: Assign multiple roles to any User or other ActiveRecord object. Select only
|
|
75
87
|
the appropriate objects based on intelligent, chainable ActiveRecord::Relation finder
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
unless defined?(Effective::AccessDenied)
|
|
2
|
-
module Effective
|
|
3
|
-
class AccessDenied < StandardError
|
|
4
|
-
attr_reader :action, :subject
|
|
5
|
-
|
|
6
|
-
def initialize(message = nil, action = nil, subject = nil)
|
|
7
|
-
@message = message
|
|
8
|
-
@action = action
|
|
9
|
-
@subject = subject
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def to_s
|
|
13
|
-
@message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module EffectiveRoles
|
|
2
|
-
module SetCurrentUser
|
|
3
|
-
module ActionController
|
|
4
|
-
|
|
5
|
-
# Add me to your ApplicationController
|
|
6
|
-
# before_action :set_effective_roles_current_user
|
|
7
|
-
|
|
8
|
-
def set_effective_roles_current_user
|
|
9
|
-
EffectiveRoles.current_user = current_user
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|