minfraud 1.1.0 → 1.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop.yml +12 -0
  3. data/.github/workflows/test.yml +33 -0
  4. data/.rubocop.yml +108 -0
  5. data/CHANGELOG.md +57 -0
  6. data/Gemfile +4 -2
  7. data/README.dev.md +1 -1
  8. data/README.md +170 -55
  9. data/Rakefile +9 -3
  10. data/bin/console +4 -3
  11. data/lib/maxmind/geoip2/model/city.rb +3 -3
  12. data/lib/maxmind/geoip2/model/country.rb +5 -5
  13. data/lib/maxmind/geoip2/record/traits.rb +13 -4
  14. data/lib/minfraud.rb +44 -6
  15. data/lib/minfraud/assessments.rb +113 -53
  16. data/lib/minfraud/components/account.rb +31 -9
  17. data/lib/minfraud/components/addressable.rb +73 -26
  18. data/lib/minfraud/components/base.rb +26 -14
  19. data/lib/minfraud/components/billing.rb +5 -0
  20. data/lib/minfraud/components/credit_card.rb +64 -20
  21. data/lib/minfraud/components/custom_inputs.rb +14 -3
  22. data/lib/minfraud/components/device.rb +45 -15
  23. data/lib/minfraud/components/email.rb +120 -9
  24. data/lib/minfraud/components/event.rb +60 -24
  25. data/lib/minfraud/components/order.rb +59 -22
  26. data/lib/minfraud/components/payment.rb +44 -9
  27. data/lib/minfraud/components/report/transaction.rb +50 -39
  28. data/lib/minfraud/components/shipping.rb +14 -5
  29. data/lib/minfraud/components/shopping_cart.rb +19 -12
  30. data/lib/minfraud/components/shopping_cart_item.rb +42 -13
  31. data/lib/minfraud/enum.rb +22 -8
  32. data/lib/minfraud/error_handler.rb +32 -25
  33. data/lib/minfraud/errors.rb +22 -2
  34. data/lib/minfraud/http_service.rb +23 -8
  35. data/lib/minfraud/http_service/request.rb +19 -18
  36. data/lib/minfraud/http_service/response.rb +19 -14
  37. data/lib/minfraud/model/address.rb +4 -4
  38. data/lib/minfraud/model/credit_card.rb +7 -7
  39. data/lib/minfraud/model/device.rb +2 -2
  40. data/lib/minfraud/model/email.rb +4 -4
  41. data/lib/minfraud/model/error.rb +1 -1
  42. data/lib/minfraud/model/insights.rb +5 -5
  43. data/lib/minfraud/model/ip_address.rb +20 -1
  44. data/lib/minfraud/model/ip_risk_reason.rb +48 -0
  45. data/lib/minfraud/model/issuer.rb +3 -3
  46. data/lib/minfraud/model/score.rb +6 -6
  47. data/lib/minfraud/model/shipping_address.rb +1 -1
  48. data/lib/minfraud/model/subscores.rb +38 -16
  49. data/lib/minfraud/model/warning.rb +2 -2
  50. data/lib/minfraud/report.rb +33 -13
  51. data/lib/minfraud/resolver.rb +25 -17
  52. data/lib/minfraud/validates.rb +187 -0
  53. data/lib/minfraud/version.rb +4 -1
  54. data/minfraud.gemspec +8 -2
  55. metadata +77 -10
  56. data/.travis.yml +0 -22
@@ -1,10 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Minfraud
4
+ # Resolver provides functionality for setting component attributes.
2
5
  module Resolver
3
6
  class << self
4
- # @param [Object] context an object for variable assignment
5
- # @param [Hash] params a hash of parameters
6
- # @return [Array] a list of supplied params
7
- # @note Raises RequestFormatError once unpermitted key is met
7
+ # Set keys on the context based on the provided parameters.
8
+ #
9
+ # @param context [Object] An object for variable assignment.
10
+ #
11
+ # @param params [Hash] A hash of parameters.
12
+ #
13
+ # @return [Array]
14
+ #
15
+ # @raise [Minfraud::RequestFormatError] If an unexpected key is found.
8
16
  def assign(context, params)
9
17
  Array(params).each do |key, value|
10
18
  raise RequestFormatError, "#{key} does not belong to request document format" unless MAPPING[key]
@@ -15,19 +23,19 @@ module Minfraud
15
23
  end
16
24
  end
17
25
 
