minfraud 1.4.1 → 1.5.0

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: aa255a8f579aa729b4ceeb84db99f283bafdc2276fc6eba3d52e6133a8e2d4ea
4
- data.tar.gz: 1d9717004f0f07eadf3d986f4f697f4d2c41ef7c08c21b9b1f3b7e6291c36286
3
+ metadata.gz: af8e0a313e978adbd8ccfdf6fccad4652ad0b5c4df5f7812da097f2be4d5390e
4
+ data.tar.gz: 8d766ee43c166bc26a8c8643cded1d7a43a27cf6cc531e9fddaf66028ab0ebde
5
5
  SHA512:
6
- metadata.gz: a57eac0733d6c1d64319c80f458f00585897030433414ab0b4888606fedafac833e5fd1298fe608f8a343b87536ad2974bc794bba9317a5043980aa689c2e0cd
7
- data.tar.gz: 0ef9a279e2ed6d9a08b3f972338f7ade34ecf1f2c409e6777333c9a6afcf1dbab3c03927b8e6a350c54ed4dd2c86bdd64672a36f51caa2087bfb8e53ab824b2a
6
+ metadata.gz: 497a1c19029b36879b1b2f1b42f7037cfa205b24b199d71c84564a1cf26136de41f6b7fc8fdb9c9ffa163d3f82b8283d159f017d887aaa9709dfd059f1333625
7
+ data.tar.gz: 72f3fd755450dd1f68b3f675fc181e3a326574bcde905ee7e1b3e64951c2c009788124b2e063e99ed6d080430d7f3d093bf64b8f8dfb78c452436de3937e5cbd
@@ -7,6 +7,6 @@ jobs:
7
7
  - uses: actions/checkout@v2
8
8
  - uses: ruby/setup-ruby@v1
9
9
  with:
10
- ruby-version: 2.7
10
+ ruby-version: '3.0'
11
11
  - run: bundle install
12
12
  - run: bundle exec rake -t rubocop
@@ -16,6 +16,7 @@ jobs:
16
16
  2.5,
17
17
  2.6,
18
18
  2.7,
19
+ '3.0',
19
20
  jruby,
20
21
  ]
21
22
  exclude:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Minfraud Changelog
2
2
 
3
+ ## v1.5.0 (2021-02-02)
4
+
5
+ * Add the `hash_address` attribute to `Minfraud::Components::Email`. If
6
+ this is `true`, the MD5 hash of the `address` will be sent instead of the
7
+ plain text `address`. Use this if you prefer to send the hash of the
8
+ `address` rather than the plain text. Note that this normalizes the
9
+ `address`, so we recommend using it as opposed to hashing the `address`
10
+ manually.
11
+ * The email `domain` input is now automatically set if the email `address`
12
+ input is set but the `domain` is not.
13
+ * Adds new payment processors `:apple_pay` and `:aps_payments` to
14
+ `Minfraud::Components::Payment`.
15
+ * Added support for the IP address risk reasons in the minFraud Insights
16
+ and Factors responses. This is available at `.ip_address.risk_reasons`.
17
+ It is an array of `IPRiskReason` objects.
18
+
3
19
  ## v1.4.1 (2020-12-01)
4
20
 
5
21
  * Do not throw an exception if the response does not include IP address
data/README.dev.md CHANGED
@@ -1,4 +1,4 @@
1
1
  # How to release
2
2
 
3
3
  See
