mini_defender 0.4.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56cc42b9b0ce4c44e30dc4bcd8dfcc31bcccc012388f52a076320ee926feec11
4
- data.tar.gz: 7e5aaf99490b42b14956fda14843065d3cd906b6568da7ff4df90059f965b75b
3
+ metadata.gz: ce828ce2c5bbb54c61b4251dbb22c7a2c47c454d8e2c40200e87def85331960b
4
+ data.tar.gz: 5e68bda0f0104af4d084458191a59626e29323b07cb738959784d723e44e670a
5
5
  SHA512:
6
- metadata.gz: f3a25a2655ed8889345d101bca863cd72a605825ae2dd99a0b6527f73c33572cf5771e8aba28fdb81b1311ac3cc22845a868c5edeb3ddcb1f9ee2572e5e91010
7
- data.tar.gz: 9ee05f959b9289c6ea0d9b1f88278bc9617df76cef267a362163fef02f6056dc8443ee3700c86308b54e6608edfd3c34ad7cfabd01d6b01e86d37772d028abe5
6
+ metadata.gz: 3e77385c0db7fb62dd8b4cce604919fd9d0d0ae5e0fad90edf4d891f63d256cb99a9a07321114688168a2e899c7dc177d9f92e61f6b3eaa063217d2a079d73a7
7
+ data.tar.gz: efc638b587907dd095dc31ad90a87396e778f1eb147f48010664b6a39f11117286f1f2d342cd62900c851eddb081c39ecadbac1faada9ec0cf6541227091820d
data/Gemfile CHANGED
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in mini_defender.gemspec
6
5
  gemspec
7
6
 
8
- gem "rake", "~> 13.0"
9
-
10
- gem "minitest", "~> 5.0"
7
+ gem 'rake', '~> 13.0'
8
+ gem 'minitest', '~> 5.0'
@@ -4,10 +4,21 @@ class Hash
4
4
  def expand
5
5
  expanded = {}
6
6
 
7
- reject{ |_, v| v.is_a?(Hash) || v.is_a?(Array) }.each do |k, v|
7
+ each do |k, v|
8
8
  keys = k.split('.')
9
9
  node = expanded
10
- node = (node[keys.shift] ||= {}) while keys.length > 1
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
+
11
22
  node[keys.shift] = v
12
23
  end
13
24
 
@@ -61,6 +61,12 @@ class MiniDefender::Rule
61
61
  value
62
62
  end
63
63
 
64
+ # This method is used to change the value
65
+ # regardless if coercion is required
66
+ def force_coerce?
67
+ false
68
+ end
69
+
64
70
  # @param [Object] attribute
65
71
  # @param [Object] value
66
72
  # @param [MiniDefender::Validator] validator
@@ -5,6 +5,22 @@ class MiniDefender::Rules::Array < MiniDefender::Rule
5
5
  'array'
6
6
  end
7
7
 
8
+ def initialize(data_mode = 'none')
9
+ @data_mode = data_mode
10
+ end
11
+
12
+ def self.make(args)
13
+ new(args[0] || 'none')
14
+ end
15
+
16
+ def coerce(value)
17
+ @data_mode == 'all' ? value : []
18
+ end
19
+
20
+ def force_coerce?
21
+ true
22
+ end
23
+
8
24
  def passes?(attribute, value, validator)
9
25
  value.is_a?(Array)
10
26
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'countries'
3
+ require 'money'
4
4
 
5
5
  class MiniDefender::Rules::Currency < MiniDefender::Rule
6
6
  CURRENCIES = Money::Currency.map(&:iso_code).map(&:upcase).uniq
@@ -5,11 +5,60 @@ class MiniDefender::Rules::Hash < MiniDefender::Rule
5
5
  'hash'
6
6
  end
7
7
 
8
+ def initialize(data_mode = 'none', key_type = 'any', value_type = 'any')
9
+ @data_mode = data_mode
10
+ @key_type = key_type
11
+ @value_type = value_type
12
+ end
13
+
14
+ def self.make(args)
15
+ new(
16
+ args[0] || 'none',
17
+ args[1] || 'any',
18
+ args[2] || 'any',
19
+ )
20
+ end
21
+
22
+ def coerce(value)
23
+ @data_mode == 'all' ? value : {}
24
+ end
25
+
26
+ def force_coerce?
27
+ true
28
+ end
29
+
8
30
  def passes?(attribute, value, validator)
