restme 1.2.2 → 1.3.1
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/Dockerfile +2 -0
- data/README.md +36 -6
- data/lib/restme/authorize/rules.rb +5 -6
- data/lib/restme/create/rules.rb +10 -6
- data/lib/restme/scope/field/attachable.rb +10 -8
- data/lib/restme/scope/field/rules.rb +20 -8
- data/lib/restme/scope/rules.rb +23 -5
- data/lib/restme/shared/restme_current_user_roles.rb +18 -0
- data/lib/restme/update/rules.rb +10 -6
- data/lib/restme/version.rb +1 -1
- metadata +2 -2
- data/lib/restme/shared/restme_current_user_role.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e523f7df013c44f903677642433e4a602469110597bf654327d1d2ef26bf0b2
|
|
4
|
+
data.tar.gz: 41f22e4c3efe48f3df65165badd1d3a58974f5a8dc183e4c2aeb3fff19b548e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3bf751aee7203b756dd96025063c144801db5b2dd568ce9df34dada419985efda09dc8c912b310d09d1fa389dce7c715f66a12e97908776c21fd7174bcae406d
|
|
7
|
+
data.tar.gz: c7a4a9442dbd845ca7e0b07d68992a53e8427a97aa95fd2527c0f36627a5901bfcb7db3ac2cc43a42e722bdf09fc97aec22be3be729951be6c3e4665b6f56330
|
data/Dockerfile
CHANGED
data/README.md
CHANGED
|
@@ -16,7 +16,7 @@ This gem manages your controller's responsibilities for:
|
|
|
16
16
|
|
|
17
17
|
GEMFILE:
|
|
18
18
|
```bash
|
|
19
|
-
gem 'restme', '~> 1.
|
|
19
|
+
gem 'restme', '~> 1.3.0'
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
INSTALL:
|
|
@@ -28,7 +28,7 @@ gem 'restme'
|
|
|
28
28
|
|
|
29
29
|
#### ℹ️ Current Version of gem require the following pré configs
|
|
30
30
|
- Your controllers must be named using the plural form of the model (e.g., Product → ProductsController). Alternatively, you can manually set the model name by defining the MODEL_NAME constant (e.g., MODEL_NAME = "Product").
|
|
31
|
-
- You must create a folder inside app named
|
|
31
|
+
- You must create a folder inside app named restme to define controller rules for authorization, scoping, creation, updating, and field selection (see example below).
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
<br>
|
|
@@ -57,6 +57,31 @@ Restme.configure do |config|
|
|
|
57
57
|
end
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
`current_user_variable`
|
|
61
|
+
|
|
62
|
+
Defines the name of the method used to access the currently authenticated user within the controller context.
|
|
63
|
+
This should match the method that returns the logged-in user (for example, :current_user when using authentication libraries like Devise).
|
|
64
|
+
Represent the the field where the role of user is (can be one or many rules)
|
|
65
|
+
|
|
66
|
+
`user_role_field`
|
|
67
|
+
|
|
68
|
+
Defines the attribute on the user model that represents the user's role.
|
|
69
|
+
This field is used to determine authorization rules and may support single or multiple roles, depending on your application's implementation.
|
|
70
|
+
|
|
71
|
+
`pagination_default_per_page`
|
|
72
|
+
|
|
73
|
+
Specifies the default number of records returned per page when pagination parameters are not explicitly provided in the request.
|
|
74
|
+
|
|
75
|
+
`pagination_default_page`
|
|
76
|
+
|
|
77
|
+
Specifies the default page number used when the request does not include a page parameter.
|
|
78
|
+
|
|
79
|
+
`pagination_max_per_page`
|
|
80
|
+
|
|
81
|
+
Defines the maximum number of records allowed per page.
|
|
82
|
+
This acts as a safety limit to prevent clients from requesting excessively large result sets, helping protect application performance and resource usage.
|
|
83
|
+
|
|
84
|
+
|
|
60
85
|
<br>
|
|
61
86
|
|
|
62
87
|
|
|
@@ -209,6 +234,13 @@ This rule defines which nested_fields are selectable (nested fields are model re
|
|
|
209
234
|
```ruby
|
|
210
235
|
module ProductsController::Field
|
|
211
236
|
class Rules
|
|
237
|
+
# Defines the default fields that will be automatically selected
|
|
238
|
+
# in queries when no explicit field selection is provided.
|
|
239
|
+
# These fields are always included in the response.
|
|
240
|
+
MODEL_FIELDS_SELECT = %i[id].freeze
|
|
241
|
+
|
|
242
|
+
UNALLOWED_MODEL_FIELDS_SELECT = %i[internal_code].freeze
|
|
243
|
+
|
|
212
244
|
NESTED_SELECTABLE_FIELDS = {
|
|
213
245
|
unit: {},
|
|
214
246
|
establishment: {},
|
|
@@ -288,8 +320,6 @@ There are two query parameters available to control pagination:
|
|
|
288
320
|
- `per_page`: Defines the number of items per page.
|
|
289
321
|
- `page`: Sets the current page number.
|
|
290
322
|
|
|
291
|
-
ℹ️ **Note:** The maximum number of items per page is currently limited to 100.
|
|
292
|
-
|
|
293
323
|
Example usage:
|
|
294
324
|
|
|
295
325
|
```bash
|
|
@@ -301,8 +331,8 @@ http://localhost:3000/api/v1/products?per_page=12&page=1
|
|
|
301
331
|
|
|
302
332
|
#### Field Selection (`fields_select`)
|
|
303
333
|
|
|
304
|
-
You can select specific fields from your model, such as `id`, `name`, or `created_at`.
|
|
305
|
-
The
|
|
334
|
+
You can select specific fields from your model, such as `id`, `name`, or `created_at`.
|
|
335
|
+
The generated query will retrieve only the selected fields directly from the database, reducing unnecessary data loading and improving performance.
|
|
306
336
|
|
|
307
337
|
Example:
|
|
308
338
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../shared/
|
|
3
|
+
require_relative "../shared/restme_current_user_roles"
|
|
4
4
|
require_relative "../shared/current_model"
|
|
5
5
|
|
|
6
6
|
module Restme
|
|
@@ -8,7 +8,7 @@ module Restme
|
|
|
8
8
|
# Defines the rules used to authotize user
|
|
9
9
|
module Rules
|
|
10
10
|
include ::Restme::Shared::CurrentModel
|
|
11
|
-
include ::Restme::Shared::
|
|
11
|
+
include ::Restme::Shared::RestmeCurrentUserRoles
|
|
12
12
|
|
|
13
13
|
def user_authorized?
|
|
14
14
|
return true if restme_current_user.blank? || authorize?
|
|
@@ -19,8 +19,7 @@ module Restme
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def authorize?
|
|
22
|
-
allowed_roles_actions
|
|
23
|
-
&.include?(restme_current_user_role&.to_sym)
|
|
22
|
+
(allowed_roles_actions & restme_current_user_roles)&.any?
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
def authorize_errors
|
|
@@ -35,9 +34,9 @@ module Restme
|
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
def allowed_roles_actions
|
|
38
|
-
return
|
|
37
|
+
return [] unless authorize_rules_class&.const_defined?(:ALLOWED_ROLES_ACTIONS)
|
|
39
38
|
|
|
40
|
-
authorize_rules_class::ALLOWED_ROLES_ACTIONS
|
|
39
|
+
authorize_rules_class::ALLOWED_ROLES_ACTIONS[action_name.to_sym] || []
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
def authorize_rules_class
|
data/lib/restme/create/rules.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../shared/
|
|
3
|
+
require_relative "../shared/restme_current_user_roles"
|
|
4
4
|
require_relative "../shared/current_model"
|
|
5
5
|
require_relative "../shared/controller_params"
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ module Restme
|
|
|
10
10
|
module Rules
|
|
11
11
|
include ::Restme::Shared::ControllerParams
|
|
12
12
|
include ::Restme::Shared::CurrentModel
|
|
13
|
-
include ::Restme::Shared::
|
|
13
|
+
include ::Restme::Shared::RestmeCurrentUserRoles
|
|
14
14
|
|
|
15
15
|
attr_reader :create_temp_record
|
|
16
16
|
|
|
@@ -34,7 +34,7 @@ module Restme
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def restme_create_status
|
|
37
|
-
return :
|
|
37
|
+
return :unprocessable_content if create_record_errors
|
|
38
38
|
|
|
39
39
|
:created
|
|
40
40
|
end
|
|
@@ -64,9 +64,13 @@ module Restme
|
|
|
64
64
|
def createable_scope?
|
|
65
65
|
return true unless restme_current_user
|
|
66
66
|
|
|
67
|
-
method_scope
|
|
67
|
+
restme_create_methods_scopes.any? { |method_scope| create_rules_class.try(method_scope) }
|
|
68
|
+
end
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
def restme_create_methods_scopes
|
|
71
|
+
@restme_create_methods_scopes ||= restme_current_user_roles.map do |restme_role|
|
|
72
|
+
"#{creatable_current_action}_#{restme_role}_scope?"
|
|
73
|
+
end
|
|
70
74
|
end
|
|
71
75
|
|
|
72
76
|
def createable_object_errors_messages
|
|
@@ -78,7 +82,7 @@ module Restme
|
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
def creatable_current_action
|
|
81
|
-
return
|
|
85
|
+
return unless create_rules_class
|
|
82
86
|
|
|
83
87
|
current_action.presence_in create_rules_class.class::CREATABLE_ACTIONS_RULES
|
|
84
88
|
rescue StandardError
|
|
@@ -25,10 +25,13 @@ module Restme
|
|
|
25
25
|
|
|
26
26
|
def define_attachment_methods
|
|
27
27
|
attachment_fields_select.each do |attachment_field_name|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
method_name = "#{attachment_field_name}_url"
|
|
29
|
+
|
|
30
|
+
next if klass.method_defined?(method_name)
|
|
31
|
+
|
|
32
|
+
klass.define_method(method_name) do
|
|
33
|
+
attachment = public_send(attachment_field_name)
|
|
34
|
+
attachment&.url
|
|
32
35
|
end
|
|
33
36
|
end
|
|
34
37
|
end
|
|
@@ -50,10 +53,9 @@ module Restme
|
|
|
50
53
|
def unallowed_attachment_fields_error
|
|
51
54
|
return if unallowed_attachment_fields.blank?
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}, status: :bad_request
|
|
56
|
+
restme_scope_errors({ body: unallowed_attachment_fields, message: "Selected not allowed attachment fields" })
|
|
57
|
+
|
|
58
|
+
restme_scope_status(:bad_request)
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def unallowed_attachment_fields
|
|
@@ -30,19 +30,31 @@ module Restme
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def select_any_field?
|
|
33
|
-
fields_select || nested_fields_select || attachment_fields_select
|
|
33
|
+
defined_fields_select || fields_select || nested_fields_select || attachment_fields_select
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def model_fields_select
|
|
37
|
-
@model_fields_select ||=
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
@model_fields_select ||= select_selected_fields.presence || model_attributes
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def select_selected_fields
|
|
41
|
+
@select_selected_fields ||= defined_fields_select | fields_select.split(",").map(&:to_s)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def model_attributes
|
|
45
|
-
@model_attributes ||= klass.
|
|
45
|
+
@model_attributes ||= klass.attribute_names - unallowed_model_fields_select
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def defined_fields_select
|
|
49
|
+
return [] unless field_class_rules&.const_defined?(:MODEL_FIELDS_SELECT)
|
|
50
|
+
|
|
51
|
+
(field_class_rules::MODEL_FIELDS_SELECT || []).map(&:to_s)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def unallowed_model_fields_select
|
|
55
|
+
return [] unless field_class_rules&.const_defined?(:UNALLOWED_MODEL_FIELDS_SELECT)
|
|
56
|
+
|
|
57
|
+
(field_class_rules::UNALLOWED_MODEL_FIELDS_SELECT || []).map(&:to_s)
|
|
46
58
|
end
|
|
47
59
|
|
|
48
60
|
def valid_nested_fields_select
|
|
@@ -79,7 +91,7 @@ module Restme
|
|
|
79
91
|
end
|
|
80
92
|
|
|
81
93
|
def fields_select
|
|
82
|
-
@fields_select ||= controller_query_params[:fields_select]
|
|
94
|
+
@fields_select ||= controller_query_params[:fields_select] || ""
|
|
83
95
|
end
|
|
84
96
|
|
|
85
97
|
def nested_fields_select
|
data/lib/restme/scope/rules.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../shared/
|
|
3
|
+
require_relative "../shared/restme_current_user_roles"
|
|
4
4
|
require_relative "../shared/current_model"
|
|
5
5
|
require_relative "../shared/controller_params"
|
|
6
6
|
require_relative "filter/rules"
|
|
@@ -20,7 +20,7 @@ module Restme
|
|
|
20
20
|
include ::Restme::Scope::Filter::Rules
|
|
21
21
|
include ::Restme::Shared::ControllerParams
|
|
22
22
|
include ::Restme::Shared::CurrentModel
|
|
23
|
-
include ::Restme::Shared::
|
|
23
|
+
include ::Restme::Shared::RestmeCurrentUserRoles
|
|
24
24
|
|
|
25
25
|
attr_reader :filterable_scope_response
|
|
26
26
|
attr_writer :restme_scope_errors, :restme_scope_status
|
|
@@ -30,6 +30,7 @@ module Restme
|
|
|
30
30
|
unknown_sortable_fields_errors
|
|
31
31
|
unallowed_filter_fields_errors
|
|
32
32
|
unallowed_select_fields_errors
|
|
33
|
+
unallowed_attachment_fields_error
|
|
33
34
|
].freeze
|
|
34
35
|
|
|
35
36
|
def pagination_response
|
|
@@ -99,7 +100,22 @@ module Restme
|
|
|
99
100
|
end
|
|
100
101
|
|
|
101
102
|
def user_scope
|
|
102
|
-
@user_scope ||= none_user_scope ||
|
|
103
|
+
@user_scope ||= none_user_scope || process_user_scope || none_scope
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def process_user_scope
|
|
107
|
+
scopes = user_scope_methods.map { |m| scope_rules_class.try(m) }
|
|
108
|
+
|
|
109
|
+
processed_scope = scopes.reduce { |combined, s| combined.or(s) }
|
|
110
|
+
|
|
111
|
+
user_scope_methods.many? ? processed_scope&.distinct : processed_scope
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def user_scope_methods
|
|
115
|
+
@user_scope_methods ||=
|
|
116
|
+
restme_methods_scopes.select do |method_scope|
|
|
117
|
+
scope_rules_class.respond_to?(method_scope)
|
|
118
|
+
end
|
|
103
119
|
end
|
|
104
120
|
|
|
105
121
|
def none_user_scope
|
|
@@ -110,8 +126,10 @@ module Restme
|
|
|
110
126
|
klass.none
|
|
111
127
|
end
|
|
112
128
|
|
|
113
|
-
def
|
|
114
|
-
|
|
129
|
+
def restme_methods_scopes
|
|
130
|
+
@restme_methods_scopes ||= restme_current_user_roles.map do |restme_role|
|
|
131
|
+
"#{restme_role}_scope"
|
|
132
|
+
end
|
|
115
133
|
end
|
|
116
134
|
|
|
117
135
|
def scope_rules_class
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Restme
|
|
4
|
+
module Shared
|
|
5
|
+
# Returns the roles associated with the user, always normalized as an Array of symbols.
|
|
6
|
+
module RestmeCurrentUserRoles
|
|
7
|
+
def restme_current_user_roles
|
|
8
|
+
Array.wrap(user_roles).map do |role|
|
|
9
|
+
role.respond_to?(:to_sym) ? role.to_sym : role.to_s.to_sym
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def user_roles
|
|
14
|
+
@user_roles ||= restme_current_user&.try(::Restme::Configuration.user_role_field)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/restme/update/rules.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../shared/
|
|
3
|
+
require_relative "../shared/restme_current_user_roles"
|
|
4
4
|
require_relative "../shared/current_model"
|
|
5
5
|
require_relative "../shared/controller_params"
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ module Restme
|
|
|
10
10
|
module Rules
|
|
11
11
|
include ::Restme::Shared::ControllerParams
|
|
12
12
|
include ::Restme::Shared::CurrentModel
|
|
13
|
-
include ::Restme::Shared::
|
|
13
|
+
include ::Restme::Shared::RestmeCurrentUserRoles
|
|
14
14
|
|
|
15
15
|
attr_reader :update_temp_record
|
|
16
16
|
|
|
@@ -36,7 +36,7 @@ module Restme
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def restme_update_status
|
|
39
|
-
return :
|
|
39
|
+
return :unprocessable_content if update_record_errors
|
|
40
40
|
|
|
41
41
|
:ok
|
|
42
42
|
end
|
|
@@ -74,9 +74,13 @@ module Restme
|
|
|
74
74
|
def updateable_scope?
|
|
75
75
|
return true unless restme_current_user
|
|
76
76
|
|
|
77
|
-
method_scope
|
|
77
|
+
restme_update_methods_scopes.any? { |method_scope| update_rules_class.try(method_scope) }
|
|
78
|
+
end
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
def restme_update_methods_scopes
|
|
81
|
+
@restme_update_methods_scopes ||= restme_current_user_roles.map do |restme_role|
|
|
82
|
+
"#{updateable_current_action}_#{restme_role}_scope?"
|
|
83
|
+
end
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
def updateable_record_errors_messages
|
|
@@ -88,7 +92,7 @@ module Restme
|
|
|
88
92
|
end
|
|
89
93
|
|
|
90
94
|
def updateable_current_action
|
|
91
|
-
return
|
|
95
|
+
return unless update_rules_class
|
|
92
96
|
|
|
93
97
|
current_action.presence_in update_rules_class.class::UPDATABLE_ACTIONS_RULES
|
|
94
98
|
rescue StandardError
|
data/lib/restme/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: restme
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- everson-ever
|
|
@@ -46,7 +46,7 @@ files:
|
|
|
46
46
|
- lib/restme/scope/sort/rules.rb
|
|
47
47
|
- lib/restme/shared/controller_params.rb
|
|
48
48
|
- lib/restme/shared/current_model.rb
|
|
49
|
-
- lib/restme/shared/
|
|
49
|
+
- lib/restme/shared/restme_current_user_roles.rb
|
|
50
50
|
- lib/restme/update/rules.rb
|
|
51
51
|
- lib/restme/version.rb
|
|
52
52
|
- sig/restme.rbs
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Restme
|
|
4
|
-
module Shared
|
|
5
|
-
# Returns the roles associated with the user, if any exist.
|
|
6
|
-
module RestmeCurrentUserRole
|
|
7
|
-
def restme_current_user_role
|
|
8
|
-
restme_current_user&.try(::Restme::Configuration.user_role_field)
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|