rabarber 1.2.2 → 1.3.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/CHANGELOG.md +6 -0
- data/README.md +52 -4
- data/lib/rabarber/cache.rb +4 -4
- data/lib/rabarber/models/concerns/has_roles.rb +21 -7
- data/lib/rabarber/models/role.rb +57 -7
- data/lib/rabarber/permissions.rb +15 -13
- data/lib/rabarber/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77a15b7eb4164c74d70e81d34630d6051915acc2abe35896df8938d9cc53e473
|
4
|
+
data.tar.gz: 847f675e00e9a85a158032af7ddc158f3189df78d4e6dae4ce15e2fe5024515e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d16835ed84fd9ee2c2e7871080c5256bad34944ee0c1a3448c609f14732f1c7901539c0287bc5206feddb79ef77ee4aa001dd26a642d7c23b05498f5a668659
|
7
|
+
data.tar.gz: 0bd35329a6608d4f6680b4aba7882d015df36f38e0b0d963c9df988edd40e490e67180e504b1901f05c957e27f8bffe585372f6494ccad2989310daaa7feec68
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 1.3.0
|
2
|
+
|
3
|
+
- Add methods to directly add, rename, and remove roles
|
4
|
+
- `HasRoles#assign_roles` and `HasRoles#revoke_roles` methods now return the list of roles assigned to the user
|
5
|
+
- Minor performance improvements
|
6
|
+
|
1
7
|
## 1.2.2
|
2
8
|
|
3
9
|
- Refactor to improve readability and maintainability
|
data/README.md
CHANGED
@@ -67,16 +67,16 @@ Rabarber can be configured by using `.configure` method in an initializer:
|
|
67
67
|
|
68
68
|
```rb
|
69
69
|
Rabarber.configure do |config|
|
70
|
-
config.cache_enabled =
|
71
|
-
config.current_user_method = :
|
72
|
-
config.must_have_roles =
|
70
|
+
config.cache_enabled = true
|
71
|
+
config.current_user_method = :current_user
|
72
|
+
config.must_have_roles = false
|
73
73
|
config.when_actions_missing = -> (missing_actions, context) { ... }
|
74
74
|
config.when_roles_missing = -> (missing_roles, context) { ... }
|
75
75
|
config.when_unauthorized = -> (controller) { ... }
|
76
76
|
end
|
77
77
|
```
|
78
78
|
|
79
|
-
- `cache_enabled` must be a boolean determining whether roles are cached. Roles are cached by default to avoid unnecessary database queries. If you want to disable caching, set this option to `false`. If caching is enabled and you need to clear the cache, use
|
79
|
+
- `cache_enabled` must be a boolean determining whether roles are cached. Roles are cached by default to avoid unnecessary database queries. If you want to disable caching, set this option to `false`. If caching is enabled and you need to clear the cache, use `Rabarber::Cache.clear` method.
|
80
80
|
|
81
81
|
- `current_user_method` must be a symbol representing the method that returns the currently authenticated user. The default value is `:current_user`.
|
82
82
|
|
@@ -112,6 +112,7 @@ By default, `#assign_roles` method will automatically create any roles that don'
|
|
112
112
|
```rb
|
113
113
|
user.assign_roles(:accountant, :marketer, create_new: false)
|
114
114
|
```
|
115
|
+
The method returns an array of roles assigned to the user.
|
115
116
|
|
116
117
|
**`#revoke_roles`**
|
117
118
|
|
@@ -122,6 +123,8 @@ user.revoke_roles(:accountant, :marketer)
|
|
122
123
|
```
|
123
124
|
If any of the specified roles doesn't exist or the user doesn't have the role you want to revoke, it will be ignored.
|
124
125
|
|
126
|
+
The method returns an array of roles assigned to the user.
|
127
|
+
|
125
128
|
**`#has_role?`**
|
126
129
|
|
127
130
|
To check whether the user has a role, use:
|
@@ -140,6 +143,51 @@ To view all the roles assigned to the user, use:
|
|
140
143
|
user.roles
|
141
144
|
```
|
142
145
|
|
146
|
+
---
|
147
|
+
|
148
|
+
To manipulate roles directly, you can use `Rabarber::Role` methods:
|
149
|
+
|
150
|
+
**`.add`**
|
151
|
+
|
152
|
+
To add a new role, use:
|
153
|
+
|
154
|
+
```rb
|
155
|
+
Rabarber::Role.add(:admin)
|
156
|
+
```
|
157
|
+
|
158
|
+
This will create a new role with the specified name and return `true`. If the role already exists, it will return `false`.
|
159
|
+
|
160
|
+
**`.rename`**
|
161
|
+
|
162
|
+
To rename a role, use:
|
163
|
+
|
164
|
+
```rb
|
165
|
+
Rabarber::Role.rename(:admin, :administrator)
|
166
|
+
```
|
167
|
+
The first argument is the old name, and the second argument is the new name. This will rename the role and return `true`. If a role with the new name already exists, it will return `false`.
|
168
|
+
|
169
|
+
The method won't rename the role if it is assigned to any user. To force the rename, use the method with `force: true` argument:
|
170
|
+
```rb
|
171
|
+
Rabarber::Role.rename(:admin, :administrator, force: true)
|
172
|
+
```
|
173
|
+
|
174
|
+
**`.remove`**
|
175
|
+
|
176
|
+
To remove a role, use:
|
177
|
+
|
178
|
+
```rb
|
179
|
+
Rabarber::Role.remove(:admin)
|
180
|
+
```
|
181
|
+
|
182
|
+
This will remove the role and return `true`. If the role doesn't exist, it will return `false`.
|
183
|
+
|
184
|
+
The method won't remove the role if it is assigned to any user. To force the removal, use the method with `force: true` argument:
|
185
|
+
```rb
|
186
|
+
Rabarber::Role.remove(:admin, force: true)
|
187
|
+
```
|
188
|
+
|
189
|
+
**`.names`**
|
190
|
+
|
143
191
|
If you need to list all the role names available in your application, use:
|
144
192
|
|
145
193
|
```rb
|
data/lib/rabarber/cache.rb
CHANGED
@@ -10,16 +10,16 @@ module Rabarber
|
|
10
10
|
enabled? ? Rails.cache.fetch(key, options, &block) : yield
|
11
11
|
end
|
12
12
|
|
13
|
-
def delete(
|
14
|
-
Rails.cache.
|
13
|
+
def delete(*keys)
|
14
|
+
Rails.cache.delete_multi(keys) if enabled?
|
15
15
|
end
|
16
16
|
|
17
17
|
def enabled?
|
18
18
|
Rabarber::Configuration.instance.cache_enabled
|
19
19
|
end
|
20
20
|
|
21
|
-
def key_for(
|
22
|
-
"rabarber:roles_#{
|
21
|
+
def key_for(id)
|
22
|
+
"rabarber:roles_#{id}"
|
23
23
|
end
|
24
24
|
|
25
25
|
def clear
|
@@ -17,7 +17,7 @@ module Rabarber
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def roles
|
20
|
-
Rabarber::Cache.fetch(Rabarber::Cache.key_for(
|
20
|
+
Rabarber::Cache.fetch(Rabarber::Cache.key_for(roleable_id), expires_in: 1.hour, race_condition_ttl: 5.seconds) do
|
21
21
|
rabarber_roles.names
|
22
22
|
end
|
23
23
|
end
|
@@ -31,15 +31,25 @@ module Rabarber
|
|
31
31
|
|
32
32
|
create_new_roles(roles_to_assign) if create_new
|
33
33
|
|
34
|
-
|
34
|
+
new_roles = Rabarber::Role.where(name: roles_to_assign) - rabarber_roles
|
35
35
|
|
36
|
-
|
36
|
+
if new_roles.any?
|
37
|
+
delete_roleable_cache
|
38
|
+
rabarber_roles << new_roles
|
39
|
+
end
|
40
|
+
|
41
|
+
roles
|
37
42
|
end
|
38
43
|
|
39
44
|
def revoke_roles(*role_names)
|
40
|
-
|
45
|
+
new_roles = rabarber_roles - Rabarber::Role.where(name: process_role_names(role_names))
|
46
|
+
|
47
|
+
if rabarber_roles != new_roles
|
48
|
+
delete_roleable_cache
|
49
|
+
self.rabarber_roles = new_roles
|
50
|
+
end
|
41
51
|
|
42
|
-
|
52
|
+
roles
|
43
53
|
end
|
44
54
|
|
45
55
|
private
|
@@ -53,8 +63,12 @@ module Rabarber
|
|
53
63
|
Rabarber::Input::Roles.new(role_names).process
|
54
64
|
end
|
55
65
|
|
56
|
-
def
|
57
|
-
Rabarber::Cache.delete(Rabarber::Cache.key_for(
|
66
|
+
def delete_roleable_cache
|
67
|
+
Rabarber::Cache.delete(Rabarber::Cache.key_for(roleable_id))
|
68
|
+
end
|
69
|
+
|
70
|
+
def roleable_id
|
71
|
+
public_send(self.class.primary_key)
|
58
72
|
end
|
59
73
|
end
|
60
74
|
end
|
data/lib/rabarber/models/role.rb
CHANGED
@@ -6,16 +6,66 @@ module Rabarber
|
|
6
6
|
|
7
7
|
validates :name, presence: true, uniqueness: true, format: { with: Rabarber::Input::Roles::REGEX }
|
8
8
|
|
9
|
-
|
9
|
+
has_and_belongs_to_many :roleables, join_table: "rabarber_roles_roleables"
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
class << self
|
12
|
+
def names
|
13
|
+
pluck(:name).map(&:to_sym)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(name)
|
17
|
+
name = process_role_name(name)
|
18
|
+
|
19
|
+
return false if exists?(name: name)
|
20
|
+
|
21
|
+
delete_roles_cache
|
22
|
+
|
23
|
+
!!create!(name: name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def rename(old_name, new_name, force: false)
|
27
|
+
role = find_by(name: process_role_name(old_name))
|
28
|
+
name = process_role_name(new_name)
|
29
|
+
|
30
|
+
return false if !role || exists?(name: name) || assigned_to_roleables(role).any? && !force
|
31
|
+
|
32
|
+
delete_roles_cache
|
33
|
+
delete_roleables_cache(role)
|
34
|
+
|
35
|
+
role.update!(name: name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove(name, force: false)
|
39
|
+
role = find_by(name: process_role_name(name))
|
40
|
+
|
41
|
+
return false if !role || assigned_to_roleables(role).any? && !force
|
42
|
+
|
43
|
+
delete_roles_cache
|
44
|
+
delete_roleables_cache(role)
|
45
|
+
|
46
|
+
!!role.destroy!
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def delete_roles_cache
|
52
|
+
Rabarber::Cache.delete(Rabarber::Cache::ALL_ROLES_KEY)
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_roleables_cache(role)
|
56
|
+
keys = assigned_to_roleables(role).map { |roleable_id| Rabarber::Cache.key_for(roleable_id) }
|
57
|
+
Rabarber::Cache.delete(*keys) if keys.any?
|
58
|
+
end
|
14
59
|
|
15
|
-
|
60
|
+
def assigned_to_roleables(role)
|
61
|
+
ActiveRecord::Base.connection.select_values(
|
62
|
+
"SELECT roleable_id FROM rabarber_roles_roleables WHERE role_id = #{role.id}"
|
63
|
+
)
|
64
|
+
end
|
16
65
|
|
17
|
-
|
18
|
-
|
66
|
+
def process_role_name(name)
|
67
|
+
Rabarber::Input::Roles.new(name).process[0]
|
68
|
+
end
|
19
69
|
end
|
20
70
|
end
|
21
71
|
end
|
data/lib/rabarber/permissions.rb
CHANGED
@@ -15,22 +15,24 @@ module Rabarber
|
|
15
15
|
@storage = { controller_rules: Hash.new({}), action_rules: Hash.new([]) }
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
class << self
|
19
|
+
def add(controller, action, roles, dynamic_rule, negated_dynamic_rule)
|
20
|
+
rule = Rabarber::Rule.new(action, roles, dynamic_rule, negated_dynamic_rule)
|
21
|
+
|
22
|
+
if action
|
23
|
+
instance.storage[:action_rules][controller] += [rule]
|
24
|
+
else
|
25
|
+
instance.storage[:controller_rules][controller] = rule
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def controller_rules
|
30
|
+
instance.storage[:controller_rules]
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
33
|
+
def action_rules
|
34
|
+
instance.storage[:action_rules]
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
data/lib/rabarber/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rabarber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- enjaku4
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-02-
|
12
|
+
date: 2024-02-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '0'
|
82
82
|
requirements: []
|
83
|
-
rubygems_version: 3.
|
83
|
+
rubygems_version: 3.3.26
|
84
84
|
signing_key:
|
85
85
|
specification_version: 4
|
86
86
|
summary: Simple authorization library for Ruby on Rails.
|