betterlint 1.0.0 → 1.1.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/README.md +41 -0
- data/config/default.yml +26 -0
- data/lib/rubocop/cop/betterment/active_job_performable.rb +1 -1
- data/lib/rubocop/cop/betterment/dynamic_params.rb +1 -1
- data/lib/rubocop/cop/betterment/implicit_redirect_type.rb +2 -2
- data/lib/rubocop/cop/betterment/memoization_with_arguments.rb +3 -3
- data/lib/rubocop/cop/betterment/non_standard_actions.rb +74 -0
- data/lib/rubocop/cop/betterment.rb +1 -0
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 530a4f9e133d2b476275f42d7f58050eab86379908d1d7b1ebc0ac56c7c680f5
|
4
|
+
data.tar.gz: 497ef95c882dae58db33bf6b7d02c28a63909968f6a751a0ed9a29c97d12aa83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 150b06a5b965394c1c7f00b95c7f3d1bb78e58855d300fb3041f90ad828fc023ca6e0cca02faad01274d58b3d5263bbf05acf337691ce5b89e98482596f30241
|
7
|
+
data.tar.gz: 2524c76c7a7ea7101f3987f79e31270fe0e51091aabf1f8bc229b9854285757e01b4c335e09be348a5f850f7b2f5b1fe16f18d4ff0d72eda94496cc1a54a0b46
|
data/README.md
CHANGED
@@ -156,3 +156,44 @@ Betterment/UnsafeJob:
|
|
156
156
|
```
|
157
157
|
|
158
158
|
It may make sense to consult your application's values for `Rails.application.config.filter_parameters`; if the application is filtering specific parameters from being logged, it might be a good idea to prevent these values from being stored in plaintext in a database as well.
|
159
|
+
|
160
|
+
### Betterment/NonStandardActions
|
161
|
+
|
162
|
+
This cop looks at Rails route files and flags routes that go to non-standard controller actions.
|
163
|
+
The 7 standard controller actions (index, show, new, edit, create, update, destroy) are well defined,
|
164
|
+
which allow for policies and middleware that can be applied to any controller.
|
165
|
+
For example, if we want a user role to only be able to view but not modify,
|
166
|
+
we can blanket deny access to create, update, and destroy actions and have it work in most use cases.
|
167
|
+
|
168
|
+
Custom actions require explicit configuration to work with these sorts of middleware,
|
169
|
+
so we prefer to use new controllers instead. For example, a resourceful route with a custom action like this:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
Rails.application.routes.draw do
|
173
|
+
resources :alerts, only: [:index, :summary]
|
174
|
+
end
|
175
|
+
```
|
176
|
+
|
177
|
+
This can instead by written with an additional controller:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
Rails.application.routes.draw do
|
181
|
+
resources :alerts, only: :index # AlertsController#index
|
182
|
+
namespace :alerts do
|
183
|
+
resource :summary, only: :show #Alerts::SummariesController#show
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
By default this will look only in `config/routes.rb` and will use the standard 7 actions.
|
189
|
+
These values can be configured:
|
190
|
+
|
191
|
+
```yaml
|
192
|
+
Betterment/NonStandardActions:
|
193
|
+
AdditionalAllowedActions:
|
194
|
+
- update_all
|
195
|
+
- destroy_all
|
196
|
+
Include:
|
197
|
+
- 'config/routes.rb'
|
198
|
+
- 'config/other_routes.rb'
|
199
|
+
```
|
data/config/default.yml
CHANGED
@@ -20,6 +20,9 @@ AllCops:
|
|
20
20
|
DisplayStyleGuide: true
|
21
21
|
DisplayCopNames: true
|
22
22
|
|
23
|
+
Betterment:
|
24
|
+
StyleGuideBaseURL: https://github.com/Betterment/betterlint
|
25
|
+
|
23
26
|
Betterment/ServerErrorAssertion:
|
24
27
|
Description: 'Detects assertions on 5XX HTTP statuses.'
|
25
28
|
Include:
|
@@ -27,20 +30,43 @@ Betterment/ServerErrorAssertion:
|
|
27
30
|
|
28
31
|
Betterment/AuthorizationInController:
|
29
32
|
Description: 'Detects unsafe handling of id-like parameters in controllers.'
|
33
|
+
StyleGuide: '#bettermentauthorizationincontroller'
|
30
34
|
Enabled: false
|
31
35
|
|
32
36
|
Betterment/UnsafeJob:
|
33
37
|
Enabled: false
|
38
|
+
StyleGuide: '#bettermentunsafejob'
|
34
39
|
sensitive_params:
|
35
40
|
- password
|
36
41
|
- social_security_number
|
37
42
|
- ssn
|
38
43
|
|
44
|
+
Betterment/UnscopedFind:
|
45
|
+
StyleGuide: '#bettermentunscopedfind'
|
46
|
+
|
47
|
+
Betterment/DynamicParams:
|
48
|
+
StyleGuide: '#bettermentdynamicparams'
|
49
|
+
|
39
50
|
Betterment/SitePrismLoaded:
|
40
51
|
Include:
|
41
52
|
- 'spec/features/**/*_spec.rb'
|
42
53
|
- 'spec/system/**/*_spec.rb'
|
43
54
|
|
55
|
+
Betterment/NonStandardActions:
|
56
|
+
Description: 'Detects non-standard controller actions.'
|
57
|
+
StyleGuide: '#bettermentnonstandardactions'
|
58
|
+
AdditionalAllowedActions: []
|
59
|
+
StandardActions:
|
60
|
+
- index
|
61
|
+
- show
|
62
|
+
- new
|
63
|
+
- edit
|
64
|
+
- create
|
65
|
+
- update
|
66
|
+
- destroy
|
67
|
+
Include:
|
68
|
+
- 'config/routes.rb'
|
69
|
+
|
44
70
|
Layout/ParameterAlignment:
|
45
71
|
Enabled: false
|
46
72
|
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
return unless arg_nodes
|
28
28
|
|
29
29
|
arg_nodes.find do |arg|
|
30
|
-
arg.array_type? && find_dynamic_param(arg.values) || !arg.literal? && !arg.const_type?
|
30
|
+
(arg.array_type? && find_dynamic_param(arg.values)) || (!arg.literal? && !arg.const_type?)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
def on_block(node)
|
47
47
|
return unless routes_file?
|
48
48
|
|
49
|
-
if block_form_with_options(node) { |options| options.none?
|
49
|
+
if block_form_with_options(node) { |options| options.none? { |n| valid_status_option?(n) } } || block_form_without_options?(node)
|
50
50
|
add_offense(node)
|
51
51
|
end
|
52
52
|
end
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
54
54
|
def on_send(node)
|
55
55
|
return unless routes_file?
|
56
56
|
|
57
|
-
if arg_form_with_options(node) { |options| options.none?
|
57
|
+
if arg_form_with_options(node) { |options| options.none? { |n| valid_status_option?(n) } } || arg_form_without_options?(node)
|
58
58
|
add_offense(node)
|
59
59
|
end
|
60
60
|
end
|
@@ -3,8 +3,8 @@ module RuboCop
|
|
3
3
|
module Betterment
|
4
4
|
class MemoizationWithArguments < Cop
|
5
5
|
MSG = 'Memoized method `%<method>s` accepts arguments, ' \
|
6
|
-
|
7
|
-
|
6
|
+
'which may cause it to return a stale result. ' \
|
7
|
+
'Remove memoization or refactor to remove arguments.'.freeze
|
8
8
|
|
9
9
|
def self.node_pattern
|
10
10
|
memo_assign = '(or_asgn $(ivasgn _) _)'
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
def on_def(node)
|
23
23
|
(method_name, ivar_assign) = memoized?(node)
|
24
|
-
return if ivar_assign.nil? || node.arguments.length.zero?
|
24
|
+
return if ivar_assign.nil? || node.arguments.length.zero? || method_name == :initialize
|
25
25
|
|
26
26
|
msg = format(MSG, method: method_name)
|
27
27
|
add_offense(node, location: ivar_assign.source_range, message: msg)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module RuboCop
|
2
|
+
module Cop
|
3
|
+
module Betterment
|
4
|
+
class NonStandardActions < Cop
|
5
|
+
MSG_GENERAL = 'Use a new controller instead of custom actions.'.freeze
|
6
|
+
MSG_RESOURCE_ONLY = "Resource route refers to a non-standard action in it's 'only:' param. #{MSG_GENERAL}".freeze
|
7
|
+
MSG_ROUTE_TO = "Route goes to a non-standard controller action. #{MSG_GENERAL}".freeze
|
8
|
+
|
9
|
+
# @!method routes?(node)
|
10
|
+
def_node_matcher :routes?, <<-PATTERN
|
11
|
+
(block (send (send (send (const nil? :Rails) :application) :routes) :draw) ...)
|
12
|
+
PATTERN
|
13
|
+
|
14
|
+
# @!method resource_with_only(node)
|
15
|
+
def_node_matcher :resource_with_only, <<-PATTERN
|
16
|
+
(send nil? {:resource :resources} _ (hash <(pair (sym :only) {(array (sym $_)*) (sym $_*)} ) ...> ))
|
17
|
+
PATTERN
|
18
|
+
|
19
|
+
def not_to_or_action?(sym)
|
20
|
+
!%i(to action).include?(sym)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @!method route_to(node)
|
24
|
+
def_node_matcher :route_to, <<~PATTERN
|
25
|
+
(send nil? {:match :get :post :put :patch :delete} ({str sym} $_) (hash {
|
26
|
+
<(pair (sym ${:to :action}) ({str sym} $_)) ...>
|
27
|
+
(pair (sym $#not_to_or_action?) $_)*
|
28
|
+
})?)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_block(node)
|
32
|
+
if routes?(node)
|
33
|
+
node.each_descendant(:send) do |descendant_node|
|
34
|
+
check_resource_with_only(descendant_node) || check_raw_route(descendant_node)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def check_resource_with_only(node)
|
42
|
+
resource_only = resource_with_only(node)
|
43
|
+
if resource_only && resource_only.any? { |action| !allowed_action?(action) }
|
44
|
+
add_offense(node, message: MSG_RESOURCE_ONLY)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_raw_route(node)
|
50
|
+
route = route_to(node)
|
51
|
+
if route
|
52
|
+
(path, param, value) = route
|
53
|
+
action = case param
|
54
|
+
when :to then value.first.split('#').last
|
55
|
+
when :action then value.first
|
56
|
+
else path
|
57
|
+
end
|
58
|
+
add_offense(node, message: MSG_ROUTE_TO) unless allowed_action?(action)
|
59
|
+
true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# NOTE: The InternalAffairs/UndefinedConfig rule seems to have a bug where it can't fine these configs in config/default.yml
|
64
|
+
def allowed_actions
|
65
|
+
@allowed_actions ||= cop_config['StandardActions'] + cop_config['AdditionalAllowedActions'] # rubocop:disable InternalAffairs/UndefinedConfig
|
66
|
+
end
|
67
|
+
|
68
|
+
def allowed_action?(action)
|
69
|
+
allowed_actions.include?(action.to_s)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -7,6 +7,7 @@ require 'rubocop/cop/betterment/unscoped_find'
|
|
7
7
|
require 'rubocop/cop/betterment/unsafe_job'
|
8
8
|
require 'rubocop/cop/betterment/timeout'
|
9
9
|
require 'rubocop/cop/betterment/memoization_with_arguments'
|
10
|
+
require 'rubocop/cop/betterment/non_standard_actions'
|
10
11
|
require 'rubocop/cop/betterment/site_prism_loaded'
|
11
12
|
require 'rubocop/cop/betterment/spec_helper_required_outside_spec_dir'
|
12
13
|
require 'rubocop/cop/betterment/implicit_redirect_type'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: betterlint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Development
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -98,16 +98,16 @@ dependencies:
|
|
98
98
|
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 12.3.3
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 12.3.3
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rspec-rails
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,6 +139,7 @@ files:
|
|
139
139
|
- lib/rubocop/cop/betterment/dynamic_params.rb
|
140
140
|
- lib/rubocop/cop/betterment/implicit_redirect_type.rb
|
141
141
|
- lib/rubocop/cop/betterment/memoization_with_arguments.rb
|
142
|
+
- lib/rubocop/cop/betterment/non_standard_actions.rb
|
142
143
|
- lib/rubocop/cop/betterment/server_error_assertion.rb
|
143
144
|
- lib/rubocop/cop/betterment/site_prism_loaded.rb
|
144
145
|
- lib/rubocop/cop/betterment/spec_helper_required_outside_spec_dir.rb
|
@@ -150,7 +151,8 @@ files:
|
|
150
151
|
homepage:
|
151
152
|
licenses:
|
152
153
|
- MIT
|
153
|
-
metadata:
|
154
|
+
metadata:
|
155
|
+
rubygems_mfa_required: 'true'
|
154
156
|
post_install_message:
|
155
157
|
rdoc_options: []
|
156
158
|
require_paths:
|
@@ -159,14 +161,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
159
161
|
requirements:
|
160
162
|
- - ">="
|
161
163
|
- !ruby/object:Gem::Version
|
162
|
-
version: '2.
|
164
|
+
version: '2.6'
|
163
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
166
|
requirements:
|
165
167
|
- - ">="
|
166
168
|
- !ruby/object:Gem::Version
|
167
169
|
version: '0'
|
168
170
|
requirements: []
|
169
|
-
rubygems_version: 3.
|
171
|
+
rubygems_version: 3.3.7
|
170
172
|
signing_key:
|
171
173
|
specification_version: 4
|
172
174
|
summary: Betterment rubocop configuration
|