rabarber 1.0.2 → 1.0.4

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: 9b3ce45aa7325a095c750691a8633e323a57a987b2c4e4f45902726ce0d30458
4
- data.tar.gz: 66be6c782c564ef658a405ec94c2ada4b46915820a0b9ac5afcfbf0a5bbcedd8
3
+ metadata.gz: 2df45030b2e771a3825eb72a544575fce977253f77ce26673f65372c9d03c06e
4
+ data.tar.gz: 3538bc9bc309f5715cdf25426d21b9353be873b2e7c25bc135403b4382342678
5
5
  SHA512:
6
- metadata.gz: bb12a4ed60e610cb9875243bb87d78ba0e0ab0713507d1967485e16b57fbe7856cbfcf855878b37c75827d02f81fa7baa8cd2f299020bb24dc621fa44aeaf902
7
- data.tar.gz: 3e65bde49df87b1656eab0b92b8da9cd5fd5975e725911026d8ada08b95eedf912aea4dffb0aa39ba1319979ed4cbb90ff234c66a32b91bbd3c3cda224867e64
6
+ metadata.gz: 50a7e4d76a49010af472916c1dfea7fd59bfc882ca67f1fd1a3742f2357e112d8fab112a75af6baf404fc02155128f928c3637ca1d7e9c71ecc238bdbe648b62
7
+ data.tar.gz: f020edd72b93678b25761df692bd3b1d361ec9caad9872952d8df79f4e21948ca46e20de2e1dbe41270a8a26d989d7394b79000429d086923dc94b1173b3a166
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 1.0.4
2
+
3
+ - Allow to use strings as role names
4
+
5
+ ## 1.0.3
6
+
7
+ - Enhance clarity by improving error types and messages
8
+ - Resolve inconsistency in types of role names
9
+
1
10
  ## 1.0.2
2
11
 
3
12
  - Various enhancements for gem development and release
data/README.md CHANGED
@@ -7,7 +7,7 @@ Rabarber is an authorization library for Ruby on Rails, primarily designed for u
7
7
 
8
8
  ---
9
9
 
10
- #### Example of Usage:
10
+ **Example of Usage**:
11
11
 
12
12
  Consider a CRM where users with different roles have distinct access levels. For instance, the role 'accountant' can interact with invoices but cannot access marketing information, while the role 'marketer' has access to marketing-related data. Such authorization rules can be easily defined with Rabarber.
13
13
 
@@ -78,7 +78,7 @@ end
78
78
  - `must_have_roles` must be a boolean determining whether a user with no roles can access endpoints permitted to everyone. The default value is `false` (allowing users without roles to access endpoints permitted to everyone).
79
79
  - `when_unauthorized` must be a lambda where you can define your actions when access is not authorized (`controller` is an instance of the controller where the code is executed). By default, the user is redirected back if the request format is HTML; otherwise, a 401 Unauthorized response is sent.
80
80
 
81
- ## Usage
81
+ ## Roles
82
82
 
83
83
  Include `Rabarber::HasRoles` module in your model representing users in your application:
84
84
 
@@ -89,9 +89,9 @@ class User < ApplicationRecord
89
89
  end
90
90
  ```
91
91
 
92
- ### This adds the following methods:
92
+ This adds the following methods:
93
93
 
94
- #### `#assign_roles`
94
+ **`#assign_roles`**
95
95
 
96
96
  To assign roles to the user, use:
97
97
 
@@ -110,7 +110,7 @@ Rabarber::Role.create(name: "manager")
110
110
  ```
111
111
  The role names are unique.
112
112
 
113
- #### `#revoke_roles`
113
+ **`#revoke_roles`**
114
114
 
115
115
  To revoke roles, use:
116
116
 
@@ -119,7 +119,7 @@ user.revoke_roles(:accountant, :marketer)
119
119
  ```
120
120
  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.
121
121
 
122
- #### `#has_role?`
122
+ **`#has_role?`**
123
123
 
124
124
  To check whether the user has a role, use:
125
125
 
@@ -129,7 +129,7 @@ user.has_role?(:accountant, :marketer)
129
129
 
130
130
  It returns `true` if the user has at least one role and `false` otherwise.
131
131
 
132
- #### `#roles`
132
+ **`#roles`**
133
133
 
134
134
  To view all the roles assigned to the user, use:
