rabarber 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '084b409c4886e7622ee37f20b8f00c0d6e083546394bf3617bdd5277548a2764'
4
- data.tar.gz: 62c3f5fb0496fc5a0cf95f04f0f04d26ba4f847bdf1e838c248361dca72744ee
3
+ metadata.gz: 77a15b7eb4164c74d70e81d34630d6051915acc2abe35896df8938d9cc53e473
4
+ data.tar.gz: 847f675e00e9a85a158032af7ddc158f3189df78d4e6dae4ce15e2fe5024515e
5
5
  SHA512:
6
- metadata.gz: 0a1b141efb53f2b863f0dbbd1fe4c03ce199b7278bc0c51f8868866b918ea3161b8aebd9920872b43d9aea8cf24c5161b0f87d6d535a7c76295aa7890ee4b337
7
- data.tar.gz: b740291aba6e4d1c529453e990c30e009b5215ccbdc99a5eac6c1b8c21d354c813e5bdd3f700c37e9aa22d528b025814ce69629aedb95449108a704e233c53d2
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 = false
71
- config.current_user_method = :authenticated_user
72
- config.must_have_roles = true
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 the `Rabarber::Cache.clear` method.
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
@@ -10,16 +10,16 @@ module Rabarber
10
10
  enabled? ? Rails.cache.fetch(key, options, &block) : yield
11
11
  end
12
12
 
13
- def delete(key)
14
- Rails.cache.delete(key) if enabled?
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(record)
22
- "rabarber:roles_#{record.public_send(record.class.primary_key)}"
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(self), expires_in: 1.hour, race_condition_ttl: 5.seconds) do
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
- rabarber_roles << Rabarber::Role.where(name: roles_to_assign) - rabarber_roles
34
+ new_roles = Rabarber::Role.where(name: roles_to_assign) - rabarber_roles
35
35
 
36
- delete_cache
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
- self.rabarber_roles = rabarber_roles - Rabarber::Role.where(name: process_role_names(role_names))
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
- delete_cache
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 delete_cache
57
- Rabarber::Cache.delete(Rabarber::Cache.key_for(self))
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
@@ -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
- after_commit :delete_cache
9
+ has_and_belongs_to_many :roleables, join_table: "rabarber_roles_roleables"
10
10
 
11
- def self.names
12
- pluck(:name).map(&:to_sym)
13
- end
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
- private
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
- def delete_cache
18
- Rabarber::Cache.delete(Rabarber::Cache::ALL_ROLES_KEY)
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
@@ -15,22 +15,24 @@ module Rabarber
15
15
  @storage = { controller_rules: Hash.new({}), action_rules: Hash.new([]) }
16
16
  end
17
17
 
18
- def self.add(controller, action, roles, dynamic_rule, negated_dynamic_rule)
19
- rule = Rabarber::Rule.new(action, roles, dynamic_rule, negated_dynamic_rule)
20
-
21
- if action
22
- instance.storage[:action_rules][controller] += [rule]
23
- else
24
- instance.storage[:controller_rules][controller] = rule
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
- def self.controller_rules
29
- instance.storage[:controller_rules]
30
- end
29
+ def controller_rules
30
+ instance.storage[:controller_rules]
31
+ end
31
32
 
32
- def self.action_rules
33
- instance.storage[:action_rules]
33
+ def action_rules
34
+ instance.storage[:action_rules]
35
+ end
34
36
  end
35
37
  end
36
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rabarber
4
- VERSION = "1.2.2"
4
+ VERSION = "1.3.0"
5
5
  end
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.2.2
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-10 00:00:00.000000000 Z
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.2.33
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.