pastore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 44d3e6e0a841c09767bef483f9c53a6c1e11f8a1603671865635a50eb139d0cd
4
+ data.tar.gz: 246bba109256e0bb1e67c0c5cc518640e99ddd2a0ca01a403a4008fd04c53298
5
+ SHA512:
6
+ metadata.gz: bc3fb06cbbc9ae2321a486dea657f2e6645ca3e3ceea3e72d36e5cb6733ef16741097fb29e669d4fbc0e64ef072b5f6ac3edc530a3b5abf0048ad93934d5c926
7
+ data.tar.gz: 8f4d326809b4ed7495a964da19de29a75818a70882c447cef7f202526c764b720bb396f931d879b505fcf49bd7cf85b4d17eee8f3970a915b60d92098c60d8fb
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.6
4
+
5
+ Style/StringLiteralsInInterpolation:
6
+ Enabled: true
7
+ EnforcedStyle: double_quotes
8
+
9
+ Layout/LineLength:
10
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-01-26
4
+
5
+ - Initial release
@@ -0,0 +1,84 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or
22
+ advances of any kind
23
+ * Trolling, insulting or derogatory comments, and personal or political attacks
24
+ * Public or private harassment
25
+ * Publishing others' private information, such as a physical or email
26
+ address, without their explicit permission
27
+ * Other conduct which could reasonably be considered inappropriate in a
28
+ professional setting
29
+
30
+ ## Enforcement Responsibilities
31
+
32
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
33
+
34
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
35
+
36
+ ## Scope
37
+
38
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
39
+
40
+ ## Enforcement
41
+
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at groza@opinioni.net. All complaints will be reviewed and investigated promptly and fairly.
43
+
44
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45
+
46
+ ## Enforcement Guidelines
47
+
48
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
49
+
50
+ ### 1. Correction
51
+
52
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
53
+
54
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
55
+
56
+ ### 2. Warning
57
+
58
+ **Community Impact**: A violation through a single incident or series of actions.
59
+
60
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
61
+
62
+ ### 3. Temporary Ban
63
+
64
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
65
+
66
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
67
+
68
+ ### 4. Permanent Ban
69
+
70
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
71
+
72
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
73
+
74
+ ## Attribution
75
+
76
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
77
+ available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
78
+
79
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
80
+
81
+ [homepage]: https://www.contributor-covenant.org
82
+
83
+ For answers to common questions about this code of conduct, see the FAQ at
84
+ https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in pastore.gemspec
6
+ gemspec
7
+
8
+ gem 'faker'
9
+ gem 'rake'
10
+ gem 'rspec-rails'
11
+ gem 'shoulda-matchers'
12
+ gem 'pry'
data/Gemfile.lock ADDED
@@ -0,0 +1,188 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pastore (0.0.1)
5
+ rails (>= 4.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actioncable (7.0.4)
11
+ actionpack (= 7.0.4)
12
+ activesupport (= 7.0.4)
13
+ nio4r (~> 2.0)
14
+ websocket-driver (>= 0.6.1)
15
+ actionmailbox (7.0.4)
16
+ actionpack (= 7.0.4)
17
+ activejob (= 7.0.4)
18
+ activerecord (= 7.0.4)
19
+ activestorage (= 7.0.4)
20
+ activesupport (= 7.0.4)
21
+ mail (>= 2.7.1)
22
+ net-imap
23
+ net-pop
24
+ net-smtp
25
+ actionmailer (7.0.4)
26
+ actionpack (= 7.0.4)
27
+ actionview (= 7.0.4)
28
+ activejob (= 7.0.4)
29
+ activesupport (= 7.0.4)
30
+ mail (~> 2.5, >= 2.5.4)
31
+ net-imap
32
+ net-pop
33
+ net-smtp
34
+ rails-dom-testing (~> 2.0)
35
+ actionpack (7.0.4)
36
+ actionview (= 7.0.4)
37
+ activesupport (= 7.0.4)
38
+ rack (~> 2.0, >= 2.2.0)
39
+ rack-test (>= 0.6.3)
40
+ rails-dom-testing (~> 2.0)
41
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
42
+ actiontext (7.0.4)
43
+ actionpack (= 7.0.4)
44
+ activerecord (= 7.0.4)
45
+ activestorage (= 7.0.4)
46
+ activesupport (= 7.0.4)
47
+ globalid (>= 0.6.0)
48
+ nokogiri (>= 1.8.5)
49
+ actionview (7.0.4)
50
+ activesupport (= 7.0.4)
51
+ builder (~> 3.1)
52
+ erubi (~> 1.4)
53
+ rails-dom-testing (~> 2.0)
54
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
55
+ activejob (7.0.4)
56
+ activesupport (= 7.0.4)
57
+ globalid (>= 0.3.6)
58
+ activemodel (7.0.4)
59
+ activesupport (= 7.0.4)
60
+ activerecord (7.0.4)
61
+ activemodel (= 7.0.4)
62
+ activesupport (= 7.0.4)
63
+ activestorage (7.0.4)
64
+ actionpack (= 7.0.4)
65
+ activejob (= 7.0.4)
66
+ activerecord (= 7.0.4)
67
+ activesupport (= 7.0.4)
68
+ marcel (~> 1.0)
69
+ mini_mime (>= 1.1.0)
70
+ activesupport (7.0.4)
71
+ concurrent-ruby (~> 1.0, >= 1.0.2)
72
+ i18n (>= 1.6, < 2)
73
+ minitest (>= 5.1)
74
+ tzinfo (~> 2.0)
75
+ builder (3.2.4)
76
+ coderay (1.1.3)
77
+ concurrent-ruby (1.1.10)
78
+ crass (1.0.6)
79
+ date (3.3.2)
80
+ diff-lcs (1.5.0)
81
+ erubi (1.11.0)
82
+ faker (3.1.0)
83
+ i18n (>= 1.8.11, < 2)
84
+ globalid (1.0.0)
85
+ activesupport (>= 5.0)
86
+ i18n (1.12.0)
87
+ concurrent-ruby (~> 1.0)
88
+ loofah (2.19.1)
89
+ crass (~> 1.0.2)
90
+ nokogiri (>= 1.5.9)
91
+ mail (2.8.0)
92
+ mini_mime (>= 0.1.1)
93
+ net-imap
94
+ net-pop
95
+ net-smtp
96
+ marcel (1.0.2)
97
+ method_source (1.0.0)
98
+ mini_mime (1.1.2)
99
+ mini_portile2 (2.8.0)
100
+ minitest (5.17.0)
101
+ net-imap (0.3.2)
102
+ date
103
+ net-protocol
104
+ net-pop (0.1.2)
105
+ net-protocol
106
+ net-protocol (0.2.1)
107
+ timeout
108
+ net-smtp (0.3.3)
109
+ net-protocol
110
+ nio4r (2.5.8)
111
+ nokogiri (1.13.10)
112
+ mini_portile2 (~> 2.8.0)
113
+ racc (~> 1.4)
114
+ pry (0.14.2)
115
+ coderay (~> 1.1)
116
+ method_source (~> 1.0)
117
+ racc (1.6.1)
118
+ rack (2.2.4)
119
+ rack-test (2.0.2)
120
+ rack (>= 1.3)
121
+ rails (7.0.4)
122
+ actioncable (= 7.0.4)
123
+ actionmailbox (= 7.0.4)
124
+ actionmailer (= 7.0.4)
125
+ actionpack (= 7.0.4)
126
+ actiontext (= 7.0.4)
127
+ actionview (= 7.0.4)
128
+ activejob (= 7.0.4)
129
+ activemodel (= 7.0.4)
130
+ activerecord (= 7.0.4)
131
+ activestorage (= 7.0.4)
132
+ activesupport (= 7.0.4)
133
+ bundler (>= 1.15.0)
134
+ railties (= 7.0.4)
135
+ rails-dom-testing (2.0.3)
136
+ activesupport (>= 4.2.0)
137
+ nokogiri (>= 1.6)
138
+ rails-html-sanitizer (1.4.4)
139
+ loofah (~> 2.19, >= 2.19.1)
140
+ railties (7.0.4)
141
+ actionpack (= 7.0.4)
142
+ activesupport (= 7.0.4)
143
+ method_source
144
+ rake (>= 12.2)
145
+ thor (~> 1.0)
146
+ zeitwerk (~> 2.5)
147
+ rake (13.0.6)
148
+ rspec-core (3.12.0)
149
+ rspec-support (~> 3.12.0)
150
+ rspec-expectations (3.12.2)
151
+ diff-lcs (>= 1.2.0, < 2.0)
152
+ rspec-support (~> 3.12.0)
153
+ rspec-mocks (3.12.3)
154
+ diff-lcs (>= 1.2.0, < 2.0)
155
+ rspec-support (~> 3.12.0)
156
+ rspec-rails (6.0.1)
157
+ actionpack (>= 6.1)
158
+ activesupport (>= 6.1)
159
+ railties (>= 6.1)
160
+ rspec-core (~> 3.11)
161
+ rspec-expectations (~> 3.11)
162
+ rspec-mocks (~> 3.11)
163
+ rspec-support (~> 3.11)
164
+ rspec-support (3.12.0)
165
+ shoulda-matchers (5.3.0)
166
+ activesupport (>= 5.2.0)
167
+ thor (1.2.1)
168
+ timeout (0.3.1)
169
+ tzinfo (2.0.5)
170
+ concurrent-ruby (~> 1.0)
171
+ websocket-driver (0.7.5)
172
+ websocket-extensions (>= 0.1.0)
173
+ websocket-extensions (0.1.5)
174
+ zeitwerk (2.6.6)
175
+
176
+ PLATFORMS
177
+ x86_64-linux
178
+
179
+ DEPENDENCIES
180
+ faker
181
+ pastore!
182
+ pry
183
+ rake
184
+ rspec-rails
185
+ shoulda-matchers
186
+
187
+ BUNDLED WITH
188
+ 2.3.24
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Demetra Opinioni.net Srl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # Pastore
2
+
3
+ Pastore is a powerful gem for Rails that simplifies the process of validating parameters and controlling access to actions in your controllers.
4
+ With Pastore, you can easily define validations for your parameters, ensuring that they meet specific requirements before being passed to your controller actions.
5
+ Additionally, Pastore allows you to easily control access to your actions, ensuring that only authorized users can access sensitive information.
6
+ With its intuitive interface and robust features, Pastore is a must-have tool for any Rails developer looking to improve the security and reliability of their application.
7
+
8
+ ## Installation
9
+
10
+ Install the gem and add to the application's Gemfile by executing:
11
+
12
+ bundle add pastore
13
+
14
+ If bundler is not being used to manage dependencies, install the gem by executing:
15
+
16
+ gem install pastore
17
+
18
+ ## Usage
19
+
20
+ Pastore gem implements 2 main features: `Guards` and `Validators`. Guards are intended to be used for action access control, while Validators are intended to be used for actions params validation.
21
+
22
+ ### Guards usage
23
+
24
+ `Guards` feature allows you to define access control logic for actions in Rails controllers. To use the `Guards` you have to include `Pastore::Guards` into your Rails controller.
25
+
26
+ ##### Setup
27
+
28
+ The best way to start using the `Guards` feature is to add the following code to your `ApplicationController`:
29
+
30
+ ```ruby
31
+ # app/controllers/application_controller.rb
32
+
33
+ class ApplicationController < ActionController::API
34
+ include Pastore::Guards
35
+
36
+ # Specify the logic for current user's role detection, which will be used to check
37
+ # if current user is authorized to access a specific action.
38
+ detect_role do
39
+ current_user&.role
40
+ end
41
+ end
42
+ ```
43
+
44
+ In this way all your controllers will inherit the authorization settings from `ApplicationController`. Then in your controller you can do something like this:
45
+
46
+ ```ruby
47
+ class MyController < ApplicationController
48
+ # By default a :deny strategy is used, so with #permit_role we're going
49
+ # to specify which roles are allowed to access this action.
50
+ permit_role :admin, :user, :pm
51
+ def index
52
+ # ... action code ...
53
+ end
54
+
55
+ # Without a `permit_role` definition the access to this action will be denied to everyone.
56
+ def not_allowed_action
57
+ # ... action code ...
58
+ end
59
+ end
60
+ ```
61
+
62
+ If you want to use `Guards` only in specific controllers, just include `Pastore::Guards` and define `detect_role` in your controller:
63
+
64
+ ```ruby
65
+ class CustomController < ApplicationController
66
+ include Pastore::Guards
67
+
68
+ detect_role do
69
+ current_user&.role
70
+ end
71
+
72
+ permit_role :admin, :supervisor
73
+ def index
74
+ # ... action code ...
75
+ end
76
+ end
77
+ ```
78
+
79
+ #### Custom authorization logic
80
+
81
+ If checking user's role is not enough, you can use the `authorize_with` helper, which will allow you to specify a custom access logic by providing a method name (where custom logic is defined) or a block to use for access verification. As a result your block or method should return `true` if access is granted, or `false` otherwise.
82
+
83
+ ```ruby
84
+ class MyController < ApplicationController
85
+ # You can override the role detection logic inside a controller if it's necessary by
86
+ # using the `detect_role` helper.
87
+ detect_role do
88
+ current_user&.selected_role
89
+ end
90
+
91
+ # If you want to use a custom/dynamic authorization logic, you can
92
+ # specify your own implementation in a method.
93
+ authorize_with :custom_authorization
94
+ def index
95
+ # ... action code ...
96
+ end
97
+
98
+ # You can also specify the authorization logic in a block.
99
+ authorize_with { custom_authorized? }
100
+ def show
101
+ # ... action code ...
102
+ end
103
+
104
+ # Allow only users with `admin` role to access this action.
105
+ permit_role :admin
106
+ def update
107
+ end
108
+
109
+ private
110
+
111
+ # Specify a custom authorization logic (return `true` if successful and `false` when forbidden).
112
+ def custom_authorization
113
+ # ... your custom authorization logic here ...
114
+ end
115
+ end
116
+ ```
117
+
118
+ #### Using `allow` strategy
119
+
120
+ **!!! WARNING !!!** Be careful when using `allow` strategy, because when enabled it grants access to every action in the controller, which could potentially lead to security issues.
121
+
122
+ By default `Pastore::Guards` will use `deny` strategy, which means that the access is denied by default, and the only way to access it is through explicit authorization.
123
+
124
+ Sometimes you might prefer a `allow` strategy instead, in order to allow access to any action within the controller, and manually restrict access to specified actions and roles.
125
+
126
+ For doing so you can use `use_allow_strategy!`, which changes the default strategy. In this case you should use `deny_role` to disable the access for a specific role or overwrite authorization strategy for specific actions with `authorize_with` helper.
127
+
128
+
129
+
130
+ ```ruby
131
+ class MyController < ApplicationController
132
+ # By default allow access to any action within the controller by any role.
133
+ use_allow_strategy!
134
+
135
+ # In this case we're using the :allow strategy, so if we want to exclude a specific role
136
+ # we can do it by using #deny_role method.
137
+ deny_role :user
138
+ def index
139
+ # ... action code ...
140
+ end
141
+
142
+ # Check access by using a custom method
143
+ authorize_with :custom_autorization
144
+ def restricted_access_action
145
+ # ... action code ...
146
+ end
147
+
148
+ # Check access by using a block
149
+ authorize_with { current_user&.role == 'admin' }
150
+ def restricted_access_action2
151
+ # ... action code ...
152
+ end
153
+
154
+ private
155
+
156
+ # Specify a custom authorization logic (return `true` if successful and `false` when forbidden).
157
+ def custom_autorization
158
+ # ... custom authorization logic ...
159
+ end
160
+ end
161
+ ```
162
+
163
+ #### Using `skip_guards`
164
+
165
+ Sometime you may want to disable the `Guards` feature for specific actions. For doing so you can use the `skip_guards` helper, which allows you to specify the list of actions for which guards check have to be disabled. In the example below the access to `index` and `show` actions is granted by `skip_guards` which bypasses the guards check. `skip_guards` have priority over `permit_role`, `deny_role` and `authorize_with`, so using those helpers on actions with disabled guards will have no effect and the access will be granted anyway.
166
+
167
+ ```ruby
168
+ class CustomController < ApplicationController
169
+ use_deny_strategy!
170
+ skip_guards :index, :show
171
+
172
+ def index
173
+ # ... action code ...
174
+ end
175
+
176
+ authorize_with { false } # this will be ignored because of `skip_guards`
177
+ def show
178
+ # ... action code ...
179
+ end
180
+ end
181
+ ```
182
+
183
+ You can also use `skip_guards` helper with `:except` key, which is useful when you need to disable
184
+ guards for all the actions except a few:
185
+
186
+ ```ruby
187
+ class CustomController < ApplicationController
188
+ # disable guards for :action_one and :action_two
189
+ skip_guards except: %i[action_one action_two]
190
+
191
+ # Guards DISABLED
192
+ def index
193
+ # ... action code ...
194
+ end
195
+
196
+ # Guards ENABLED
197
+ def action_one
198
+ # ... action code ...
199
+ end
200
+
201
+ # Guards ENABLED
202
+ def action_two
203
+ # ... action code ...
204
+ end
205
+
206
+ # Guards DISABLED
207
+ def action_three
208
+ # ... action code ...
209
+ end
210
+ end
211
+ ```
212
+
213
+ #### `Pastore::Guards` features
214
+
215
+ Below you can find the list of methods implemented by `Pastore::Guards`, that can be used inside
216
+ your Rails Controller.
217
+
218
+ | Method | Description |
219
+ |--------|-------------|
220
+ | `use_deny_strategy!` | Set to `deny` the default authorization strategy, which meands that by default the access to the actions will be denied |
221
+ | `use_allow_strategy!` | Set to `allow` the default authorization strategy, which automatically authorizes the access to all the actions. **!!! WARNING !!!** Be careful when using `allow` strategy, because that way any user can access any action of your controller, including guest users if not filtered before. |
222
+ | `detect_role(&block)` | Allows to specify the logic for user role detection. This block will be automatically called to get current user's role information. |
223
+ | `permit_role(*roles)` | Specifies the roles that are allowed to access the action that follows. |
224
+ | `deny_role(*roles)` | Specifies the roles that are not allowed to access the action that follows. |
225
+ | `authorize_with(Symbol|&block)` | Allows to specify a custom authorization logic to use for action access check. Accepts a method name or a block. |
226
+ | `skip_guards(*Symbol|*String, except: *Symbol|*String)` | Allows to disable guards for specific actions. Accepts a list of actions for which to disable guards (e.g. `skip_guards :index, 'show'`), but can be also used to disable guards for all the actions except specified (e.g. `skip_guards except: :index`). |
227
+
228
+ ## Contributing
229
+
230
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/demetra-it/pastore>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/demetra-it/pastore/blob/master/CODE_OF_CONDUCT.md).
231
+
232
+ ## License
233
+
234
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
235
+
236
+ ## Code of Conduct
237
+
238
+ Everyone interacting in the Pastore project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/pastore/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Pastore
6
+ # Implements the features for Rails controller access guards.
7
+ module Guards # rubocop:disable Metrics/ModuleLength
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ before_action :pastore_check_access
12
+ end
13
+
14
+ class_methods do # rubocop:disable Metrics/BlockLength
15
+ attr_accessor :_role_detector, :_default_strategy, :_action_permitted_roles, :_controller_allowed_roles,
16
+ :_forbidden_callback, :_action_authorization_lambda, :_controller_authorization_lambdas,
17
+ :_action_denied_roles, :_controller_denied_roles, :_actions_with_skipped_guards,
18
+ :_actions_with_active_guards
19
+
20
+ # Sets the logic to use for current role detection.
21
+ def detect_role(&block)
22
+ self._role_detector = block
23
+ end
24
+
25
+ # Specifies a custom callback to be called when access is forbidden.
26
+ def forbidden(&block)
27
+ self._forbidden_callback = block
28
+ end
29
+
30
+ # Sets the default strategy to "deny".
31
+ def use_deny_strategy!
32
+ self._default_strategy = :deny
33
+ end
34
+
35
+ # Sets the default strategy to "allow".
36
+ def use_allow_strategy!
37
+ self._default_strategy = :allow
38
+ end
39
+
40
+ # Returns the default strategy.
41
+ def pastore_default_strategy
42
+ _default_strategy || :deny
43
+ end
44
+
45
+ def skip_guards(*actions, except: [])
46
+ self._actions_with_active_guards = [except].flatten.compact.map(&:to_sym)
47
+ self._actions_with_skipped_guards = actions.flatten.compact.map(&:to_sym)
48
+ end
49
+
50
+ def actions_with_active_guards
51
+ _actions_with_active_guards || []
52
+ end
53
+
54
+ def actions_with_skipped_guards
55
+ _actions_with_skipped_guards || []
56
+ end
57
+
58
+ # Specify the list of roles allowed to access the action.
59
+ def permit_role(*roles)
60
+ self._action_permitted_roles = [roles].flatten.compact.uniq.map(&:to_s)
61
+ end
62
+
63
+ # Specify the list of roles denied to access the action.
64
+ def deny_role(*roles)
65
+ self._action_denied_roles = [roles].flatten.compact.uniq.map(&:to_s)
66
+ end
67
+
68
+ # Specify a custom lambda to be called to authorize the action.
69
+ def authorize_with(method_name = nil, &block)
70
+ custom_lambda = method_name.to_sym if method_name.is_a?(Symbol) || method_name.is_a?(String)
71
+ custom_lambda = block if block_given?
72
+
73
+ if custom_lambda.present?
74
+ self._action_authorization_lambda = custom_lambda
75
+ else
76
+ raise ArgumentError, 'A block or a method name must be provided'
77
+ end
78
+ end
79
+
80
+ # Save the configurations of the action when the action is defined.
81
+ def method_added(name, *args) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
82
+ unless _action_permitted_roles.blank?
83
+ self._controller_allowed_roles ||= {}
84
+ self._controller_allowed_roles[name] = _action_permitted_roles
85
+ self._action_permitted_roles = nil
86
+ end
87
+
88
+ unless _action_denied_roles.blank?
89
+ self._controller_denied_roles ||= {}
90
+ self._controller_denied_roles[name] = _action_denied_roles
91
+ self._action_denied_roles = nil
92
+ end
93
+
94
+ unless _action_authorization_lambda.blank?
95
+ self._controller_authorization_lambdas ||= {}
96
+ self._controller_authorization_lambdas[name] = _action_authorization_lambda
97
+ self._action_authorization_lambda = nil
98
+ end
99
+
100
+ super
101
+ end
102
+ end
103
+
104
+ protected
105
+
106
+ # Returns the current role detected by the role detector logic.
107
+ def pastore_current_role
108
+ self.class._role_detector&.call&.to_s
109
+ end
110
+
111
+ # Returns the list of roles allowed to access current action.
112
+ def pastore_allowed_roles
113
+ self.class._controller_allowed_roles&.dig(action_name.to_sym) || []
114
+ end
115
+
116
+ # Returns the list of roles denied to access current action.
117
+ def pastore_denied_roles
118
+ self.class._controller_denied_roles&.dig(action_name.to_sym) || []
119
+ end
120
+
121
+ # Returns the custom lambda to be called to authorize the action.
122
+ def pastore_authorization_lambda
123
+ self.class._controller_authorization_lambdas&.dig(action_name.to_sym)
124
+ end
125
+
126
+ def skip_pastore_guards?
127
+ active_guards = self.class._actions_with_active_guards
128
+
129
+ # If current action is listed in `:except` field of `skip_guards`, then we have to run guards (return false).
130
+ return false if active_guards&.include?(action_name.to_sym)
131
+
132
+ # If `skip_guards` has specified an `:except` field, then we can skip guards, because current action has
133
+ # implicitely been marked as "to skip guards".
134
+ return true if active_guards.present?
135
+
136
+ # If `skip_guards` don't have the any `except` field, just check if current actions is listed in
137
+ # `skip_guards`.
138
+ return true if self.class._actions_with_skipped_guards&.include?(action_name.to_sym)
139
+
140
+ # Current action isn't listed in `skip_guards`, so we have to run guards (return false).
141
+ false
142
+ end
143
+
144
+ # Performs the access check for current action.
145
+ def pastore_check_access # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
146
+ return if skip_pastore_guards?
147
+
148
+ if pastore_authorization_lambda.present?
149
+ authorized = instance_eval(&pastore_authorization_lambda) if pastore_authorization_lambda.is_a?(Proc)
150
+ authorized = send(pastore_authorization_lambda) if pastore_authorization_lambda.is_a?(Symbol)
151
+
152
+ return if authorized
153
+
154
+ return pastore_deny_access!
155
+ end
156
+
157
+ case self.class.pastore_default_strategy
158
+ when :deny then check_access_with_deny_strategy
159
+ when :allow then check_access_with_allow_strategy
160
+ end
161
+ end
162
+
163
+ def check_access_with_deny_strategy
164
+ return pastore_deny_access! unless pastore_allowed_roles.include?(pastore_current_role)
165
+ end
166
+
167
+ def check_access_with_allow_strategy
168
+ return pastore_deny_access! if pastore_denied_roles.include?(pastore_current_role)
169
+ end
170
+
171
+ def pastore_deny_access!
172
+ callback = self.class._forbidden_callback
173
+
174
+ if callback
175
+ instance_eval(&callback)
176
+ response.status = :forbidden
177
+ else
178
+ render json: { message: 'Forbidden' }, status: :forbidden
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pastore
4
+ # Implements the features for Rails controller params validation.
5
+ module ParamsValidators
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pastore
4
+ VERSION = '0.0.1'
5
+ end
data/lib/pastore.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'pastore/version'
4
+ require_relative 'pastore/guards'
5
+ require_relative 'pastore/params_validators'
6
+
7
+ module Pastore
8
+ class Error < StandardError; end
9
+ # Your code goes here...
10
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pastore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Groza Sergiu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-01-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ description: |
28
+ Pastore is a powerful gem for Rails that simplifies the process of
29
+ validating parameters and controlling access to actions in your controllers.
30
+ With Pastore, you can easily define validations for your parameters,
31
+ ensuring that they meet specific requirements before being passed to your controller actions.
32
+ Additionally, Pastore allows you to easily control access to your actions,
33
+ ensuring that only authorized users can access sensitive information.
34
+ With its intuitive interface and robust features,
35
+ Pastore is a must-have tool for any Rails developer looking to improve
36
+ the security and reliability of their application.
37
+ email:
38
+ - developers@opinioni.net
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - ".rspec"
44
+ - ".rubocop.yml"
45
+ - CHANGELOG.md
46
+ - CODE_OF_CONDUCT.md
47
+ - Gemfile
48
+ - Gemfile.lock
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - lib/pastore.rb
53
+ - lib/pastore/guards.rb
54
+ - lib/pastore/params_validators.rb
55
+ - lib/pastore/version.rb
56
+ homepage: https://github.com/demetra-it/pastore
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/demetra-it/pastore
61
+ source_code_uri: https://github.com/demetra-it/pastore
62
+ changelog_uri: https://github.com/demetra-it/pastore/blob/master/CHANGELOG.md
63
+ rubygems_mfa_required: 'true'
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.6.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.3.7
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: A powerful gem for Rails that simplifies the process of validating parameters
83
+ and controlling access to actions in your controllers.
84
+ test_files: []