135
135
 
@@ -147,9 +147,7 @@ Rabarber::Role.names
147
147
 
148
148
  Utilize the aforementioned methods to manipulate user roles. For example, create a custom UI for managing roles or assign necessary roles during migration or runtime (e.g., when the user is created). You can also write custom authorization policies based on `#has_role?` method (e.g., to scope the data that the user can access). Adapt these methods to fit the requirements of your application.
149
149
 
150
- ---
151
-
152
- ### Authorization Rules
150
+ ## Authorization Rules
153
151
 
154
152
  Include `Rabarber::Authorization` module into the controller that needs authorization rules to be applied (authorization rules will be applied to the controller and its children). Typically, it is `ApplicationController`, but it can be any controller.
155
153
 
@@ -159,7 +157,7 @@ class ApplicationController < ActionController::Base
159
157
  ...
160
158
  end
161
159
  ```
162
- This adds `.grant_access` method to the controller and its children. This method allows you to define the authorization rules.
160
+ This adds `.grant_access` method which allows you to define the authorization rules.
163
161
 
164
162
  The most basic usage of the method is as follows:
165
163
 
@@ -260,9 +258,7 @@ end
260
258
  ```
261
259
  This means that `Crm::InvoicesController` is still accessible to `admin` but is also accessible to `accountant`.
262
260
 
263
- ---
264
-
265
- ### View Helpers
261
+ ## View Helpers
266
262
 
267
263
  Rabarber also provides a couple of helpers that can be used in views: `visible_to` and `hidden_from`. The usage is straightforward:
268
264
 
@@ -21,21 +21,21 @@ module Rabarber
21
21
  end
22
22
 
23
23
  def current_user_method=(method_name)
24
- unless [Symbol, String].include?(method_name.class)
25
- raise ArgumentError, "Method name must be a symbol or a string"
24
+ unless (method_name.is_a?(Symbol) || method_name.is_a?(String)) && method_name.present?
25
+ raise ConfigurationError, "Configuration 'current_user_method' must be a Symbol or a String"
26
26
  end
27
27
 
28
28
  @current_user_method = method_name.to_sym
29
29
  end
30
30
 
31
31
  def must_have_roles=(value)
32
- raise ArgumentError, "Value must be a boolean" unless [true, false].include?(value)
32
+ raise ConfigurationError, "Configuration 'must_have_roles' must be a Boolean" unless [true, false].include?(value)
33
33
 
34
34
  @must_have_roles = value
35
35
  end
36
36
 
37
37
  def when_unauthorized=(callable)
38
- raise ArgumentError, "Proc is expected" unless callable.is_a?(Proc)
38
+ raise ConfigurationError, "Configuration 'when_unauthorized' must be a Proc" unless callable.is_a?(Proc)
39
39
 
40
40
  @when_unauthorized = callable
41
41
  end
@@ -19,38 +19,23 @@ module Rabarber
19
19
  end
20
20
 
21
21
  def has_role?(*role_names)
22
- validate_role_names(role_names)
23
-
24
- (roles & role_names).any?
22
+ (roles & RoleNames.pre_process(role_names)).any?
25
23
  end
26
24
 
27
25
  def assign_roles(*role_names, create_new: true)
28
- validate_role_names(role_names)
26
+ roles_to_assign = RoleNames.pre_process(role_names)
29
27
 
30
- create_new_roles(role_names) if create_new
28
+ create_new_roles(roles_to_assign) if create_new
31
29
 
32
- rabarber_roles << Role.where(name: role_names) - rabarber_roles
30
+ rabarber_roles << Role.where(name: roles_to_assign) - rabarber_roles
33
31
  end
34
32
 
35
33
  def revoke_roles(*role_names)
36
- validate_role_names(role_names)
37
-
38
- self.rabarber_roles = rabarber_roles - Role.where(name: role_names)
34
+ self.rabarber_roles = rabarber_roles - Role.where(name: RoleNames.pre_process(role_names))
39
35
  end
40
36
 
41
37
  private
42
38
 
43
- def validate_role_names(role_names)
44
- return if role_names.all? do |role_name|
45
- [Symbol, String].include?(role_name.class) && role_name.match?(/\A[a-z0-9_]+\z/)
46
- end
47
-
48
- raise(
49
- ArgumentError,
50
- "Role names must be symbols or strings and may only contain lowercase letters and underscores"
51
- )
52
- end
53
-
54
39
  def create_new_roles(role_names)