18
- # Mapping between components & minFraud request keys
26
+ # @!visibility private
19
27
  MAPPING = {
20
- account: ::Minfraud::Components::Account,
21
- billing: ::Minfraud::Components::Billing,
22
- credit_card: ::Minfraud::Components::CreditCard,
23
- custom_inputs: ::Minfraud::Components::CustomInputs,
24
- device: ::Minfraud::Components::Device,
25
- email: ::Minfraud::Components::Email,
26
- event: ::Minfraud::Components::Event,
27
- order: ::Minfraud::Components::Order,
28
- payment: ::Minfraud::Components::Payment,
29
- shipping: ::Minfraud::Components::Shipping,
30
- shopping_cart: ::Minfraud::Components::ShoppingCart,
31
- }
28
+ account: ::Minfraud::Components::Account,
29
+ billing: ::Minfraud::Components::Billing,
30
+ credit_card: ::Minfraud::Components::CreditCard,
31
+ custom_inputs: ::Minfraud::Components::CustomInputs,
32
+ device: ::Minfraud::Components::Device,
33
+ email: ::Minfraud::Components::Email,
34
+ event: ::Minfraud::Components::Event,
35
+ order: ::Minfraud::Components::Order,
36
+ payment: ::Minfraud::Components::Payment,
37
+ shipping: ::Minfraud::Components::Shipping,
38
+ shopping_cart: ::Minfraud::Components::ShoppingCart,
39
+ }.freeze
32
40
  end
33
41
  end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'ipaddr'
5
+ require 'uri'
6
+
7
+ # rubocop:disable Metrics/ModuleLength
8
+ module Minfraud
9
+ # @!visibility private
10
+ module Validates
11
+ def validate_string(field, length, value)
12
+ return if !value
13
+
14
+ if value.to_s.length > length
15
+ raise InvalidInputError, "The #{field} value is not valid. The maximum length is #{length}."
16
+ end
17
+ end
18
+
19
+ def validate_md5(field, value)
20
+ return if !value
21
+
22
+ if !value.to_s.match(/\A[a-fA-F0-9]{32}\z/)
23
+ raise InvalidInputError, "The #{field} value is not valid. It must be an MD5 hash as a string."
24
+ end
25
+ end
26
+
27
+ def validate_subdivision_code(field, value)
28
+ return if !value
29
+
30
+ if !value.to_s.match(/\A[0-9A-Z]{1,4}\z/)
31
+ raise InvalidInputError, "The #{field} value is not valid. It must be an ISO 3166-2 subdivision code."
32
+ end
33
+ end
34
+
35
+ def validate_country_code(field, value)
36
+ return if !value
37
+
38
+ if !value.to_s.match(/\A[A-Z]{2}\z/)
39
+ raise InvalidInputError, "The #{field} value is not valid. It must be an ISO 3166-1 alpha-2 country code."
40
+ end
41
+ end
42
+
43
+ def validate_telephone_country_code(field, value)
44
+ return if !value
45
+
46
+ if !value.to_s.match(/\A[0-9]{1,4}\z/)
47
+ raise InvalidInputError, "The #{field} value is not valid. It must be at most 4 digits."
48
+ end
49
+ end
50
+
51
+ def validate_regex(field, regex, value)
52
+ return if !value
53
+
54
+ if !regex.match(value.to_s)
55
+ raise InvalidInputError, "The #{field} value is not valid. It must match the pattern #{regex}."
56
+ end
57
+ end
58
+
59
+ def validate_credit_card_token(field, value)
60
+ return if !value
61
+
62
+ s = value.to_s
63
+
64
+ if !/\A[\x21-\x7E]{1,255}\z/.match(s)
65
+ raise InvalidInputError, "The #{field} value is not valid. It must contain only non-space printable ASCII characters."
66
+ end
67
+
68
+ if /\A[0-9]{1,19}\z/.match(s)
69
+ raise InvalidInputError, "The #{field} value is not valid. If it is all digits, it must be longer than 19 characters."
70
+ end
71
+ end
72
+
73
+ def validate_custom_input_value(field, value)
74
+ return if !value
75
+
76
+ if [true, false].include?(value)
77
+ return
78
+ end
79
+
80
+ if value.is_a? Numeric
81
+ if value < -1e13 + 1 || value > 1e13 - 1
82
+ raise InvalidInputError, "The #{field} value is not valid. Numeric values must be between -1e13 and 1e13."
83
+ end
84
+
85
+ return
86
+ end
87
+
88
+ validate_string(field, 255, value)
89
+ end
90
+
91
+ def validate_ip(field, value)
92
+ return if !value
93
+
94
+ s = value.to_s
95
+ if s.include? '/'
96
+ raise InvalidInputError, "The #{field} value is not valid. It must be an individual IP address."
97
+ end
98
+
99
+ # rubocop:disable Style/RescueStandardError
100
+ begin
101
+ IPAddr.new(s)
102
+ rescue
103
+ raise InvalidInputError, "The #{field} value is not valid. It must be an IPv4 or IPv6 address."
104
+ end
105
+ # rubocop:enable Style/RescueStandardError
106
+
107
+ nil
108
+ end
109
+
110
+ def validate_nonnegative_number(field, value)
111
+ return if !value
112
+
113
+ if !value.is_a? Numeric
114
+ raise InvalidInputError, "The #{field} value is not valid. It must be numeric."
115
+ end
116
+
117
+ if value < 0 || value > 1e13 - 1
118
+ raise InvalidInputError, "The #{field} value is not valid. It must be at least 0 and at most 1e13 - 1."
119
+ end
120
+ end
121
+
122
+ def validate_nonnegative_integer(field, value)
123
+ return if !value
124
+
125
+ if !value.is_a? Integer
126
+ raise InvalidInputError, "The #{field} is not valid. It must be an integer."
127
+ end
128
+
129
+ if value < 0 || value > 1e13 - 1
130
+ raise InvalidInputError, "The #{field} is not valid. It must be at least 0 and at most 1e13 - 1."
131
+ end
132
+ end
133
+
134
+ def validate_email(field, value)
135
+ return if !value
136
+
137
+ if /.@./.match(value)
138
+ validate_string(field, 255, value)
139
+ return
140
+ end
141
+
142
+ validate_md5(field, value)
143
+ end
144
+
145
+ def validate_rfc3339(field, value)
146
+ return if !value
147
+
148
+ # rubocop:disable Style/RescueStandardError
149
+ begin
150
+ DateTime.rfc3339(value)
151
+ rescue
152
+ raise InvalidInputError, "The #{field} value is not valid. It must be in the RFC 3339 date-time format."
153
+ end
154
+ # rubocop:enable Style/RescueStandardError
155
+
156
+ nil
157
+ end
158
+
159
+ def validate_boolean(field, value)
160
+ return if !value
161
+
162
+ if ![false, true].include? value
163
+ raise InvalidInputError, "The #{field} value is not valid. It must be boolean."
164
+ end
165
+ end
166
+
167
+ def validate_uri(field, value)
168
+ return if !value
169
+
170
+ if value.to_s.length > 1_024
171
+ raise InvalidInputError, "The #{field} value is not valid. It must not exceed 1024 characters."
172
+ end
173
+
174
+ # rubocop:disable Style/RescueStandardError
175
+ begin
176
+ u = URI(value)
177
+ if !u.scheme
178
+ raise InvalidInputError
179
+ end
180
+ rescue
181
+ raise InvalidInputError, "The #{field} value is not valid. It must be an absolute URI."
182
+ end
183
+ # rubocop:enable Style/RescueStandardError
184
+ end
185
+ end
186
+ end
187
+ # rubocop:enable Metrics/ModuleLength
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Minfraud
2
- VERSION = '1.1.0'
4
+ # The Gem version.
5
+ VERSION = '1.5.0'
3
6
  end
data/minfraud.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('lib', File.dirname(File.realpath(__FILE__)))
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
 
@@ -9,11 +11,11 @@ Gem::Specification.new do |spec|
9
11
  spec.authors = ['kushnir.yb']
10
12
  spec.email = ['support@maxmind.com']
11
13
 
12
- spec.summary = %q(Ruby interface to the MaxMind minFraud v2.0 API services)
14
+ spec.summary = 'Ruby API for the minFraud Score, Insights, Factors, and Report Transactions services'
13
15
  spec.homepage = 'https://github.com/maxmind/minfraud-api-ruby'
14
16
  spec.license = 'MIT'
15
17
 
16
- spec.required_ruby_version = '>= 1.9'
18
+ spec.required_ruby_version = '>= 2.1'
17
19
 
18
20
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
21
  spec.bindir = 'exe'
@@ -22,8 +24,12 @@ Gem::Specification.new do |spec|
22
24
 
23
25
  spec.add_runtime_dependency 'faraday', '>= 0.9.1', '< 2.0'
24
26
  spec.add_runtime_dependency 'faraday_middleware', '>= 0.9.1', '< 2.0'
27
+ spec.add_runtime_dependency 'net-http-persistent', '>= 2.0.0', '< 5.0'
28
+ spec.add_runtime_dependency 'simpleidn', '>= 0.1.1'
25
29
 
26
30
  spec.add_development_dependency 'bundler', '>= 1.16'
27
31
  spec.add_development_dependency 'rake'
28
32
  spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'rubocop'
34
+ spec.add_development_dependency 'webmock'
29
35
  end
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.1.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kushnir.yb
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-19 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
@@ -50,6 +50,40 @@ dependencies:
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '2.0'
53
+ - !ruby/object:Gem::Dependency
54
+ name: net-http-persistent
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 2.0.0
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '5.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 2.0.0
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
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
53
87
  - !ruby/object:Gem::Dependency
54
88
  name: bundler
55
89
  requirement: !ruby/object:Gem::Requirement
@@ -92,16 +126,46 @@ dependencies:
92
126
  - - "~>"
93
127
  - !ruby/object:Gem::Version