4
- [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/master/README.dev.md).
4
+ [here](https://github.com/maxmind/MaxMind-DB-Reader-ruby/blob/main/README.dev.md).
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'digest/md5'
4
+ require 'simpleidn'
5
+
3
6
  module Minfraud
4
7
  module Components
5
8
  # Email corresponds to the email object of a minFraud request.
@@ -11,7 +14,8 @@ module Minfraud
11
14
  # This field must be either be a valid email address or an MD5 of the
12
15
  # lowercased email used in the transaction. Important: if using the MD5
13
16
  # hash, please be sure to convert the email address to lowercase before
14
- # calculating its MD5 hash.
17
+ # calculating its MD5 hash. Instead of converting an address to an MD5
18
+ # hash yourself, please use the hash_address attribute in this class.
15
19
  #
16
20
  # @return [String, nil]
17
21
  attr_accessor :address
@@ -21,15 +25,46 @@ module Minfraud
21
25
  # @return [String, nil]
22
26
  attr_accessor :domain
23
27
 
28
+ # By default, the address will be sent in plain text. If this is set
29
+ # true, the address will instead be sent as an MD5 hash.
30
+ #
31
+ # @return [Boolean, nil]
32
+ attr_accessor :hash_address
33
+
24
34
  # @param params [Hash] Hash of parameters. Each key/value should
25
35
  # correspond to one of the available attributes.
26
36
  def initialize(params = {})
27
- @address = params[:address]
28
- @domain = params[:domain]
37
+ @address = params[:address]
38
+ @domain = params[:domain]
39
+ @hash_address = params[:hash_address]
29
40
 
30
41
  validate
31
42
  end
32
43
 
44
+ # A JSON representation of Minfraud::Components::Email.
45
+ #
46
+ # @return [Hash]
47
+ def to_json(*_args)
48
+ json = super
49
+
50
+ if json['address'] && !json['domain']
51
+ _, domain = address.split('@', 2)
52
+ if domain
53
+ domain = clean_domain(domain)
54
+ json['domain'] = domain if domain
55
+ end
56
+ end
57
+
58
+ if json.delete('hash_address') && json['address']
59
+ hash = hash_email_address(json['address'])
60
+
61
+ # We could consider clearing the key if !hash.
62
+ json['address'] = hash if hash
63
+ end
64
+
65
+ json
66
+ end
67
+
33
68
  private
34
69
 
35
70
  def validate
@@ -38,6 +73,60 @@ module Minfraud
38
73
  validate_email('email', @address)
39
74
  validate_string('domain', 255, @domain)
40
75
  end
76
+
77
+ def hash_email_address(address)
78
+ address = clean_email_address(address)
79
+ return nil if !address
80
+
81
+ Digest::MD5.hexdigest(address)
82
+ end
83
+
84
+ def clean_email_address(address)
85
+ address = address.strip
86
+ address.downcase!
87
+
88
+ local_part, domain = address.split('@', 2)
89
+ return nil if !local_part || !domain
90
+
91
+ domain = clean_domain(domain)
92
+
93
+ if domain == 'yahoo.com'
94
+ local_part.sub!(/\A([^-]+)-.*\z/, '\1')
95
+ else
96
+ local_part.sub!(/\A([^+]+)\+.*\z/, '\1')
97
+ end
98
+
99
+ "#{local_part}@#{domain}"
100
+ end
101
+
102
+ TYPO_DOMAINS = {
103
+ # gmail.com
104
+ '35gmai.com' => 'gmail.com',
105
+ '636gmail.com' => 'gmail.com',
106
+ 'gamil.com' => 'gmail.com',
107
+ 'gmail.comu' => 'gmail.com',
108
+ 'gmial.com' => 'gmail.com',
109
+ 'gmil.com' => 'gmail.com',
110
+ 'yahoogmail.com' => 'gmail.com',
111
+ # outlook.com
112
+ 'putlook.com' => 'outlook.com',
113
+ }.freeze
114
+ private_constant :TYPO_DOMAINS
115
+
116
+ def clean_domain(domain)
117
+ domain = domain.strip
118
+
119
+ # We could use delete_suffix!, but that is in Ruby 2.5+ only.
120
+ domain.sub!(/\.\z/, '')
121
+
122
+ domain = SimpleIDN.to_ascii(domain)
123
+
124
+ if TYPO_DOMAINS.key?(domain)
125
+ domain = TYPO_DOMAINS[domain]
126
+ end
127
+
128
+ domain
129
+ end
41
130
  end
42
131
  end
43
132
  end
@@ -22,6 +22,8 @@ module Minfraud
22
22
  :altapay,
23
23
  :amazon_payments,
24
24
  :american_express_payment_gateway,
25
+ :apple_pay,
26
+ :aps_payments,
25
27
  :authorizenet,
26
28
  :balanced,
27
29
  :beanstream,
@@ -13,7 +13,7 @@ module Minfraud
13
13
  attr_accessor :items
14
14
 
15
15
  # @param params [Array] Array of shopping cart items. You may provide
16
- # each item as either as Hash where each key is a symbol corresponding
16
+ # each item as either a Hash where each key is a symbol corresponding
17
17
  # to an item's field, or as a Minfraud:::Components::ShoppingCartItem
18
18
  # object.
19
19
  def initialize(params = [])
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'maxmind/geoip2/model/insights'
4
4
  require 'minfraud/model/geoip2_location'
5
+ require 'minfraud/model/ip_risk_reason'
5
6
 
6
7
  module Minfraud
7
8
  module Model
@@ -13,6 +14,13 @@ module Minfraud
13
14
  # @return [Float]
14
15
  attr_reader :risk
15
16
 
17
+ # This field contains IPRiskReason objects identifying the reasons why
18
+ # the IP address received the associated risk. This will be an empty
19
+ # array if there are no reasons.
20
+ #
21
+ # @return [Array<Minfraud::Model::IPRiskReason>]
22
+ attr_reader :risk_reasons
23
+
16
24
  # @!visibility private
17
25
  def initialize(record, locales)
18
26
  if record
@@ -32,6 +40,13 @@ module Minfraud
32
40
  @risk = nil
33
41
  end
34
42
 
43
+ @risk_reasons = []
44
+ if record && record.key?('risk_reasons')
45
+ record['risk_reasons'].each do |r|
46
+ @risk_reasons << Minfraud::Model::IPRiskReason.new(r)
47
+ end
48
+ end
49
+
35
50
  # Decorate objects with deprecated attributes and names for backwards
36
51
  # compatibility. Do this here rather than with the overhead of
37
52
  # subclasses/modules for them in the hope that one day we can delete
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minfraud/model/abstract'
4
+
5
+ module Minfraud
6
+ module Model
7
+ # Reason for the IP risk.
8
+ #
9
+ # This class provides both a machine-readable code and a human-readable
10
+ # explanation of the reason for the IP risk score.
11
+ #
12
+ # Although more codes may be added in the future, the current codes are:
13
+ #
14
+ # * ANONYMOUS_IP - The IP address belongs to an anonymous network. See the
15
+ # object at ip_address.traits for more details.
16
+ # * BILLING_POSTAL_VELOCITY - Many different billing postal codes have been
17
+ # seen on this IP address.
18
+ # * EMAIL_VELOCITY - Many different email addresses have been seen on this
19
+ # IP address.
20
+ # * HIGH_RISK_DEVICE - A high risk device was seen on this IP address.
21
+ # * HIGH_RISK_EMAIL - A high risk email address was seen on this IP address
22
+ # in your past transactions.
23
+ # * ISSUER_ID_NUMBER_VELOCITY - Many different issuer ID numbers have been
24
+ # seen on this IP address.
25
+ # * MINFRAUD_NETWORK_ACTIVITY - Suspicious activity has been seen on this
26
+ # IP address across minFraud customers.
27
+ class IPRiskReason < Abstract
28
+ # This value is a machine-readable code identifying the reason.
29
+ #
30
+ # @return [String, nil]
31
+ attr_reader :code
32
+
33
+ # This field provides a human-readable explanation of the reason. The
34
+ # text may change at any time and should not be matched against.
35
+ #
36
+ # @return [String, nil]
37
+ attr_reader :reason
38
+
39
+ # @!visibility private
40
+ def initialize(record)
41
+ super(record)
42
+
43
+ @code = get('code')
44
+ @reason = get('reason')
45
+ end
46
+ end
47
+ end
48
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Minfraud
4
4
  # The Gem version.
5
- VERSION = '1.4.1'
5
+ VERSION = '1.5.0'
6
6
  end
data/minfraud.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency 'faraday', '>= 0.9.1', '< 2.0'
26
26
  spec.add_runtime_dependency 'faraday_middleware', '>= 0.9.1', '< 2.0'
27
27
  spec.add_runtime_dependency 'net-http-persistent', '>= 2.0.0', '< 5.0'
28
+ spec.add_runtime_dependency 'simpleidn', '>= 0.1.1'
28
29
 
29
30
  spec.add_development_dependency 'bundler', '>= 1.16'
30
31
  spec.add_development_dependency 'rake'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minfraud
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kushnir.yb
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-01 00:00:00.000000000 Z
11
+ date: 2021-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -70,6 +70,20 @@ dependencies:
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
72
  version: '5.0'
73
+ - !ruby/object:Gem::Dependency
74
+ name: simpleidn
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 0.1.1
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 0.1.1
73
87
  - !ruby/object:Gem::Dependency
74
88
  name: bundler
75
89
  requirement: !ruby/object:Gem::Requirement
@@ -211,6 +225,7 @@ files:
211
225
  - lib/minfraud/model/geoip2_location.rb
212
226
  - lib/minfraud/model/insights.rb
213
227
  - lib/minfraud/model/ip_address.rb
228
+ - lib/minfraud/model/ip_risk_reason.rb
214
229
  - lib/minfraud/model/issuer.rb
215
230
  - lib/minfraud/model/score.rb
216
231
  - lib/minfraud/model/score_ip_address.rb