55
40
  new_roles = role_names - Role.names
56
41
  new_roles.each { |role_name| Role.create!(name: role_name) }
@@ -4,7 +4,7 @@ module Rabarber
4
4
  class Role < ActiveRecord::Base
5
5
  self.table_name = "rabarber_roles"
6
6
 
7
- validates :name, presence: true, uniqueness: true
7
+ validates :name, presence: true, uniqueness: true, format: { with: RoleNames::REGEX }
8
8
 
9
9
  def self.names
10
10
  pluck(:name).map(&:to_sym)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rabarber
4
+ module RoleNames
5
+ module_function
6
+
7
+ REGEX = /\A[a-z0-9_]+\z/
8
+
9
+ def pre_process(role_names)
10
+ return role_names.map(&:to_sym) if role_names.all? do |role_name|
11
+ (role_name.is_a?(Symbol) || role_name.is_a?(String)) && role_name.to_s.match?(REGEX)
12
+ end
13
+
14
+ raise(
15
+ InvalidArgumentError,
16
+ "Role names must be Symbols or Strings and may only contain lowercase letters, numbers and underscores"
17
+ )
18
+ end
19
+ end
20
+ end
data/lib/rabarber/rule.rb CHANGED
@@ -5,9 +5,9 @@ module Rabarber
5
5
  attr_reader :action, :roles, :custom
6
6
 
7
7
  def initialize(action, roles, custom)
8
- @action = action
9
- @roles = Array(roles)
10
- @custom = custom
8
+ @action = pre_process_action(action)
9
+ @roles = RoleNames.pre_process(Array(roles))
10
+ @custom = pre_process_custom_rule(custom)
11
11
  end
12
12
 
13
13
  def verify_access(user_roles, custom_rule_receiver, action_name = nil)
@@ -37,5 +37,19 @@ module Rabarber
37
37
  custom_rule_receiver.send(custom)
38
38
  end
39
39
  end
40
+
41
+ def pre_process_action(action)
42
+ return action.to_sym if (action.is_a?(String) || action.is_a?(Symbol)) && action.present?
43
+ return action if action.nil?
44
+
45
+ raise InvalidArgumentError, "Action name must be a Symbol or a String"
46
+ end
47
+
48
+ def pre_process_custom_rule(custom)
49
+ return custom.to_sym if (custom.is_a?(String) || custom.is_a?(Symbol)) && action.present?
50
+ return custom if custom.nil? || custom.is_a?(Proc)
51
+
52
+ raise InvalidArgumentError, "Custom rule must be a Symbol, a String, or a Proc"
53
+ end
40
54
  end
41
55
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rabarber
4
- VERSION = "1.0.2"
4
+ VERSION = "1.0.4"
5
5
  end
data/lib/rabarber.rb CHANGED
@@ -6,13 +6,12 @@ require_relative "rabarber/configuration"
6
6
  require "active_record"
7
7
  require "active_support"
8
8
 
9
- require_relative "rabarber/controllers/concerns/authorization"
9
+ require_relative "rabarber/role_names"
10
10
 
11
+ require_relative "rabarber/controllers/concerns/authorization"
11
12
  require_relative "rabarber/helpers/helpers"
12
-
13
- require_relative "rabarber/models/role"
14
13
  require_relative "rabarber/models/concerns/has_roles"
15
-
14
+ require_relative "rabarber/models/role"
16
15
  require_relative "rabarber/permissions"
17
16
 
18
17
  module Rabarber
@@ -23,4 +22,6 @@ module Rabarber
23
22
  end
24
23
 
25
24
  class Error < StandardError; end
25
+ class ConfigurationError < Error; end
26
+ class InvalidArgumentError < Error; end
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabarber
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-01 00:00:00.000000000 Z
11
+ date: 2024-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -44,6 +44,7 @@ files:
44
44
  - lib/rabarber/models/concerns/has_roles.rb
45
45
  - lib/rabarber/models/role.rb
46
46
  - lib/rabarber/permissions.rb
47
+ - lib/rabarber/role_names.rb
47
48
  - lib/rabarber/rule.rb
48
49
  - lib/rabarber/version.rb
49
50
  - rabarber.gemspec