verifip 0.1.4 → 0.2.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 +4 -4
- data/lib/verifip/client.rb +83 -0
- data/lib/verifip/models.rb +240 -0
- data/lib/verifip/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e99ded51e832b1176e27fad783ead281c84558bc6068281a3c3b0d592bba427a
|
|
4
|
+
data.tar.gz: 392d5354097484e8300e83aae37861a86a4569f5b629e5511b325591078c89fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d028b0428cfb862608aeaa9ab614c2cb0b0f9f7b1ef65cfb0e0334656aeb619baf415a880750120c7c11e7b09519570c042b4bfd4863e0f664c661e2dcd83d18
|
|
7
|
+
data.tar.gz: 4403542ed7c9a49ec9d47ce17a847617e7ec95716a90c5fac13fb5a41adf9b1aff38235a5e59d33a3016012cdf7b36359dcd47dc0fda5ee871e432c5cf3a82a9
|
data/lib/verifip/client.rb
CHANGED
|
@@ -78,6 +78,89 @@ module VerifIP
|
|
|
78
78
|
HealthResponse.from_hash(data)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
# Check an email address for fraud risk.
|
|
82
|
+
#
|
|
83
|
+
# @param email [String] email address to check
|
|
84
|
+
# @return [EmailResponse]
|
|
85
|
+
def check_email(email)
|
|
86
|
+
raise ArgumentError, "email is required" if email.nil? || email.empty?
|
|
87
|
+
|
|
88
|
+
data = request(:get, "/v1/email?email=#{URI.encode_uri_component(email)}", auth: true)
|
|
89
|
+
EmailResponse.from_hash(data)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Check a phone number for fraud risk.
|
|
93
|
+
#
|
|
94
|
+
# @param phone [String] phone number to check
|
|
95
|
+
# @return [PhoneResponse]
|
|
96
|
+
def check_phone(phone)
|
|
97
|
+
raise ArgumentError, "phone is required" if phone.nil? || phone.empty?
|
|
98
|
+
|
|
99
|
+
data = request(:get, "/v1/phone?phone=#{URI.encode_uri_component(phone)}", auth: true)
|
|
100
|
+
PhoneResponse.from_hash(data)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Check a URL for fraud risk.
|
|
104
|
+
#
|
|
105
|
+
# @param url [String] URL to check
|
|
106
|
+
# @return [URLResponse]
|
|
107
|
+
def check_url(url)
|
|
108
|
+
raise ArgumentError, "url is required" if url.nil? || url.empty?
|
|
109
|
+
|
|
110
|
+
data = request(:get, "/v1/url?url=#{URI.encode_uri_component(url)}", auth: true)
|
|
111
|
+
URLResponse.from_hash(data)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Perform a WHOIS lookup for an IP address.
|
|
115
|
+
#
|
|
116
|
+
# @param ip [String] IPv4 or IPv6 address
|
|
117
|
+
# @return [WHOISResponse]
|
|
118
|
+
def check_whois(ip)
|
|
119
|
+
raise ArgumentError, "ip is required" if ip.nil? || ip.empty?
|
|
120
|
+
|
|
121
|
+
data = request(:get, "/v1/whois?ip=#{URI.encode_uri_component(ip)}", auth: true)
|
|
122
|
+
WHOISResponse.from_hash(data)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Submit a fraud report for an IP address.
|
|
126
|
+
#
|
|
127
|
+
# @param ip [String] IPv4 or IPv6 address
|
|
128
|
+
# @param is_fraud [Boolean] whether the IP was used for fraud
|
|
129
|
+
# @param category [String] optional fraud category
|
|
130
|
+
# @param comment [String] optional comment
|
|
131
|
+
# @return [ReportResponse]
|
|
132
|
+
def report(ip, is_fraud, category: "", comment: "")
|
|
133
|
+
raise ArgumentError, "ip is required" if ip.nil? || ip.empty?
|
|
134
|
+
|
|
135
|
+
payload = { ip: ip, is_fraud: is_fraud }
|
|
136
|
+
payload[:category] = category unless category.empty?
|
|
137
|
+
payload[:comment] = comment unless comment.empty?
|
|
138
|
+
|
|
139
|
+
body = JSON.generate(payload)
|
|
140
|
+
data = request(:post, "/v1/report", body: body, auth: true)
|
|
141
|
+
ReportResponse.from_hash(data)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Perform a multi-signal risk assessment.
|
|
145
|
+
#
|
|
146
|
+
# @param ip [String] optional IP address
|
|
147
|
+
# @param email [String] optional email address
|
|
148
|
+
# @param phone [String] optional phone number
|
|
149
|
+
# @param url [String] optional URL
|
|
150
|
+
# @return [AssessResponse]
|
|
151
|
+
def assess(ip: "", email: "", phone: "", url: "")
|
|
152
|
+
params = []
|
|
153
|
+
params << "ip=#{URI.encode_uri_component(ip)}" unless ip.empty?
|
|
154
|
+
params << "email=#{URI.encode_uri_component(email)}" unless email.empty?
|
|
155
|
+
params << "phone=#{URI.encode_uri_component(phone)}" unless phone.empty?
|
|
156
|
+
params << "url=#{URI.encode_uri_component(url)}" unless url.empty?
|
|
157
|
+
|
|
158
|
+
raise ArgumentError, "at least one parameter is required" if params.empty?
|
|
159
|
+
|
|
160
|
+
data = request(:get, "/v1/assess?#{params.join('&')}", auth: true)
|
|
161
|
+
AssessResponse.from_hash(data)
|
|
162
|
+
end
|
|
163
|
+
|
|
81
164
|
def to_s = "VerifIP::Client(base_url=#{@base_url})"
|
|
82
165
|
def inspect = to_s
|
|
83
166
|
|
data/lib/verifip/models.rb
CHANGED
|
@@ -115,6 +115,246 @@ module VerifIP
|
|
|
115
115
|
def inspect = to_s
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
# Response from an email risk check.
|
|
119
|
+
class EmailResponse
|
|
120
|
+
FIELDS = %i[
|
|
121
|
+
request_id email risk_score valid_syntax mx_found is_disposable
|
|
122
|
+
is_free_provider is_role_based domain_age_days domain
|
|
123
|
+
signal_breakdown error
|
|
124
|
+
].freeze
|
|
125
|
+
|
|
126
|
+
attr_reader(*FIELDS)
|
|
127
|
+
|
|
128
|
+
def initialize(**kwargs)
|
|
129
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
130
|
+
@email = kwargs.fetch(:email, "")
|
|
131
|
+
@risk_score = kwargs.fetch(:risk_score, 0)
|
|
132
|
+
@valid_syntax = kwargs.fetch(:valid_syntax, false)
|
|
133
|
+
@mx_found = kwargs.fetch(:mx_found, false)
|
|
134
|
+
@is_disposable = kwargs.fetch(:is_disposable, false)
|
|
135
|
+
@is_free_provider = kwargs.fetch(:is_free_provider, false)
|
|
136
|
+
@is_role_based = kwargs.fetch(:is_role_based, false)
|
|
137
|
+
@domain_age_days = kwargs.fetch(:domain_age_days, 0)
|
|
138
|
+
@domain = kwargs.fetch(:domain, "")
|
|
139
|
+
@signal_breakdown = kwargs.fetch(:signal_breakdown, {})
|
|
140
|
+
@error = kwargs.fetch(:error, nil)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def self.from_hash(hash)
|
|
144
|
+
hash = _symbolize(hash)
|
|
145
|
+
new(**hash.slice(*FIELDS))
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def to_h
|
|
149
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def to_s = "EmailResponse(email=#{@email}, risk_score=#{@risk_score})"
|
|
153
|
+
def inspect = to_s
|
|
154
|
+
|
|
155
|
+
def self._symbolize(hash)
|
|
156
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
157
|
+
end
|
|
158
|
+
private_class_method :_symbolize
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Response from a phone number risk check.
|
|
162
|
+
class PhoneResponse
|
|
163
|
+
FIELDS = %i[
|
|
164
|
+
request_id phone risk_score valid country_code carrier
|
|
165
|
+
line_type is_voip signal_breakdown error
|
|
166
|
+
].freeze
|
|
167
|
+
|
|
168
|
+
attr_reader(*FIELDS)
|
|
169
|
+
|
|
170
|
+
def initialize(**kwargs)
|
|
171
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
172
|
+
@phone = kwargs.fetch(:phone, "")
|
|
173
|
+
@risk_score = kwargs.fetch(:risk_score, 0)
|
|
174
|
+
@valid = kwargs.fetch(:valid, false)
|
|
175
|
+
@country_code = kwargs.fetch(:country_code, "")
|
|
176
|
+
@carrier = kwargs.fetch(:carrier, "")
|
|
177
|
+
@line_type = kwargs.fetch(:line_type, "")
|
|
178
|
+
@is_voip = kwargs.fetch(:is_voip, false)
|
|
179
|
+
@signal_breakdown = kwargs.fetch(:signal_breakdown, {})
|
|
180
|
+
@error = kwargs.fetch(:error, nil)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def self.from_hash(hash)
|
|
184
|
+
hash = _symbolize(hash)
|
|
185
|
+
new(**hash.slice(*FIELDS))
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def voip? = @is_voip
|
|
189
|
+
|
|
190
|
+
def to_h
|
|
191
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def to_s = "PhoneResponse(phone=#{@phone}, risk_score=#{@risk_score})"
|
|
195
|
+
def inspect = to_s
|
|
196
|
+
|
|
197
|
+
def self._symbolize(hash)
|
|
198
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
199
|
+
end
|
|
200
|
+
private_class_method :_symbolize
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Response from a URL risk check.
|
|
204
|
+
class URLResponse
|
|
205
|
+
FIELDS = %i[
|
|
206
|
+
request_id url risk_score is_phishing is_malware
|
|
207
|
+
safe_browsing_threat in_phishtank spamhaus_dbl domain_age_days
|
|
208
|
+
ssl_valid ssl_issuer signal_breakdown error
|
|
209
|
+
].freeze
|
|
210
|
+
|
|
211
|
+
attr_reader(*FIELDS)
|
|
212
|
+
|
|
213
|
+
def initialize(**kwargs)
|
|
214
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
215
|
+
@url = kwargs.fetch(:url, "")
|
|
216
|
+
@risk_score = kwargs.fetch(:risk_score, 0)
|
|
217
|
+
@is_phishing = kwargs.fetch(:is_phishing, false)
|
|
218
|
+
@is_malware = kwargs.fetch(:is_malware, false)
|
|
219
|
+
@safe_browsing_threat = kwargs.fetch(:safe_browsing_threat, "")
|
|
220
|
+
@in_phishtank = kwargs.fetch(:in_phishtank, false)
|
|
221
|
+
@spamhaus_dbl = kwargs.fetch(:spamhaus_dbl, false)
|
|
222
|
+
@domain_age_days = kwargs.fetch(:domain_age_days, 0)
|
|
223
|
+
@ssl_valid = kwargs.fetch(:ssl_valid, false)
|
|
224
|
+
@ssl_issuer = kwargs.fetch(:ssl_issuer, "")
|
|
225
|
+
@signal_breakdown = kwargs.fetch(:signal_breakdown, {})
|
|
226
|
+
@error = kwargs.fetch(:error, nil)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def self.from_hash(hash)
|
|
230
|
+
hash = _symbolize(hash)
|
|
231
|
+
new(**hash.slice(*FIELDS))
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def phishing? = @is_phishing
|
|
235
|
+
def malware? = @is_malware
|
|
236
|
+
|
|
237
|
+
def to_h
|
|
238
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def to_s = "URLResponse(url=#{@url}, risk_score=#{@risk_score})"
|
|
242
|
+
def inspect = to_s
|
|
243
|
+
|
|
244
|
+
def self._symbolize(hash)
|
|
245
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
246
|
+
end
|
|
247
|
+
private_class_method :_symbolize
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Response from a WHOIS lookup.
|
|
251
|
+
class WHOISResponse
|
|
252
|
+
FIELDS = %i[
|
|
253
|
+
request_id ip network_cidr network_name org_name abuse_contact
|
|
254
|
+
rir allocation_date country_code asn asn_org
|
|
255
|
+
].freeze
|
|
256
|
+
|
|
257
|
+
attr_reader(*FIELDS)
|
|
258
|
+
|
|
259
|
+
def initialize(**kwargs)
|
|
260
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
261
|
+
@ip = kwargs.fetch(:ip, "")
|
|
262
|
+
@network_cidr = kwargs.fetch(:network_cidr, "")
|
|
263
|
+
@network_name = kwargs.fetch(:network_name, "")
|
|
264
|
+
@org_name = kwargs.fetch(:org_name, "")
|
|
265
|
+
@abuse_contact = kwargs.fetch(:abuse_contact, "")
|
|
266
|
+
@rir = kwargs.fetch(:rir, "")
|
|
267
|
+
@allocation_date = kwargs.fetch(:allocation_date, "")
|
|
268
|
+
@country_code = kwargs.fetch(:country_code, "")
|
|
269
|
+
@asn = kwargs.fetch(:asn, 0)
|
|
270
|
+
@asn_org = kwargs.fetch(:asn_org, "")
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def self.from_hash(hash)
|
|
274
|
+
hash = _symbolize(hash)
|
|
275
|
+
new(**hash.slice(*FIELDS))
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def to_h
|
|
279
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def to_s = "WHOISResponse(ip=#{@ip}, network_cidr=#{@network_cidr})"
|
|
283
|
+
def inspect = to_s
|
|
284
|
+
|
|
285
|
+
def self._symbolize(hash)
|
|
286
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
287
|
+
end
|
|
288
|
+
private_class_method :_symbolize
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Response from a fraud report submission.
|
|
292
|
+
class ReportResponse
|
|
293
|
+
FIELDS = %i[request_id status message].freeze
|
|
294
|
+
|
|
295
|
+
attr_reader(*FIELDS)
|
|
296
|
+
|
|
297
|
+
def initialize(**kwargs)
|
|
298
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
299
|
+
@status = kwargs.fetch(:status, "")
|
|
300
|
+
@message = kwargs.fetch(:message, "")
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def self.from_hash(hash)
|
|
304
|
+
hash = _symbolize(hash)
|
|
305
|
+
new(**hash.slice(*FIELDS))
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def to_h
|
|
309
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def to_s = "ReportResponse(status=#{@status}, message=#{@message})"
|
|
313
|
+
def inspect = to_s
|
|
314
|
+
|
|
315
|
+
def self._symbolize(hash)
|
|
316
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
317
|
+
end
|
|
318
|
+
private_class_method :_symbolize
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Response from a multi-signal risk assessment.
|
|
322
|
+
class AssessResponse
|
|
323
|
+
FIELDS = %i[request_id overall_risk ip email phone url].freeze
|
|
324
|
+
|
|
325
|
+
attr_reader(*FIELDS)
|
|
326
|
+
|
|
327
|
+
def initialize(**kwargs)
|
|
328
|
+
@request_id = kwargs.fetch(:request_id, "")
|
|
329
|
+
@overall_risk = kwargs.fetch(:overall_risk, 0)
|
|
330
|
+
@ip = kwargs.fetch(:ip, nil)
|
|
331
|
+
@email = kwargs.fetch(:email, nil)
|
|
332
|
+
@phone = kwargs.fetch(:phone, nil)
|
|
333
|
+
@url = kwargs.fetch(:url, nil)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def self.from_hash(hash)
|
|
337
|
+
hash = _symbolize(hash)
|
|
338
|
+
hash[:ip] = CheckResponse.from_hash(hash[:ip]) if hash[:ip].is_a?(Hash)
|
|
339
|
+
hash[:email] = EmailResponse.from_hash(hash[:email]) if hash[:email].is_a?(Hash)
|
|
340
|
+
hash[:phone] = PhoneResponse.from_hash(hash[:phone]) if hash[:phone].is_a?(Hash)
|
|
341
|
+
hash[:url] = URLResponse.from_hash(hash[:url]) if hash[:url].is_a?(Hash)
|
|
342
|
+
new(**hash.slice(*FIELDS))
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def to_h
|
|
346
|
+
FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def to_s = "AssessResponse(overall_risk=#{@overall_risk})"
|
|
350
|
+
def inspect = to_s
|
|
351
|
+
|
|
352
|
+
def self._symbolize(hash)
|
|
353
|
+
hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
|
354
|
+
end
|
|
355
|
+
private_class_method :_symbolize
|
|
356
|
+
end
|
|
357
|
+
|
|
118
358
|
# Rate limit information parsed from response headers.
|
|
119
359
|
class RateLimitInfo
|
|
120
360
|
# @return [Integer] maximum requests in the current window
|
data/lib/verifip/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: verifip
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- VerifIP
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|