rubocop-github 0.12.0 → 0.16.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.
@@ -0,0 +1,4 @@
1
+ inherit_from: _default_shared.yml
2
+
3
+ require:
4
+ - rubocop-performance
data/config/rails.yml CHANGED
@@ -1,118 +1,2 @@
1
- Rails:
2
- Enabled: true
3
-
4
- Rails/FindEach:
5
- Enabled: false
6
-
7
- Rails/OutputSafety:
8
- Enabled: true
9
-
10
- Rails/PluralizationGrammar:
11
- Enabled: true
12
-
13
- Rails/RequestReferer:
14
- Enabled: true
15
- EnforcedStyle: referrer
16
-
17
- Rails/ScopeArgs:
18
- Enabled: true
19
-
20
- Rails/UniqBeforePluck:
21
- Enabled: true
22
-
23
- GitHub/RailsApplicationRecord:
24
- Enabled: true
25
-
26
- GitHub/RailsControllerRenderActionSymbol:
27
- Enabled: true
28
- Include:
29
- - 'app/controllers/**/*.rb'
30
-
31
- GitHub/RailsControllerRenderLiteral:
32
- Enabled: true
33
- StyleGuide: https://github.com/github/rubocop-github/blob/master/guides/rails-render-literal.md
34
- Include:
35
- - 'app/controllers/**/*.rb'
36
-
37
- GitHub/RailsControllerRenderPathsExist:
38
- Enabled: true
39
- ViewPath:
40
- - 'app/views'
41
- Include:
42
- - 'app/controllers/**/*.rb'
43
-
44
- GitHub/RailsControllerRenderShorthand:
45
- Enabled: true
46
- StyleGuide: https://github.com/github/rubocop-github/blob/master/guides/rails-controller-render-shorthand.md
47
- Include:
48
- - 'app/controllers/**/*.rb'
49
-
50
- GitHub/RailsRenderInline:
51
- Enabled: true
52
- StyleGuide: https://github.com/github/rubocop-github/blob/master/guides/rails-controller-render-inline.md
53
- Include:
54
- - 'app/controllers/**/*.rb'
55
- - 'app/helpers/**/*.rb'
56
- - 'app/view_models/**/*.rb'
57
- - 'app/views/**/*.erb'
58
-
59
- GitHub/RailsRenderObjectCollection:
60
- Enabled: false
61
-
62
- GitHub/RailsViewRenderLiteral:
63
- Enabled: true
64
- StyleGuide: https://github.com/github/rubocop-github/blob/master/guides/rails-render-literal.md
65
- Include:
66
- - 'app/helpers/**/*.rb'
67
- - 'app/view_models/**/*.rb'
68
- - 'app/views/**/*.erb'
69
-
70
- GitHub/RailsViewRenderPathsExist:
71
- Enabled: true
72
- ViewPath:
73
- - 'app/views'
74
- Include:
75
- - 'app/helpers/**/*.rb'
76
- - 'app/view_models/**/*.rb'
77
- - 'app/views/**/*.erb'
78
-
79
- GitHub/RailsViewRenderShorthand:
80
- Enabled: true
81
- Include:
82
- - 'app/helpers/**/*.rb'
83
- - 'app/view_models/**/*.rb'
84
- - 'app/views/**/*.erb'
85
-
86
- # Exclude Rails ERB files from incompatible cops
87
-
88
- Layout/BlockAlignment:
89
- Exclude:
90
- - 'app/views/**/*.erb'
91
-
92
- Style/For:
93
- Exclude:
94
- - 'app/views/**/*.erb'
95
-
96
- Style/OneLineConditional:
97
- Exclude:
98
- - 'app/views/**/*.erb'
99
-
100
- Style/Semicolon:
101
- Exclude:
102
- - 'app/views/**/*.erb'
103
-
104
- Layout/SpaceInsideParens:
105
- Exclude:
106
- - 'app/views/**/*.erb'
107
-
108
- Style/StringLiterals:
109
- Exclude:
110
- - 'app/views/**/*.erb'
111
-
112
- Layout/TrailingBlankLines:
113
- Exclude:
114
- - 'app/views/**/*.erb'
115
-
116
- Layout/TrailingWhitespace:
117
- Exclude:
118
- - 'app/views/**/*.erb'
1
+ # Inherit from rails_deprecated until 1.0
2
+ inherit_from: rails_deprecated.yml
@@ -0,0 +1,7 @@
1
+ inherit_from: _rails_shared.yml
2
+
3
+ Rails:
4
+ Enabled: true
5
+
6
+ Rails/FindEach:
7
+ Enabled: false
@@ -0,0 +1,4 @@
1
+ inherit_from: _rails_shared.yml
2
+
3
+ require:
4
+ - rubocop-rails
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rubocop/cop/github/insecure_hash_algorithm"
3
4
  require "rubocop/cop/github/rails_application_record"