9
- value.is_a?(Hash)
31
+ passes = value.is_a?(Hash)
32
+
33
+ if @key_type == 'string'
34
+ passes &= value.all? { |k, _| k.is_a?(String) }
35
+ end
36
+
37
+ case @value_type
38
+ when 'string'
39
+ passes &= value.all? { |_, v| v.is_a?(String) }
40
+ when 'integer'
41
+ passes &= value.all? { |_, v| v.is_a?(Integer) }
42
+ when 'float'
43
+ passes &= value.all? { |_, v| v.is_a?(Float) }
44
+ else
45
+ # None
46
+ end
47
+
48
+ passes
10
49
  end
11
50
 
12
51
  def message(attribute, value, validator)
13
- "The field must be an object."
52
+ additional = ''
53
+
54
+ if @key_type != 'any'
55
+ additional += ", key must be #{@key_type}"
56
+ end
57
+
58
+ if @value_type != 'any'
59
+ additional += ", value must be #{@value_type}"
60
+ end
61
+
62
+ "The field must be an object#{additional}."
14
63
  end
15
64
  end
@@ -6,14 +6,23 @@ module MiniDefender
6
6
  # @param [Hash] flat_data
7
7
  # @return [Hash]
8
8
  def expand(rules, flat_data)
9
- rules
10
- .map { |k, v| [Regexp.compile('\A' + k.gsub(/\*/, '\d+') + '\Z'), v] }.to_h
11
- .map { |p, set|
12
- data_rules = flat_data.filter { |k, _| p.match? k }.map { |k, _| [k, set] }
13
- data_rules.length > 0 ? data_rules : [[p.source.gsub(/\\[AZ]/, '').gsub('\d+', '0'), set]]
14
- }
15
- .flatten(1)
16
- .to_h
9
+ result = {}
10
+
11
+ rules.each do |rule_key, rule_set|
12
+ unless rule_key.include?('*')
13
+ result[rule_key] = rule_set
14
+ next
15
+ end
16
+
17
+ k_pattern = Regexp.compile('\A' + rule_key.gsub(/\*/, '\d+') + '\Z')
18
+
19
+ flat_data.each do |value_key, _|
20
+ next unless k_pattern.match?(value_key)
21
+ result[value_key] = rule_set
22
+ end
23
+ end
24
+
25
+ result
17
26
  end
18
27
  end
19
28
  end
@@ -23,6 +23,7 @@ module MiniDefender
23
23
  [k, @factory.init_set(set)]
24
24
  end
25
25
 
26
+ # Set default values for missing data key compared to rules
26
27
  data_rules.each do |k, set|
27
28
  if !@data.key?(k) || @data[k].blank?
28
29
  set.filter{ |r| r.defaults?(self) }.each do |r|
@@ -51,18 +52,25 @@ module MiniDefender
51
52
  end
52
53
 
53
54
  value = coerced = @data[k]
55
+ force_coerce = false
56
+
54
57
  rule_set.each do |rule|
55
58
  next unless rule.active?(self)
56
59
 
57
60
  value_included &= !rule.excluded?(self)
58
61
 
59
- if rule.passes?(k, coerced, self)
62
+ if rule.passes?(k, value, self)
60
63
  coerced = rule.coerce(coerced)
64
+ force_coerce = rule.force_coerce?
61
65
  else
62
66
  @errors[k] << rule.error_message(k, value, self)
63
67
  end
64
68
  end
65
69
 
70
+ if force_coerce
71
+ value = coerced
72
+ end
73
+
66
74
  if @errors[k].empty? && value_included
67
75
  @validated[k] = value
68
76
  @coerced[k] = coerced
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniDefender
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -14,8 +14,6 @@ Gem::Specification.new do |spec|
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.6.0"
16
16
 
17
- # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
18
-
19
17
  spec.metadata["homepage_uri"] = spec.homepage
20
18
  spec.metadata["source_code_uri"] = spec.homepage
21
19
 
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.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ali Alhoshaiyan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-16 00:00:00.000000000 Z
11
+ date: 2024-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport