mini_defender 0.5.0 → 0.5.2

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: ce828ce2c5bbb54c61b4251dbb22c7a2c47c454d8e2c40200e87def85331960b
4
- data.tar.gz: 5e68bda0f0104af4d084458191a59626e29323b07cb738959784d723e44e670a
3
+ metadata.gz: f7eb4878351ebf49bb42e33a10f8fefd34745b4067bdf40b50180792d2883819
4
+ data.tar.gz: 93ec54964db744a7f2f03a7fc23bf96b6458637d94dbfb00c4307a0e5e598964
5
5
  SHA512:
6
- metadata.gz: 3e77385c0db7fb62dd8b4cce604919fd9d0d0ae5e0fad90edf4d891f63d256cb99a9a07321114688168a2e899c7dc177d9f92e61f6b3eaa063217d2a079d73a7
7
- data.tar.gz: efc638b587907dd095dc31ad90a87396e778f1eb147f48010664b6a39f11117286f1f2d342cd62900c851eddb081c39ecadbac1faada9ec0cf6541227091820d
6
+ metadata.gz: a04dc7d2a819a0d3f8e443342900bd29db0c7e9b730128ff7d8f266f7853e52079166903997f660ef87c26c3965dd689c229bd5e533a0ff824debd3548f65417
7
+ data.tar.gz: cd0109845a3f6f2ddc22c23448856124384554b6e3bbc75f1d952773c589797a421c1f7e04da15ed3461713f65ee436a8c102776ff0377dbbdeecc96da746196
@@ -16,6 +16,13 @@ class MiniDefender::Rule
16
16
  true
17
17
  end
18
18
 
19
+ # Priority is used to sort rules in a rule set to allow rules to validate data
20
+ # before rules that will radically change data
21
+ # @return [Integer]
22
+ def priority
23
+ 100
24
+ end
25
+
19
26
  # @param [MiniDefender::Validator] validator
20
27
  # @return [Boolean]
21
28
  def implicit?(validator)
@@ -13,6 +13,10 @@ class MiniDefender::Rules::Array < MiniDefender::Rule
13
13
  new(args[0] || 'none')
14
14
  end
15
15
 
16
+ def priority
17
+ 500
18
+ end
19
+
16
20
  def coerce(value)
17
21
  @data_mode == 'all' ? value : []
18
22
  end
@@ -19,6 +19,10 @@ class MiniDefender::Rules::Hash < MiniDefender::Rule
19
19
  )
20
20
  end
21
21
 
22
+ def priority
23
+ 500
24
+ end
25
+
22
26
  def coerce(value)
23
27
  @data_mode == 'all' ? value : {}
24
28
  end
@@ -15,14 +15,27 @@ module MiniDefender
15
15
  end
16
16
 
17
17
  k_pattern = Regexp.compile('\A' + rule_key.gsub(/\*/, '\d+') + '\Z')
18
+ k_pattern_result = {}
18
19
 
19
20
  flat_data.each do |value_key, _|
20
21
  next unless k_pattern.match?(value_key)
21
- result[value_key] = rule_set
22
+ k_pattern_result[value_key] = rule_set
22
23
  end
24
+
25
+ if k_pattern_result.empty?
26
+ k_pattern_result[k_pattern.source.gsub(/\\[AZ]/, '').gsub('\d+', '0')] = rule_set
27
+ end
28
+
29
+ result.merge!(k_pattern_result)
23
30
  end
24
31
 
25
32
  result
26
33
  end
34
+
35
+ def array_patterns(rules)
36
+ rules
37
+ .filter { |key, _| key.include?('*') }
38
+ .map { |key, _| Regexp.compile('\A' + key.gsub(/\*/, '\d+') + '\Z') }
39
+ end
27
40
  end
28
41
  end
@@ -11,16 +11,23 @@ module MiniDefender
11
11
  end
12
12
 
13
13
  def init_set(rule_set)
14
- rule_set = rule_set.split('|') if rule_set.is_a?(String)
15
- raise ArgumentError, 'Rule set must be a string or an array' unless rule_set.is_a?(Array)
14
+ if rule_set.is_a?(String)
15
+ rule_set = rule_set.split('|')
16
+ end
17
+
18
+ unless rule_set.is_a?(Array)
19
+ raise ArgumentError, 'Rule set must be a string or an array'
20
+ end
16
21
 
17
- rule_set.map do |rule|
22
+ rule_set = rule_set.map do |rule|
18
23
  unless rule.is_a?(String) || rule.is_a?(Rule)
19
24
  raise ArgumentError, 'Rule must be a string or an instance of MiniDefender::Rule'
20
25
  end
21
26
 
22
27
  rule.is_a?(String) ? init_rule(rule) : rule
23
28
  end
29
+
30
+ rule_set.sort_by! { |r| r.priority }
24
31
  end
25
32
 
26
33
  def init_rule(signature)
@@ -12,10 +12,13 @@ module MiniDefender
12
12
  @coerced = {}
13
13
  @expander = RulesExpander.new
14
14
  @factory = RulesFactory.new
15
+ @array_patterns = @expander.array_patterns(rules)
15
16
  end
16
17
 
17
18
  def validate
18
- return unless @errors.nil?
19
+ unless @errors.nil?
20
+ return
21
+ end
19
22
 
20
23
  @errors = {}
21
24
 
@@ -59,7 +62,7 @@ module MiniDefender
59
62
 
60
63
  value_included &= !rule.excluded?(self)
61
64
 
62
- if rule.passes?(k, value, self)
65
+ if rule.passes?(k, coerced, self)
63
66
  coerced = rule.coerce(coerced)
64
67
  force_coerce = rule.force_coerce?
65
68
  else
@@ -77,15 +80,15 @@ module MiniDefender
77
80
  end
78
81
  end
79
82
 
80
- @validated = @validated.expand
81
- @coerced = @coerced.expand
82
-
83
83
  @errors.reject! { |_, v| v.empty? }
84
84
  end
85
85
 
86
86
  def validate!
87
87
  validate if @errors.nil?
88
- raise ValidationError.new('Data validation failed', @errors) unless @errors.empty?
88
+
89
+ unless @errors.empty?
90
+ raise ValidationError.new('Data validation failed', @errors)
91
+ end
89
92
  end
90
93
 
91
94
  def passes?
@@ -99,12 +102,12 @@ module MiniDefender
99
102
 
100
103
  def validated
101
104
  validate! if @errors.nil?
102
- @validated
105
+ @validated_compacted ||= compact_expanded(@validated)
103
106
  end
104
107
 
105
108
  def coerced
106
109
  validate! if @errors.nil?
107
- @coerced
110
+ @coerced_compacted = compact_expanded(@coerced)
108
111
  end
109
112
 
110
113
  # @return [Hash]
@@ -133,5 +136,57 @@ module MiniDefender
133
136
 
134
137
  Regexp.compile("\\A#{search_key.reverse.join('\.')}\\z")
135
138
  end
139
+
140
+ def compact_expanded(hash)
141
+ expanded = {}
142
+
143
+ hash.each do |k, v|
144
+ keys = k.split('.')
145
+ node = expanded
146
+
147
+ while keys.length > 1
148
+ next_key = keys.shift
149
+ next_node = (node[next_key] ||= {})
150
+
151
+ if next_node.is_a?(Array)
152
+ node[next_key] = next_node = next_node.each_with_index.to_h do |value, index|
153
+ [index.to_s, value]
154
+ end
155
+ end
156
+
157
+ node = next_node
158
+ end
159
+
160
+ node[keys.shift] = v
161
+ end
162
+
163
+ compact_keys(expanded)
164
+ end
165
+
166
+ def compact_keys(hash, current_key = '')
167
+ current_key_suffixed = if current_key == ''
168
+ ''
169
+ else
170
+ "#{current_key}."
171
+ end
172
+
173
+ result = hash.to_h do |k, v|
174
+ [k, v.is_a?(Hash) ? compact_keys(v, current_key_suffixed + k) : v]
175
+ end
176
+
177
+ if result.empty?
178
+ return result
179
+ end
180
+
181
+ unless @array_patterns.any? { |p| p.match?("#{current_key_suffixed}#{result.keys.first}") }
182
+ return result
183
+ end
184
+
185
+ if result.all? { |k, _v| k.match?(/\A\d+\z/) }
186
+ return result.values
187
+ end
188
+
189
+ result
190
+ end
136
191
  end
137
192
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniDefender
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.2"
5
5
  end
data/lib/mini_defender.rb CHANGED
@@ -13,7 +13,6 @@ require_relative 'mini_defender/validation_helpers'
13
13
 
14
14
  # Extensions to Ruby Core
15
15
  require_relative 'mini_defender/extensions/enumerable'
16
- require_relative 'mini_defender/extensions/hash'
17
16
 
18
17
  module MiniDefender
19
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_defender
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ali Alhoshaiyan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-16 00:00:00.000000000 Z
11
+ date: 2024-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -97,7 +97,6 @@ files:
97
97
  - Rakefile
98
98
  - lib/mini_defender.rb
99
99
  - lib/mini_defender/extensions/enumerable.rb
100
- - lib/mini_defender/extensions/hash.rb
101
100
  - lib/mini_defender/handles_validation_errors.rb
102
101
  - lib/mini_defender/rule.rb
103
102
  - lib/mini_defender/rules.rb
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Hash
4
- def expand
5
- expanded = {}
6
-
7
- each do |k, v|
8
- keys = k.split('.')
9
- node = expanded
10
-
11
- while keys.length > 1
12
- next_key = keys.shift
13
- next_node = (node[next_key] ||= {})
14
-
15
- if next_node.is_a?(Array)
16
- node[next_key] = next_node = next_node.each_with_index.to_h { |value, index| [index.to_s, value] }
17
- end
18
-
19
- node = next_node
20
- end
21
-
22
- node[keys.shift] = v
23
- end
24
-
25
- expanded.compact_keys
26
- end
27
-
28
- def compact_keys
29
- result = to_h do |k, v|
30
- [k, v.is_a?(Hash) ? v.compact_keys : v]
31
- end
32
-
33
- if !result.empty? && result.all? { |k, _v| k.match?(/\A\d+\z/) }
34
- result.values
35
- else
36
- result
37
- end
38
- end
39
- end