noresponse 2.0.17
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 +7 -0
- data/lib/crystalline/enum.rbi +17 -0
- data/lib/crystalline/metadata_fields.rb +263 -0
- data/lib/crystalline/module.rb +186 -0
- data/lib/crystalline/types.rb +168 -0
- data/lib/crystalline/utils.rb +67 -0
- data/lib/crystalline.rb +11 -0
- data/lib/no_response/assessments.rb +1252 -0
- data/lib/no_response/auth.rb +263 -0
- data/lib/no_response/issued_credential.rb +21 -0
- data/lib/no_response/keys.rb +318 -0
- data/lib/no_response/late_results.rb +301 -0
- data/lib/no_response/models/callbacks.rb +10 -0
- data/lib/no_response/models/errors/apistatuserror.rb +41 -0
- data/lib/no_response/models/errors/apistatuserror.rbi +30 -0
- data/lib/no_response/models/errors/authenticationerror.rb +108 -0
- data/lib/no_response/models/errors/authenticationerror.rbi +56 -0
- data/lib/no_response/models/errors/badrequesterror.rb +108 -0
- data/lib/no_response/models/errors/badrequesterror.rbi +56 -0
- data/lib/no_response/models/errors/conflicterror.rb +108 -0
- data/lib/no_response/models/errors/conflicterror.rbi +56 -0
- data/lib/no_response/models/errors/notfounderror.rb +108 -0
- data/lib/no_response/models/errors/notfounderror.rbi +56 -0
- data/lib/no_response/models/errors/permissiondeniederror.rb +108 -0
- data/lib/no_response/models/errors/permissiondeniederror.rbi +56 -0
- data/lib/no_response/models/errors/ratelimiterror.rb +108 -0
- data/lib/no_response/models/errors/ratelimiterror.rbi +56 -0
- data/lib/no_response/models/errors.rb +16 -0
- data/lib/no_response/models/operations/createassessment_request.rb +36 -0
- data/lib/no_response/models/operations/createassessment_request.rbi +20 -0
- data/lib/no_response/models/operations/createassessment_response.rb +32 -0
- data/lib/no_response/models/operations/createassessment_response.rbi +20 -0
- data/lib/no_response/models/operations/getassessment_request.rb +41 -0
- data/lib/no_response/models/operations/getassessment_request.rbi +20 -0
- data/lib/no_response/models/operations/getassessment_response.rb +32 -0
- data/lib/no_response/models/operations/getassessment_response.rbi +20 -0
- data/lib/no_response/models/operations/queryaccountassessments_response.rb +44 -0
- data/lib/no_response/models/operations/queryaccountassessments_response.rbi +20 -0
- data/lib/no_response/models/operations/recordassessmentoutcome_request.rb +52 -0
- data/lib/no_response/models/operations/recordassessmentoutcome_request.rbi +26 -0
- data/lib/no_response/models/operations/recordassessmentoutcome_response.rb +32 -0
- data/lib/no_response/models/operations/recordassessmentoutcome_response.rbi +20 -0
- data/lib/no_response/models/operations/rotateapikey_response.rb +32 -0
- data/lib/no_response/models/operations/rotateapikey_response.rbi +20 -0
- data/lib/no_response/models/operations.rb +17 -0
- data/lib/no_response/models/shared/alternate_name.rb +23 -0
- data/lib/no_response/models/shared/alternate_name.rbi +9 -0
- data/lib/no_response/models/shared/alternate_name_union.rb +23 -0
- data/lib/no_response/models/shared/alternate_name_union.rbi +9 -0
- data/lib/no_response/models/shared/assessment.rb +235 -0
- data/lib/no_response/models/shared/assessment.rbi +116 -0
- data/lib/no_response/models/shared/assessmentlist.rb +78 -0
- data/lib/no_response/models/shared/assessmentlist.rbi +38 -0
- data/lib/no_response/models/shared/assessmentoutcome.rb +61 -0
- data/lib/no_response/models/shared/assessmentoutcome.rbi +32 -0
- data/lib/no_response/models/shared/assessmentoutcomerequest.rb +71 -0
- data/lib/no_response/models/shared/assessmentoutcomerequest.rbi +32 -0
- data/lib/no_response/models/shared/assessmentquery.rb +70 -0
- data/lib/no_response/models/shared/assessmentquery.rbi +32 -0
- data/lib/no_response/models/shared/assessmentrequest.rb +125 -0
- data/lib/no_response/models/shared/assessmentrequest.rbi +62 -0
- data/lib/no_response/models/shared/assessmentrequestclientcontext.rb +125 -0
- data/lib/no_response/models/shared/assessmentrequestclientcontext.rbi +62 -0
- data/lib/no_response/models/shared/assessmentrequestidentifiers.rb +74 -0
- data/lib/no_response/models/shared/assessmentrequestidentifiers.rbi +38 -0
- data/lib/no_response/models/shared/assessmentrequestissuedcredential.rb +33 -0
- data/lib/no_response/models/shared/assessmentrequestissuedcredential.rbi +14 -0
- data/lib/no_response/models/shared/assessmentrequestpolicycontext.rb +46 -0
- data/lib/no_response/models/shared/assessmentrequestpolicycontext.rbi +20 -0
- data/lib/no_response/models/shared/assessmenttiming.rb +41 -0
- data/lib/no_response/models/shared/assessmenttiming.rbi +20 -0
- data/lib/no_response/models/shared/assurancelevel.rb +18 -0
- data/lib/no_response/models/shared/assurancelevel.rbi +9 -0
- data/lib/no_response/models/shared/authcontext.rb +285 -0
- data/lib/no_response/models/shared/authcontext.rbi +152 -0
- data/lib/no_response/models/shared/authcontextmfa.rb +55 -0
- data/lib/no_response/models/shared/authcontextmfa.rbi +26 -0
- data/lib/no_response/models/shared/authenticationerrorcode.rb +18 -0
- data/lib/no_response/models/shared/authenticationerrorcode.rbi +9 -0
- data/lib/no_response/models/shared/badrequesterrorcode.rb +20 -0
- data/lib/no_response/models/shared/badrequesterrorcode.rbi +9 -0
- data/lib/no_response/models/shared/band.rb +21 -0
- data/lib/no_response/models/shared/band.rbi +9 -0
- data/lib/no_response/models/shared/breach.rb +108 -0
- data/lib/no_response/models/shared/breach.rbi +56 -0
- data/lib/no_response/models/shared/breachexposed.rb +28 -0
- data/lib/no_response/models/shared/breachexposed.rbi +9 -0
- data/lib/no_response/models/shared/breachkind.rb +24 -0
- data/lib/no_response/models/shared/breachkind.rbi +9 -0
- data/lib/no_response/models/shared/breachselector.rb +20 -0
- data/lib/no_response/models/shared/breachselector.rbi +9 -0
- data/lib/no_response/models/shared/breachsummary.rb +109 -0
- data/lib/no_response/models/shared/breachsummary.rbi +56 -0
- data/lib/no_response/models/shared/confidence.rb +21 -0
- data/lib/no_response/models/shared/confidence.rbi +9 -0
- data/lib/no_response/models/shared/conflicterrorcode.rb +19 -0
- data/lib/no_response/models/shared/conflicterrorcode.rbi +9 -0
- data/lib/no_response/models/shared/consistency.rb +85 -0
- data/lib/no_response/models/shared/consistency.rbi +32 -0
- data/lib/no_response/models/shared/consistencyvalue.rb +21 -0
- data/lib/no_response/models/shared/consistencyvalue.rbi +9 -0
- data/lib/no_response/models/shared/country.rb +20 -0
- data/lib/no_response/models/shared/country.rbi +9 -0
- data/lib/no_response/models/shared/email.rb +23 -0
- data/lib/no_response/models/shared/email.rbi +9 -0
- data/lib/no_response/models/shared/email_union.rb +23 -0
- data/lib/no_response/models/shared/email_union.rbi +9 -0
- data/lib/no_response/models/shared/failurereason.rb +24 -0
- data/lib/no_response/models/shared/failurereason.rbi +9 -0
- data/lib/no_response/models/shared/flow.rb +18 -0
- data/lib/no_response/models/shared/flow.rbi +9 -0
- data/lib/no_response/models/shared/freshness.rb +20 -0
- data/lib/no_response/models/shared/freshness.rbi +9 -0
- data/lib/no_response/models/shared/hookpoint.rb +19 -0
- data/lib/no_response/models/shared/hookpoint.rbi +9 -0
- data/lib/no_response/models/shared/identifierkind.rb +21 -0
- data/lib/no_response/models/shared/identifierkind.rbi +9 -0
- data/lib/no_response/models/shared/incompletereason.rb +23 -0
- data/lib/no_response/models/shared/incompletereason.rbi +9 -0
- data/lib/no_response/models/shared/incompletesource.rb +53 -0
- data/lib/no_response/models/shared/incompletesource.rbi +20 -0
- data/lib/no_response/models/shared/ipsummary.rb +61 -0
- data/lib/no_response/models/shared/ipsummary.rbi +26 -0
- data/lib/no_response/models/shared/ipsummarytype.rb +24 -0
- data/lib/no_response/models/shared/ipsummarytype.rbi +9 -0
- data/lib/no_response/models/shared/keyrotation.rb +79 -0
- data/lib/no_response/models/shared/keyrotation.rbi +44 -0
- data/lib/no_response/models/shared/keyrotationrequest.rb +33 -0
- data/lib/no_response/models/shared/keyrotationrequest.rbi +14 -0
- data/lib/no_response/models/shared/lane.rb +21 -0
- data/lib/no_response/models/shared/lane.rbi +9 -0
- data/lib/no_response/models/shared/linetype.rb +22 -0
- data/lib/no_response/models/shared/linetype.rbi +9 -0
- data/lib/no_response/models/shared/location.rb +23 -0
- data/lib/no_response/models/shared/location.rbi +9 -0
- data/lib/no_response/models/shared/location_union.rb +23 -0
- data/lib/no_response/models/shared/location_union.rbi +9 -0
- data/lib/no_response/models/shared/name_candidate.rb +23 -0
- data/lib/no_response/models/shared/name_candidate.rbi +9 -0
- data/lib/no_response/models/shared/name_candidate_union.rb +23 -0
- data/lib/no_response/models/shared/name_candidate_union.rbi +9 -0
- data/lib/no_response/models/shared/notfounderrorcode.rb +18 -0
- data/lib/no_response/models/shared/notfounderrorcode.rbi +9 -0
- data/lib/no_response/models/shared/outcome.rb +23 -0
- data/lib/no_response/models/shared/outcome.rbi +9 -0
- data/lib/no_response/models/shared/permissiondeniederrorcode.rb +18 -0
- data/lib/no_response/models/shared/permissiondeniederrorcode.rbi +9 -0
- data/lib/no_response/models/shared/phoneenrichment.rb +32 -0
- data/lib/no_response/models/shared/phoneenrichment.rbi +14 -0
- data/lib/no_response/models/shared/phoneenrichmentfields.rb +451 -0
- data/lib/no_response/models/shared/phoneenrichmentfields.rbi +212 -0
- data/lib/no_response/models/shared/platform.rb +18 -0
- data/lib/no_response/models/shared/platform.rbi +9 -0
- data/lib/no_response/models/shared/probleminvalidparam.rb +48 -0
- data/lib/no_response/models/shared/probleminvalidparam.rbi +26 -0
- data/lib/no_response/models/shared/ratelimiterrorcode.rb +18 -0
- data/lib/no_response/models/shared/ratelimiterrorcode.rbi +9 -0
- data/lib/no_response/models/shared/reasoncode.rb +52 -0
- data/lib/no_response/models/shared/reasoncode.rbi +9 -0
- data/lib/no_response/models/shared/reasonidentifier.rb +23 -0
- data/lib/no_response/models/shared/reasonidentifier.rbi +9 -0
- data/lib/no_response/models/shared/recommendation.rb +20 -0
- data/lib/no_response/models/shared/recommendation.rbi +9 -0
- data/lib/no_response/models/shared/responsemode.rb +16 -0
- data/lib/no_response/models/shared/responsemode.rbi +9 -0
- data/lib/no_response/models/shared/risk.rb +171 -0
- data/lib/no_response/models/shared/risk.rbi +80 -0
- data/lib/no_response/models/shared/riskconfidence.rb +20 -0
- data/lib/no_response/models/shared/riskconfidence.rbi +9 -0
- data/lib/no_response/models/shared/riskcoverage.rb +49 -0
- data/lib/no_response/models/shared/riskcoverage.rbi +26 -0
- data/lib/no_response/models/shared/riskdetails.rb +55 -0
- data/lib/no_response/models/shared/riskdetails.rbi +26 -0
- data/lib/no_response/models/shared/riskdetailsbreachname.rb +40 -0
- data/lib/no_response/models/shared/riskdetailsbreachname.rbi +20 -0
- data/lib/no_response/models/shared/riskdetailsphonename.rb +40 -0
- data/lib/no_response/models/shared/riskdetailsphonename.rbi +20 -0
- data/lib/no_response/models/shared/riskreason.rb +67 -0
- data/lib/no_response/models/shared/riskreason.rbi +26 -0
- data/lib/no_response/models/shared/risksummary.rb +73 -0
- data/lib/no_response/models/shared/risksummary.rbi +38 -0
- data/lib/no_response/models/shared/risksummaryemail.rb +55 -0
- data/lib/no_response/models/shared/risksummaryemail.rbi +26 -0
- data/lib/no_response/models/shared/risksummaryphone.rb +69 -0
- data/lib/no_response/models/shared/risksummaryphone.rbi +32 -0
- data/lib/no_response/models/shared/risksummaryusername.rb +41 -0
- data/lib/no_response/models/shared/risksummaryusername.rbi +20 -0
- data/lib/no_response/models/shared/scope.rb +21 -0
- data/lib/no_response/models/shared/scope.rbi +9 -0
- data/lib/no_response/models/shared/security.rb +32 -0
- data/lib/no_response/models/shared/security.rbi +14 -0
- data/lib/no_response/models/shared/signal.rb +149 -0
- data/lib/no_response/models/shared/signal.rbi +68 -0
- data/lib/no_response/models/shared/signaloutcome.rb +22 -0
- data/lib/no_response/models/shared/signaloutcome.rbi +9 -0
- data/lib/no_response/models/shared/social_profile.rb +23 -0
- data/lib/no_response/models/shared/social_profile.rbi +9 -0
- data/lib/no_response/models/shared/social_profile_union.rb +23 -0
- data/lib/no_response/models/shared/social_profile_union.rbi +9 -0
- data/lib/no_response/models/shared/status.rb +20 -0
- data/lib/no_response/models/shared/status.rbi +9 -0
- data/lib/no_response/models/shared/timezone.rb +23 -0
- data/lib/no_response/models/shared/timezone.rbi +9 -0
- data/lib/no_response/models/shared/timezone_union.rb +23 -0
- data/lib/no_response/models/shared/timezone_union.rbi +9 -0
- data/lib/no_response/models/shared/transport.rb +17 -0
- data/lib/no_response/models/shared/transport.rbi +9 -0
- data/lib/no_response/models/shared/website.rb +23 -0
- data/lib/no_response/models/shared/website.rbi +9 -0
- data/lib/no_response/models/shared/website_union.rb +23 -0
- data/lib/no_response/models/shared/website_union.rbi +9 -0
- data/lib/no_response/models/shared.rb +92 -0
- data/lib/no_response/noresponseclient.rb +110 -0
- data/lib/no_response/sdk_hooks/hooks.rb +97 -0
- data/lib/no_response/sdk_hooks/idempotency_key_hook.rb +25 -0
- data/lib/no_response/sdk_hooks/registration.rb +43 -0
- data/lib/no_response/sdk_hooks/types.rb +178 -0
- data/lib/no_response/sdkconfiguration.rb +107 -0
- data/lib/no_response/sdkconfiguration.rbi +83 -0
- data/lib/no_response/utils/forms.rb +230 -0
- data/lib/no_response/utils/headers.rb +80 -0
- data/lib/no_response/utils/query_params.rb +165 -0
- data/lib/no_response/utils/request_bodies.rb +77 -0
- data/lib/no_response/utils/retries.rb +137 -0
- data/lib/no_response/utils/security.rb +156 -0
- data/lib/no_response/utils/url.rb +122 -0
- data/lib/no_response/utils/utils.rb +243 -0
- data/lib/no_response/wait.rb +66 -0
- data/lib/no_response/webhooks.rb +177 -0
- data/lib/noresponse.rb +25 -0
- metadata +501 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Webhook verification. Hand-written beside the generated client.
|
|
5
|
+
#
|
|
6
|
+
# Verify the exact bytes received: the signature is HMAC-SHA256 over
|
|
7
|
+
# "<timestamp>.<raw body>", so re-serialising parsed JSON breaks it.
|
|
8
|
+
|
|
9
|
+
require 'json'
|
|
10
|
+
require 'openssl'
|
|
11
|
+
require 'time'
|
|
12
|
+
|
|
13
|
+
module NoResponse
|
|
14
|
+
module Webhooks
|
|
15
|
+
DEFAULT_TOLERANCE_SECONDS = 300
|
|
16
|
+
|
|
17
|
+
REQUIRED = %w[nr-webhook-id nr-webhook-timestamp nr-webhook-key-id nr-webhook-signature].freeze
|
|
18
|
+
KEY_ID = /\Awhk_[A-Za-z0-9]{8,64}\z/
|
|
19
|
+
SIGNATURE = /\Av1=[0-9a-f]{64}\z/
|
|
20
|
+
TIMESTAMP = /\A[0-9]{1,12}\z/
|
|
21
|
+
CHALLENGE = /\A[A-Za-z0-9_-]{43}\z/
|
|
22
|
+
EVENT_ID = /\Aevt_[0-9A-HJKMNP-TV-Z]{26}\z/
|
|
23
|
+
ASSESSMENT_ID = /\Aasm_[0-9A-HJKMNP-TV-Z]{26}\z/
|
|
24
|
+
ACCOUNT_ID = /\A[A-Za-z0-9][A-Za-z0-9._:|-]{0,127}\z/
|
|
25
|
+
ENDPOINT_ID = /\Awhe_[0-9A-HJKMNP-TV-Z]{26}\z/
|
|
26
|
+
|
|
27
|
+
# Raised by construct_event. Answer 400 and do not process the delivery.
|
|
28
|
+
# code is one of :missing_header, :duplicate_header, :invalid_timestamp,
|
|
29
|
+
# :unknown_key, :invalid_signature or :invalid_payload.
|
|
30
|
+
class VerificationError < StandardError
|
|
31
|
+
attr_reader :code
|
|
32
|
+
|
|
33
|
+
def initialize(code, message)
|
|
34
|
+
super(message)
|
|
35
|
+
@code = code
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# The final event for an assessment: it has expired and get now answers
|
|
40
|
+
# 404. assessment_version is the last served version.
|
|
41
|
+
AssessmentExpired = Struct.new(:assessment_id, :account_id, :assessment_version, keyword_init: true) do
|
|
42
|
+
def status = 'expired'
|
|
43
|
+
def change_reason = 'expired'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
EndpointVerification = Struct.new(:endpoint_id, :challenge, keyword_init: true)
|
|
47
|
+
|
|
48
|
+
# A verified delivery. data is a Models::Shared::Assessment (exactly as
|
|
49
|
+
# assessments.get returns it) or an AssessmentExpired for type
|
|
50
|
+
# "assessment.updated", and an EndpointVerification for
|
|
51
|
+
# "endpoint.verification". Deliveries are at least once and unordered:
|
|
52
|
+
# deduplicate on id and keep the highest assessment_version.
|
|
53
|
+
Event = Struct.new(:id, :type, :created_at, :data, keyword_init: true) do
|
|
54
|
+
# True for the terminal expiry event: delete what you hold and fetch nothing.
|
|
55
|
+
def expired? = data.is_a?(AssessmentExpired)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class << self
|
|
59
|
+
|
|
60
|
+
# Verify one delivery and return the typed Event.
|
|
61
|
+
#
|
|
62
|
+
# payload is the raw request body. headers is a Hash, Rack env-style
|
|
63
|
+
# pairs or any object with each; each NR-Webhook-* header must appear
|
|
64
|
+
# exactly once, in any letter case. secrets maps each whk_ key id
|
|
65
|
+
# NoResponse gave you to its secret; hold both during a rotation.
|
|
66
|
+
def construct_event(payload, headers, secrets, tolerance_seconds: DEFAULT_TOLERANCE_SECONDS, now: Time.now.to_i)
|
|
67
|
+
raw = payload.to_s.b
|
|
68
|
+
found = collect(headers)
|
|
69
|
+
timestamp = found['nr-webhook-timestamp']
|
|
70
|
+
if !TIMESTAMP.match?(timestamp) || (now.to_i - timestamp.to_i).abs > tolerance_seconds
|
|
71
|
+
raise VerificationError.new(:invalid_timestamp, 'Webhook timestamp is outside the replay window')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
key_id = found['nr-webhook-key-id']
|
|
75
|
+
unless KEY_ID.match?(key_id) && secrets.key?(key_id)
|
|
76
|
+
raise VerificationError.new(:unknown_key, 'Webhook key id is not one this receiver holds')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
signature = found['nr-webhook-signature']
|
|
80
|
+
raise VerificationError.new(:invalid_signature, 'Webhook signature is malformed') unless SIGNATURE.match?(signature)
|
|
81
|
+
|
|
82
|
+
expected = OpenSSL::HMAC.hexdigest('SHA256', secrets.fetch(key_id).to_s, "#{timestamp}.".b + raw)
|
|
83
|
+
unless OpenSSL.fixed_length_secure_compare(expected, signature.delete_prefix('v1='))
|
|
84
|
+
raise VerificationError.new(:invalid_signature, 'Webhook signature does not match')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
event(raw, found['nr-webhook-id'])
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# The body to answer an endpoint.verification event with, as JSON, status 200.
|
|
91
|
+
def verification_response(event)
|
|
92
|
+
unless event.data.is_a?(EndpointVerification)
|
|
93
|
+
raise VerificationError.new(:invalid_payload, 'Not an endpoint.verification event')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
{ 'challenge' => event.data.challenge }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def collect(headers)
|
|
102
|
+
found = {}
|
|
103
|
+
headers.each do |name, value|
|
|
104
|
+
key = name.to_s.downcase.tr('_', '-').delete_prefix('http-')
|
|
105
|
+
next unless REQUIRED.include?(key)
|
|
106
|
+
|
|
107
|
+
values = Array(value)
|
|
108
|
+
if values.length != 1 || found.key?(key)
|
|
109
|
+
raise VerificationError.new(:duplicate_header, "Webhook header #{key} is repeated")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
found[key] = values.first.to_s
|
|
113
|
+
end
|
|
114
|
+
REQUIRED.each do |key|
|
|
115
|
+
raise VerificationError.new(:missing_header, "Webhook header #{key} is missing") if found[key].to_s.empty?
|
|
116
|
+
end
|
|
117
|
+
found
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def event(raw, header_id)
|
|
121
|
+
body = begin
|
|
122
|
+
JSON.parse(raw)
|
|
123
|
+
rescue JSON::ParserError
|
|
124
|
+
raise VerificationError.new(:invalid_payload, 'Webhook body is not JSON')
|
|
125
|
+
end
|
|
126
|
+
unless body.is_a?(Hash) && body['id'] == header_id && EVENT_ID.match?(body['id'].to_s)
|
|
127
|
+
raise VerificationError.new(:invalid_payload, 'Webhook event id does not match NR-Webhook-Id')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
data = body['data']
|
|
131
|
+
unless body['created_at'].is_a?(String) && valid_datetime?(body['created_at']) && data.is_a?(Hash)
|
|
132
|
+
raise VerificationError.new(:invalid_payload, 'Webhook event envelope is malformed')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
Event.new(id: body['id'], type: body['type'], created_at: body['created_at'], data: event_data(body['type'], data))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def event_data(type, data)
|
|
139
|
+
case type
|
|
140
|
+
when 'endpoint.verification'
|
|
141
|
+
unless ENDPOINT_ID.match?(data['endpoint_id'].to_s) && CHALLENGE.match?(data['challenge'].to_s)
|
|
142
|
+
raise VerificationError.new(:invalid_payload, 'Endpoint verification event is malformed')
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
EndpointVerification.new(endpoint_id: data['endpoint_id'], challenge: data['challenge'])
|
|
146
|
+
when 'assessment.updated'
|
|
147
|
+
return expired(data) if data['status'] == 'expired'
|
|
148
|
+
begin
|
|
149
|
+
Crystalline.unmarshal_json(data, Models::Shared::Assessment)
|
|
150
|
+
rescue KeyError, TypeError, ArgumentError, NoMethodError
|
|
151
|
+
raise VerificationError.new(:invalid_payload, 'Webhook data is not an assessment')
|
|
152
|
+
end
|
|
153
|
+
else
|
|
154
|
+
raise VerificationError.new(:invalid_payload, 'Unknown webhook event type')
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def expired(data)
|
|
159
|
+
unless ASSESSMENT_ID.match?(data['assessment_id'].to_s) &&
|
|
160
|
+
ACCOUNT_ID.match?(data['account_id'].to_s) && data['assessment_version'].is_a?(Integer) &&
|
|
161
|
+
data['assessment_version'] >= 1 && data['status'] == 'expired' && data['change_reason'] == 'expired'
|
|
162
|
+
raise VerificationError.new(:invalid_payload, 'Expired assessment event is malformed')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
AssessmentExpired.new(assessment_id: data['assessment_id'], account_id: data['account_id'],
|
|
166
|
+
assessment_version: data['assessment_version'])
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def valid_datetime?(value)
|
|
170
|
+
Time.iso8601(value)
|
|
171
|
+
true
|
|
172
|
+
rescue ArgumentError
|
|
173
|
+
false
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
data/lib/noresponse.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
autoload :NoResponseClient, "no_response/noresponseclient"
|
|
6
|
+
autoload :Assessments, "no_response/assessments"
|
|
7
|
+
autoload :Keys, "no_response/keys"
|
|
8
|
+
|
|
9
|
+
module Models
|
|
10
|
+
autoload :Shared, "no_response/models/shared"
|
|
11
|
+
autoload :Operations, "no_response/models/operations"
|
|
12
|
+
autoload :Errors, "no_response/models/errors"
|
|
13
|
+
autoload :Callbacks, "no_response/models/callbacks"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require_relative "no_response/utils/utils"
|
|
18
|
+
require_relative "no_response/utils/request_bodies"
|
|
19
|
+
require_relative "no_response/utils/query_params"
|
|
20
|
+
require_relative "no_response/utils/forms"
|
|
21
|
+
require_relative "no_response/utils/headers"
|
|
22
|
+
require_relative "no_response/utils/url"
|
|
23
|
+
require_relative "no_response/utils/security"
|
|
24
|
+
require_relative "crystalline"
|
|
25
|
+
require_relative "no_response/sdkconfiguration"
|