trustcaptcha 2.0.0 → 3.0.0.pre.beta.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10be47df90f618cc6611a61abc1a854103de387ab11485d5441792cb9020ef2b
|
|
4
|
+
data.tar.gz: d07f749734370f5389306497b494a0c4174a62a589a96642f12e5bff70ca9a56
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9124e75c419119f80641dd7c4a7740359872e01ffc771c840caae4cb7be8035818d3cc158663b47787d889052567d92048fa8433872f1576d8f4e455262c0a8d
|
|
7
|
+
data.tar.gz: 5be40a6a066b02c720969460754a7a322f6beb31de61f3be9b4b133ded5e4a3a15279c6135b458eeb948586704f948b1accae85102d85c16b75c47456d774d89
|
|
@@ -1,25 +1,35 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
|
|
3
3
|
class VerificationResult
|
|
4
|
-
attr_reader :captcha_id, :verification_id, :
|
|
5
|
-
:
|
|
6
|
-
:
|
|
4
|
+
attr_reader :captcha_id, :verification_id, :verification_passed, :score,
|
|
5
|
+
:decision_type, :decision_action, :gateway_failover_active,
|
|
6
|
+
:risk_scoring_enabled, :minimal_data_mode_enabled,
|
|
7
|
+
:origin, :ip_address, :country_code,
|
|
8
|
+
:device_family, :operating_system, :browser,
|
|
9
|
+
:verification_started_at, :verification_finished_at,
|
|
10
|
+
:result_expires_at, :result_first_fetched_at, :result_last_fetched_at
|
|
7
11
|
|
|
8
12
|
def initialize(data)
|
|
9
13
|
@captcha_id = data['captchaId']
|
|
10
14
|
@verification_id = data['verificationId']
|
|
15
|
+
@verification_passed = data['verificationPassed']
|
|
11
16
|
@score = data['score']
|
|
12
|
-
@
|
|
13
|
-
@
|
|
17
|
+
@decision_type = data['decisionType']
|
|
18
|
+
@decision_action = data['decisionAction']
|
|
19
|
+
@gateway_failover_active = data['gatewayFailoverActive']
|
|
20
|
+
@risk_scoring_enabled = data['riskScoringEnabled']
|
|
21
|
+
@minimal_data_mode_enabled = data['minimalDataModeEnabled']
|
|
14
22
|
@origin = data['origin']
|
|
15
23
|
@ip_address = data['ipAddress']
|
|
24
|
+
@country_code = data['countryCode']
|
|
16
25
|
@device_family = data['deviceFamily']
|
|
17
26
|
@operating_system = data['operatingSystem']
|
|
18
27
|
@browser = data['browser']
|
|
19
|
-
@
|
|
20
|
-
@
|
|
21
|
-
@
|
|
22
|
-
@
|
|
28
|
+
@verification_started_at = data['verificationStartedAt']
|
|
29
|
+
@verification_finished_at = data['verificationFinishedAt']
|
|
30
|
+
@result_expires_at = data['resultExpiresAt']
|
|
31
|
+
@result_first_fetched_at = data['resultFirstFetchedAt']
|
|
32
|
+
@result_last_fetched_at = data['resultLastFetchedAt']
|
|
23
33
|
end
|
|
24
34
|
|
|
25
35
|
def self.from_json(json_data)
|
|
@@ -31,18 +41,24 @@ class VerificationResult
|
|
|
31
41
|
{
|
|
32
42
|
captchaId: @captcha_id,
|
|
33
43
|
verificationId: @verification_id,
|
|
44
|
+
verificationPassed: @verification_passed,
|
|
34
45
|
score: @score,
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
decisionType: @decision_type,
|
|
47
|
+
decisionAction: @decision_action,
|
|
48
|
+
gatewayFailoverActive: @gateway_failover_active,
|
|
49
|
+
riskScoringEnabled: @risk_scoring_enabled,
|
|
50
|
+
minimalDataModeEnabled: @minimal_data_mode_enabled,
|
|
37
51
|
origin: @origin,
|
|
38
52
|
ipAddress: @ip_address,
|
|
53
|
+
countryCode: @country_code,
|
|
39
54
|
deviceFamily: @device_family,
|
|
40
55
|
operatingSystem: @operating_system,
|
|
41
56
|
browser: @browser,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
verificationStartedAt: @verification_started_at,
|
|
58
|
+
verificationFinishedAt: @verification_finished_at,
|
|
59
|
+
resultExpiresAt: @result_expires_at,
|
|
60
|
+
resultFirstFetchedAt: @result_first_fetched_at,
|
|
61
|
+
resultLastFetchedAt: @result_last_fetched_at
|
|
46
62
|
}.to_json
|
|
47
63
|
end
|
|
48
64
|
end
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
require 'json'
|
|
2
|
-
require 'securerandom'
|
|
3
2
|
require 'base64'
|
|
4
3
|
|
|
5
4
|
class VerificationToken
|
|
6
|
-
attr_reader :
|
|
5
|
+
attr_reader :verification_id, :client_failover
|
|
7
6
|
|
|
8
|
-
def initialize(
|
|
9
|
-
@api_endpoint = api_endpoint
|
|
7
|
+
def initialize(verification_id, client_failover = false)
|
|
10
8
|
@verification_id = verification_id
|
|
9
|
+
@client_failover = client_failover
|
|
11
10
|
end
|
|
12
11
|
|
|
13
12
|
def self.from_base64(base64_string)
|
|
14
13
|
json_string = Base64.decode64(base64_string)
|
|
15
14
|
data = JSON.parse(json_string)
|
|
16
|
-
|
|
15
|
+
raise StandardError, 'Missing verificationId' if data['verificationId'].nil?
|
|
16
|
+
new(data['verificationId'], data['clientFailover'] == true)
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
raise e
|
|
17
19
|
end
|
|
18
20
|
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'base64'
|
|
5
|
+
require_relative 'model/verification_token'
|
|
6
|
+
require_relative 'model/verification_result'
|
|
7
|
+
|
|
8
|
+
class TrustCaptcha
|
|
9
|
+
|
|
10
|
+
LIBRARY_VERSION = '3.0.0'.freeze
|
|
11
|
+
LIBRARY_LANGUAGE = 'ruby'.freeze
|
|
12
|
+
DEFAULT_API_HOST = 'https://api.trustcomponent.com'.freeze
|
|
13
|
+
DEFAULT_CONNECT_TIMEOUT_S = 3
|
|
14
|
+
DEFAULT_READ_TIMEOUT_S = 5
|
|
15
|
+
|
|
16
|
+
class ApiKeyInvalidException < StandardError; end
|
|
17
|
+
class VerificationTokenInvalidException < StandardError; end
|
|
18
|
+
class VerificationNotFoundException < StandardError; end
|
|
19
|
+
class VerificationNotFinishedException < StandardError; end
|
|
20
|
+
class VerificationResultExpiredException < StandardError; end
|
|
21
|
+
class VerificationResultRetrievalLimitReachedException < StandardError; end
|
|
22
|
+
class FailoverException < StandardError; end
|
|
23
|
+
class ServerUnreachableException < FailoverException; end
|
|
24
|
+
class ClientReportedServerUnreachableException < FailoverException; end
|
|
25
|
+
|
|
26
|
+
def initialize(api_key,
|
|
27
|
+
api_host: DEFAULT_API_HOST,
|
|
28
|
+
connect_timeout_s: DEFAULT_CONNECT_TIMEOUT_S,
|
|
29
|
+
read_timeout_s: DEFAULT_READ_TIMEOUT_S,
|
|
30
|
+
proxy: nil)
|
|
31
|
+
raise ArgumentError, 'api_key must not be empty' if api_key.nil? || api_key.empty?
|
|
32
|
+
@api_key = api_key
|
|
33
|
+
@api_host = api_host
|
|
34
|
+
@connect_timeout_s = connect_timeout_s
|
|
35
|
+
@read_timeout_s = read_timeout_s
|
|
36
|
+
@proxy = proxy # Either a URI string ("http://host:port[/]") or nil.
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def get_verification_result(base64_verification_token)
|
|
40
|
+
verification_token = parse_verification_token(base64_verification_token)
|
|
41
|
+
query = verification_token.client_failover ? '?clientFailover=true' : ''
|
|
42
|
+
url = URI("#{@api_host}/v2/verifications/#{verification_token.verification_id}/results#{query}")
|
|
43
|
+
headers = {
|
|
44
|
+
'Authorization' => "Bearer #{@api_key}",
|
|
45
|
+
'User-Agent' => self.class.build_user_agent,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
http = if @proxy
|
|
49
|
+
p = URI.parse(@proxy)
|
|
50
|
+
Net::HTTP.new(url.host, url.port, p.host, p.port, p.user, p.password)
|
|
51
|
+
else
|
|
52
|
+
Net::HTTP.new(url.host, url.port)
|
|
53
|
+
end
|
|
54
|
+
http.use_ssl = url.scheme == 'https'
|
|
55
|
+
http.open_timeout = @connect_timeout_s
|
|
56
|
+
http.read_timeout = @read_timeout_s
|
|
57
|
+
|
|
58
|
+
response = begin
|
|
59
|
+
request = Net::HTTP::Get.new(url.request_uri, headers)
|
|
60
|
+
http.request(request)
|
|
61
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Net::OpenTimeout, Net::ReadTimeout, Errno::ETIMEDOUT
|
|
62
|
+
raise ServerUnreachableException, 'Could not reach the TrustCaptcha server. This is a high-trust failover signal — your backend was unable to contact our servers.'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
case response.code.to_i
|
|
66
|
+
when 403
|
|
67
|
+
raise ApiKeyInvalidException, 'The provided api key is invalid. Please verify the api key from your captcha settings.'
|
|
68
|
+
when 404
|
|
69
|
+
raise VerificationNotFoundException, 'No verification could be found for the given verification token.'
|
|
70
|
+
when 423
|
|
71
|
+
raise VerificationNotFinishedException, 'The verification is not yet completed. Please wait until the user has finished solving the captcha before requesting the result.'
|
|
72
|
+
when 410
|
|
73
|
+
raise VerificationResultExpiredException, 'The verification result has expired and can no longer be retrieved.'
|
|
74
|
+
when 412
|
|
75
|
+
raise ClientReportedServerUnreachableException, 'The client reported it could not reach the TrustCaptcha server, but the gateway has no record of a recent outage.'
|
|
76
|
+
when 429
|
|
77
|
+
raise VerificationResultRetrievalLimitReachedException, 'The verification result has reached its maximum retrieval count and can no longer be retrieved.'
|
|
78
|
+
else
|
|
79
|
+
raise "Failed to retrieve verification result: HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
VerificationResult.from_json(response.body)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def parse_verification_token(base64_verification_token)
|
|
88
|
+
VerificationToken.from_base64(base64_verification_token)
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
raise VerificationTokenInvalidException, "The verification token is malformed or could not be parsed: #{e.message}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.build_user_agent
|
|
94
|
+
payload = { 'language' => LIBRARY_LANGUAGE, 'version' => LIBRARY_VERSION }
|
|
95
|
+
encoded = Base64.strict_encode64(JSON.generate(payload))
|
|
96
|
+
"Trustcaptcha/#{encoded}"
|
|
97
|
+
end
|
|
98
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trustcaptcha
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0.pre.beta.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- TrustComponent
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -46,9 +46,9 @@ executables: []
|
|
|
46
46
|
extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
|
48
48
|
files:
|
|
49
|
-
- lib/trustcaptcha/captcha_manager.rb
|
|
50
49
|
- lib/trustcaptcha/model/verification_result.rb
|
|
51
50
|
- lib/trustcaptcha/model/verification_token.rb
|
|
51
|
+
- lib/trustcaptcha/trust_captcha.rb
|
|
52
52
|
homepage: https://www.trustcomponent.com/en/products/captcha/integrations/ruby-captcha
|
|
53
53
|
licenses:
|
|
54
54
|
- Apache-2.0
|
|
@@ -65,9 +65,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
65
65
|
version: '0'
|
|
66
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
requirements:
|
|
68
|
-
- - "
|
|
68
|
+
- - ">"
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
|
-
version:
|
|
70
|
+
version: 1.3.1
|
|
71
71
|
requirements: []
|
|
72
72
|
rubygems_version: 3.3.7
|
|
73
73
|
signing_key:
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
require 'net/http'
|
|
2
|
-
require 'uri'
|
|
3
|
-
require 'json'
|
|
4
|
-
require_relative 'model/verification_token'
|
|
5
|
-
require_relative 'model/verification_result'
|
|
6
|
-
|
|
7
|
-
class CaptchaManager
|
|
8
|
-
|
|
9
|
-
class SecretKeyInvalidException < StandardError; end
|
|
10
|
-
class VerificationTokenInvalidException < StandardError; end
|
|
11
|
-
class VerificationNotFoundException < StandardError; end
|
|
12
|
-
class VerificationNotFinishedException < StandardError; end
|
|
13
|
-
|
|
14
|
-
def self.get_verification_result(secret_key, base64_verification_token)
|
|
15
|
-
verification_token = get_verification_token(base64_verification_token)
|
|
16
|
-
fetch_verification_result(verification_token, secret_key)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def self.get_verification_token(base64_verification_token)
|
|
22
|
-
VerificationToken.from_base64(base64_verification_token)
|
|
23
|
-
rescue StandardError => e
|
|
24
|
-
raise VerificationTokenInvalidException, "Invalid verification token: #{e.message}"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.fetch_verification_result(verification_token, access_token)
|
|
28
|
-
url = URI("#{verification_token.api_endpoint}/verifications/#{verification_token.verification_id}/assessments")
|
|
29
|
-
headers = {
|
|
30
|
-
"tc-authorization" => access_token,
|
|
31
|
-
"tc-library-language" => "ruby",
|
|
32
|
-
"tc-library-version" => "2.0"
|
|
33
|
-
}
|
|
34
|
-
response = Net::HTTP.get_response(url, headers)
|
|
35
|
-
|
|
36
|
-
case response.code.to_i
|
|
37
|
-
when 403
|
|
38
|
-
raise SecretKeyInvalidException, "Secret key is invalid"
|
|
39
|
-
when 404
|
|
40
|
-
raise VerificationNotFoundException, "Verification not found"
|
|
41
|
-
when 423
|
|
42
|
-
raise VerificationNotFinishedException, "Verification not finished"
|
|
43
|
-
else
|
|
44
|
-
raise "Failed to retrieve verification result: HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
VerificationResult.from_json(response.body)
|
|
48
|
-
end
|
|
49
|
-
end
|