4
5
  require "rubocop/cop/github/rails_controller_render_action_symbol"
5
6
  require "rubocop/cop/github/rails_controller_render_literal"
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module GitHub
8
+ class InsecureHashAlgorithm < Cop
9
+ MSG = "This hash function is not allowed"
10
+ UUID_V3_MSG = "uuid_v3 uses MD5, which is not allowed"
11
+ UUID_V5_MSG = "uuid_v5 uses SHA1, which is not allowed"
12
+
13
+ # Matches constants like these:
14
+ # Digest::MD5
15
+ # OpenSSL::Digest::MD5
16
+ def_node_matcher :insecure_const?, <<-PATTERN
17
+ (const (const _ :Digest) #insecure_algorithm?)
18
+ PATTERN
19
+
20
+ # Matches calls like these:
21
+ # Digest.new('md5')
22
+ # Digest.hexdigest('md5', 'str')
23
+ # OpenSSL::Digest.new('md5')
24
+ # OpenSSL::Digest.hexdigest('md5', 'str')
25
+ # OpenSSL::Digest::Digest.new('md5')
26
+ # OpenSSL::Digest::Digest.hexdigest('md5', 'str')
27
+ # OpenSSL::Digest::Digest.new(:MD5)
28
+ # OpenSSL::Digest::Digest.hexdigest(:MD5, 'str')
29
+ def_node_matcher :insecure_digest?, <<-PATTERN
30
+ (send
31
+ (const _ {:Digest :HMAC})
32
+ #not_just_encoding?
33
+ #insecure_algorithm?
34
+ ...)
35
+ PATTERN
36
+
37
+ # Matches calls like "Digest(:MD5)".
38
+ def_node_matcher :insecure_hash_lookup?, <<-PATTERN
39
+ (send _ :Digest #insecure_algorithm?)
40
+ PATTERN
41
+
42
+ # Matches calls like "OpenSSL::HMAC.new(secret, hash)"
43
+ def_node_matcher :openssl_hmac_new?, <<-PATTERN
44
+ (send (const (const _ :OpenSSL) :HMAC) :new ...)
45
+ PATTERN
46
+
47
+ # Matches calls like "OpenSSL::HMAC.new(secret, 'sha1')"
48
+ def_node_matcher :openssl_hmac_new_insecure?, <<-PATTERN
49
+ (send (const (const _ :OpenSSL) :HMAC) :new _ #insecure_algorithm?)
50
+ PATTERN
51
+
52
+ # Matches Rails's Digest::UUID.
53
+ def_node_matcher :digest_uuid?, <<-PATTERN
54
+ (const (const _ :Digest) :UUID)
55
+ PATTERN
56
+
57
+ def_node_matcher :uuid_v3?, <<-PATTERN
58
+ (send (const _ :UUID) :uuid_v3 ...)
59
+ PATTERN
60
+
61
+ def_node_matcher :uuid_v5?, <<-PATTERN
62
+ (send (const _ :UUID) :uuid_v5 ...)
63
+ PATTERN
64
+
65
+ def insecure_algorithm?(val)
66
+ return false if val == :Digest # Don't match "Digest::Digest".
67
+ case alg_name(val)
68
+ when *allowed_hash_functions
69
+ false
70
+ when Symbol
71
+ # can't figure this one out, it's nil or a var or const.
72
+ false
73
+ else
74
+ true
75
+ end
76
+ end
77
+
78
+ def not_just_encoding?(val)
79
+ !just_encoding?(val)
80
+ end
81
+
82
+ def just_encoding?(val)
83
+ val == :hexencode || val == :bubblebabble
84
+ end
85
+
86
+ # Built-in hash functions are listed in these docs:
87
+ # https://ruby-doc.org/stdlib-2.7.0/libdoc/digest/rdoc/Digest.html
88
+ # https://ruby-doc.org/stdlib-2.7.0/libdoc/openssl/rdoc/OpenSSL/Digest.html
89
+ DEFAULT_ALLOWED = %w[
90
+ SHA256
91
+ SHA384
92
+ SHA512
93
+ ].freeze
94
+
95
+ def allowed_hash_functions
96
+ @allowed_algorithms ||= cop_config.fetch("Allowed", DEFAULT_ALLOWED).map(&:downcase)
97
+ end
98
+
99
+ def alg_name(val)
100
+ return :nil if val.nil?
101
+ return val.to_s.downcase unless val.is_a?(RuboCop::AST::Node)
102
+ case val.type
103
+ when :sym, :str
104
+ val.children.first.to_s.downcase
105
+ else
106
+ val.type
107
+ end
108
+ end
109
+
110
+ def on_const(const_node)
111
+ if insecure_const?(const_node) && !digest_uuid?(const_node)
112
+ add_offense(const_node, message: MSG)
113
+ end
114
+ end
115
+
116
+ def on_send(send_node)
117
+ case
118
+ when uuid_v3?(send_node)
119
+ unless allowed_hash_functions.include?("md5")
120
+ add_offense(send_node, message: UUID_V3_MSG)
121
+ end
122
+ when uuid_v5?(send_node)
123
+ unless allowed_hash_functions.include?("sha1")
124
+ add_offense(send_node, message: UUID_V5_MSG)
125
+ end
126
+ when openssl_hmac_new?(send_node)
127
+ if openssl_hmac_new_insecure?(send_node)
128
+ add_offense(send_node, message: MSG)
129
+ end
130
+ when insecure_digest?(send_node)
131
+ add_offense(send_node, message: MSG)
132
+ when insecure_hash_lookup?(send_node)
133
+ add_offense(send_node, message: MSG)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -9,11 +9,11 @@ module RuboCop
9
9
  MSG = "Prefer `render` with string instead of symbol"
10
10
 
11
11
  def_node_matcher :render_sym?, <<-PATTERN
12
- (send nil? :render $(sym _))
12
+ (send nil? {:render :render_to_string} $(sym _))
13
13
  PATTERN
14
14
 
15
15
  def_node_matcher :render_with_options?, <<-PATTERN
16
- (send nil? :render (hash $...))
16
+ (send nil? {:render :render_to_string} (hash $...))
17
17
  PATTERN
18
18
 
19
19
  def_node_matcher :action_key?, <<-PATTERN
@@ -1,28 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rubocop"
4
+ require "rubocop/cop/github/render_literal_helpers"
4
5
 
5
6
  module RuboCop
6
7
  module Cop
7
8
  module GitHub
8
9
  class RailsControllerRenderLiteral < Cop
9
- MSG = "render must be used with a string literal"
10
+ include RenderLiteralHelpers
10
11
 
11
- def_node_matcher :literal?, <<-PATTERN
12
- ({str sym true false nil?} ...)
13
- PATTERN
14
-
15
- def_node_matcher :render?, <<-PATTERN
16
- (send nil? :render ...)
17
- PATTERN
18
-
19
- def_node_matcher :render_literal?, <<-PATTERN
20
- (send nil? :render ({str sym} $_) $...)
21
- PATTERN
22
-
23
- def_node_matcher :render_with_options?, <<-PATTERN
24
- (send nil? :render (hash $...))
25
- PATTERN
12
+ MSG = "render must be used with a string literal or an instance of a Class"
26
13
 
27
14
  def_node_matcher :ignore_key?, <<-PATTERN
28
15
  (pair (sym {
@@ -60,9 +47,15 @@ module RuboCop
60
47
  }) ...)
61
48
  PATTERN
62
49
 
50
+ def_node_matcher :render_const?, <<-PATTERN
51
+ (send nil? {:render :render_to_string} (const _ _) ...)
52
+ PATTERN
53
+
63
54
  def on_send(node)
64
55
  return unless render?(node)
65
56
 
57
+ return if render_view_component?(node) || render_const?(node)
58
+
66
59
  if render_literal?(node)
67
60
  elsif option_pairs = render_with_options?(node)
68
61
  option_pairs = option_pairs.reject { |pair| options_key?(pair) }
@@ -74,18 +67,40 @@ module RuboCop
74
67
  if template_node = option_pairs.map { |pair| template_key?(pair) }.compact.first
75
68
  if !literal?(template_node)
76
69
  add_offense(node, location: :expression)
70
+ return
77
71
  end
78
72
  else
79
73
  add_offense(node, location: :expression)
74
+ return
80
75
  end
81
76
 
82
77
  if layout_node = option_pairs.map { |pair| layout_key?(pair) }.compact.first
83
78
  if !literal?(layout_node)
84
79
  add_offense(node, location: :expression)
80
+ return
85
81
  end
86
82
  end
87
83
  else
88
84
  add_offense(node, location: :expression)
85
+ return
86
+ end
87
+
88
+ if render_literal?(node)
89
+ option_hash = node.arguments[1]
90
+ if option_hash && !option_hash.hash_type?
91
+ add_offense(node, location: :expression)
92
+ return
93
+ end
94
+ option_pairs = option_hash && option_hash.pairs
95
+ else
96
+ option_pairs = node.arguments[0].pairs
97
+ end
98
+
99
+ if option_pairs
100
+ locals = option_pairs.map { |pair| locals_key?(pair) }.compact.first
101
+ if locals && (!locals.hash_type? || !hash_with_literal_keys?(locals))
102
+ add_offense(node, location: :expression)
103
+ end
89
104
  end
90
105
  end
91
106
  end
@@ -7,15 +7,15 @@ module RuboCop
7
7
  module GitHub
8
8
  class RailsControllerRenderPathsExist < Cop
9
9
  def_node_matcher :render?, <<-PATTERN
10
- (send nil? :render $...)
10
+ (send nil? {:render :render_to_string} $...)
11
11
  PATTERN
12
12
 
13
13
  def_node_matcher :render_str?, <<-PATTERN
14
- (send nil? :render $({str sym} $_) ...)
14
+ (send nil? {:render :render_to_string} $({str sym} $_) ...)
15
15
  PATTERN
16
16
 
17
17
  def_node_matcher :render_options?, <<-PATTERN
18
- (send nil? :render (hash $...))
18
+ (send nil? {:render :render_to_string} (hash $...))
19
19
  PATTERN
20
20
 
21
21
  def_node_matcher :render_key?, <<-PATTERN
@@ -9,7 +9,7 @@ module RuboCop
9
9
  MSG = "Prefer `render` template shorthand"
10
10
 
11
11
  def_node_matcher :render_with_options?, <<-PATTERN
12
- (send nil? :render (hash $...))
12
+ (send nil? {:render :render_to_string} (hash $...))
13
13
  PATTERN
14
14
 
15
15
  def_node_matcher :action_key?, <<-PATTERN
@@ -9,7 +9,7 @@ module RuboCop
9
9
  MSG = "Avoid `render inline:`"
10
10
 
11
11
  def_node_matcher :render_with_options?, <<-PATTERN
12
- (send nil? :render (hash $...))
12
+ (send nil? {:render :render_to_string} (hash $...))
13
13
  PATTERN
14
14
 
15
15
  def_node_matcher :inline_key?, <<-PATTERN
@@ -9,7 +9,7 @@ module RuboCop
9
9
  MSG = "Avoid `render object:`"
10
10
 
11
11
  def_node_matcher :render_with_options?, <<-PATTERN
12
- (send nil? :render (hash $...) ...)
12
+ (send nil? {:render :render_to_string} (hash $...) ...)
13
13
  PATTERN
14
14
 
15
15
  def_node_matcher :partial_key?, <<-PATTERN
@@ -1,28 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rubocop"
4
+ require "rubocop/cop/github/render_literal_helpers"
4
5
 
5
6
  module RuboCop
6
7
  module Cop
7
8
  module GitHub
8
9
  class RailsViewRenderLiteral < Cop
9
- MSG = "render must be used with a string literal"
10
+ include RenderLiteralHelpers
10
11
 
11
- def_node_matcher :literal?, <<-PATTERN
12
- ({str sym true false nil?} ...)
13
- PATTERN
14
-
15
- def_node_matcher :render?, <<-PATTERN
16
- (send nil? :render $...)
17
- PATTERN
18
-
19
- def_node_matcher :render_literal?, <<-PATTERN
20
- (send nil? :render ({str sym} $_) $...)
21
- PATTERN
22
-
23
- def_node_matcher :render_with_options?, <<-PATTERN
24
- (send nil? :render (hash $...) ...)
25
- PATTERN
12
+ MSG = "render must be used with a literal template and use literals for locals keys"
26
13
 
27
14
  def_node_matcher :ignore_key?, <<-PATTERN
28
15
  (pair (sym {
@@ -33,6 +20,7 @@ module RuboCop
33
20
  def_node_matcher :partial_key?, <<-PATTERN
34
21
  (pair (sym {
35
22
  :file
23
+ :template
36
24
  :layout
37
25
  :partial
38
26
  }) $_)
@@ -41,6 +29,9 @@ module RuboCop
41
29
  def on_send(node)
42
30
  return unless render?(node)
43
31
 
32
+ # Ignore "component"-style renders
33
+ return if render_view_component?(node)
34
+
44
35
  if render_literal?(node)
45
36
  elsif option_pairs = render_with_options?(node)
46
37
  if option_pairs.any? { |pair| ignore_key?(pair) }
@@ -50,12 +41,31 @@ module RuboCop
50
41
  if partial_node = option_pairs.map { |pair| partial_key?(pair) }.compact.first
51
42
  if !literal?(partial_node)
52
43
  add_offense(node, location: :expression)
44
+ return
53
45
  end
54
46
  else
55
47
  add_offense(node, location: :expression)
48
+ return
56
49
  end
57
50
  else
58
51
  add_offense(node, location: :expression)
52
+ return
53
+ end
54
+
55
+ if render_literal?(node) && node.arguments.count > 1
56
+ locals = node.arguments[1]
57
+ elsif options_pairs = render_with_options?(node)
58
+ locals = option_pairs.map { |pair| locals_key?(pair) }.compact.first
59
+ end
60
+
61
+ if locals
62
+ if locals.hash_type?
63
+ if !hash_with_literal_keys?(locals)
64
+ add_offense(node, location: :expression)
65
+ end
66
+ else
67
+ add_offense(node, location: :expression)
68
+ end
59
69
  end
60
70
  end
61
71
  end