94
128
  version: '3.0'
95
- description:
129
+ - !ruby/object:Gem::Dependency
130
+ name: rubocop
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ - !ruby/object:Gem::Dependency
144
+ name: webmock
145
+ requirement: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ description:
96
158
  email:
97
159
  - support@maxmind.com
98
160
  executables: []
99
161
  extensions: []
100
162
  extra_rdoc_files: []
101
163
  files:
164
+ - ".github/workflows/rubocop.yml"
165
+ - ".github/workflows/test.yml"
102
166
  - ".gitignore"
103
167
  - ".rspec"
104
- - ".travis.yml"
168
+ - ".rubocop.yml"
105
169
  - CHANGELOG.md
106
170
  - CODE_OF_CONDUCT.md
107
171
  - Gemfile
@@ -161,6 +225,7 @@ files:
161
225
  - lib/minfraud/model/geoip2_location.rb
162
226
  - lib/minfraud/model/insights.rb
163
227
  - lib/minfraud/model/ip_address.rb
228
+ - lib/minfraud/model/ip_risk_reason.rb
164
229
  - lib/minfraud/model/issuer.rb
165
230
  - lib/minfraud/model/score.rb
166
231
  - lib/minfraud/model/score_ip_address.rb
@@ -169,13 +234,14 @@ files:
169
234
  - lib/minfraud/model/warning.rb
170
235
  - lib/minfraud/report.rb
171
236
  - lib/minfraud/resolver.rb
237
+ - lib/minfraud/validates.rb
172
238
  - lib/minfraud/version.rb
173
239
  - minfraud.gemspec
174
240
  homepage: https://github.com/maxmind/minfraud-api-ruby
175
241
  licenses:
176
242
  - MIT
177
243
  metadata: {}
178
- post_install_message:
244
+ post_install_message:
179
245
  rdoc_options: []
180
246
  require_paths:
181
247
  - lib
@@ -183,16 +249,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
249
  requirements:
184
250
  - - ">="
185
251
  - !ruby/object:Gem::Version
186
- version: '1.9'
252
+ version: '2.1'
187
253
  required_rubygems_version: !ruby/object:Gem::Requirement
188
254
  requirements:
189
255
  - - ">="
190
256
  - !ruby/object:Gem::Version
191
257
  version: '0'
192
258
  requirements: []
193
- rubyforge_project:
259
+ rubyforge_project:
194
260
  rubygems_version: 2.7.6.2
195
- signing_key:
261
+ signing_key:
196
262
  specification_version: 4
197
- summary: Ruby interface to the MaxMind minFraud v2.0 API services
263
+ summary: Ruby API for the minFraud Score, Insights, Factors, and Report Transactions
264
+ services
198
265
  test_files: []
data/.travis.yml DELETED
@@ -1,22 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 1.9
5
- - 2.0
6
- - 2.1
7
- - 2.2
8
- - 2.3
9
- - 2.4
10
- - 2.5
11
- - 2.6
12
- - 2.7
13
-
14
- notifications:
15
- email:
16
- on_failure: always
17
- on_success: change
18
- recipients:
19
- - dev-ci@maxmind.com
20
- slack:
21
- rooms:
22
- secure: "wuwMo+BWnaBtkt1uGAi4Zd0EARX3B2TXDmBGCtn8r4PLfehh61S6nLQDASNXSk200PmniFM8PyOUNVGVJqWpYQAEMn32WWdy4vTK2c8CsjwfsMhgnOI2YDCzw+jiP+8EfIGBsPO4xA7yrzweP8gkzBtplb3LbaCiW83WfFo9+402yr0/0F9gfWi8qvuIw29XAS1XWhTY4itqGfkSPdOHQz/45ElpLkGlgreuRrih3tAgn9YLb/Uh/6McHfHkL74YwQU3p0NiZcoleWYM0CLpPzyrN8EsbmIT+L75nIVwXnh62Gx2jJWayj7ZzvyKtVKHtLb/LKRs4Dg0UEg65xX1EcBAkC5fn4KG1jQHvi/tdOx1Sfh3hO6OK+68q1R6cQQYy+uG84q8RUjpO6dzFcWpE1yMdbQ5XMKfTh56ZdhXJ803LD2gGeIgcMwJp6HK9tnf0vaPPI9kbr8fqJBUUkciUoqpYzFd5m0ZCUbJsMD0oPY19FSRtfCNQvCbmhYrLy1sQ5FeMzbF0bi2oaUv+JD/A5RKokNMrrwv3nnTtG4vN1hJklQk2VW3sZWl6UjYgzhrbmKABtvPuB+xcYywIu4+JSworpfDwM/PZAKOfd6n+r8OdNV256l8WaNeF6osvXkUR7yxYpytywdQPA0d/z8mxTVoATE3wat7pnmTrqI5fqw=\n"