noresponse 5.1.1 → 6.0.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/no_response/late_results.rb +10 -8
- data/lib/no_response/models/shared/accountdeleted.rb +49 -0
- data/lib/no_response/models/shared/accountdeleted.rbi +26 -0
- data/lib/no_response/models/shared/accountdeletedevent.rb +70 -0
- data/lib/no_response/models/shared/accountdeletedevent.rbi +38 -0
- data/lib/no_response/models/shared/accountriskchanged.rb +44 -0
- data/lib/no_response/models/shared/accountriskchanged.rbi +20 -0
- data/lib/no_response/models/shared/accountriskchangedevent.rb +70 -0
- data/lib/no_response/models/shared/accountriskchangedevent.rbi +38 -0
- data/lib/no_response/models/shared/assessmentexpired.rb +82 -0
- data/lib/no_response/models/shared/assessmentexpired.rbi +38 -0
- data/lib/no_response/models/shared/assessmentupdateddata.rb +23 -0
- data/lib/no_response/models/shared/assessmentupdateddata.rbi +9 -0
- data/lib/no_response/models/shared/assessmentupdatedevent.rb +79 -0
- data/lib/no_response/models/shared/assessmentupdatedevent.rbi +38 -0
- data/lib/no_response/models/shared/endpointverification.rb +41 -0
- data/lib/no_response/models/shared/endpointverification.rbi +20 -0
- data/lib/no_response/models/shared/endpointverificationevent.rb +70 -0
- data/lib/no_response/models/shared/endpointverificationevent.rbi +38 -0
- data/lib/no_response/models/shared/environment.rb +16 -0
- data/lib/no_response/models/shared/environment.rbi +9 -0
- data/lib/no_response/models/shared/webhookendpointdisabled.rb +49 -0
- data/lib/no_response/models/shared/webhookendpointdisabled.rbi +26 -0
- data/lib/no_response/models/shared/webhookendpointdisabledevent.rb +70 -0
- data/lib/no_response/models/shared/webhookendpointdisabledevent.rbi +38 -0
- data/lib/no_response/models/shared/webhookevent.rb +23 -0
- data/lib/no_response/models/shared/webhookevent.rbi +9 -0
- data/lib/no_response/models/shared/webhookverificationresponse.rb +33 -0
- data/lib/no_response/models/shared/webhookverificationresponse.rbi +14 -0
- data/lib/no_response/models/shared/workspacedeleted.rb +55 -0
- data/lib/no_response/models/shared/workspacedeleted.rbi +26 -0
- data/lib/no_response/models/shared/workspacedeletedevent.rb +70 -0
- data/lib/no_response/models/shared/workspacedeletedevent.rbi +38 -0
- data/lib/no_response/models/shared.rb +16 -0
- data/lib/no_response/sdk_hooks/registration.rb +0 -1
- data/lib/no_response/sdkconfiguration.rb +2 -2
- data/lib/no_response/webhook_verification.rb +170 -0
- data/lib/noresponse.rb +2 -0
- metadata +34 -2
- data/lib/no_response/webhooks.rb +0 -264
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# The workspace.deleted event.
|
|
8
|
+
class WorkspaceDeletedEvent
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# The event id, equal to the NR-Webhook-Id header and across redeliveries and every endpoint the event fans out to.
|
|
13
|
+
field :id, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("id"), required: true}}
|
|
14
|
+
# When the event was created. Equal across redeliveries; the signing timestamp header is per delivery.
|
|
15
|
+
field(
|
|
16
|
+
:created_at,
|
|
17
|
+
::String,
|
|
18
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("created_at"), required: true}}
|
|
19
|
+
)
|
|
20
|
+
# Terminal for the receiving endpoint's environment: its workspace was deleted. Every key of the environment already answers 401, its assessments and accounts are gone, and no further event follows. The workspace id is not reused, so a later event naming it cannot arrive.
|
|
21
|
+
field(
|
|
22
|
+
:data,
|
|
23
|
+
Models::Shared::WorkspaceDeleted,
|
|
24
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("data"), required: true}}
|
|
25
|
+
)
|
|
26
|
+
# Always workspace.deleted.
|
|
27
|
+
field :type, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("type"), required: true}}
|
|
28
|
+
# Present, and true, only on an event sent by POST /v1/webhooks/{endpoint_id}/test: its data is a fixed example assessment, not one of the workspace's, so a receiver acknowledges it and applies nothing. Real events have no test member.
|
|
29
|
+
field(
|
|
30
|
+
:test,
|
|
31
|
+
Crystalline::Nilable.new(Crystalline::Boolean.new),
|
|
32
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("test")}}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
sig {
|
|
36
|
+
params(
|
|
37
|
+
id: ::String,
|
|
38
|
+
created_at: ::String,
|
|
39
|
+
data: Models::Shared::WorkspaceDeleted,
|
|
40
|
+
type: ::String,
|
|
41
|
+
test: T.nilable(T::Boolean)
|
|
42
|
+
)
|
|
43
|
+
.void
|
|
44
|
+
}
|
|
45
|
+
def initialize(id:, created_at:, data:, type: "workspace.deleted", test: nil)
|
|
46
|
+
@id = id
|
|
47
|
+
@created_at = created_at
|
|
48
|
+
@data = data
|
|
49
|
+
unless type == "workspace.deleted"
|
|
50
|
+
raise ArgumentError, "Invalid value for type"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@type = "workspace.deleted"
|
|
54
|
+
@test = test
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
58
|
+
def ==(other)
|
|
59
|
+
return false unless other.is_a?(self.class)
|
|
60
|
+
return false unless @id == other.id
|
|
61
|
+
return false unless @created_at == other.created_at
|
|
62
|
+
return false unless @data == other.data
|
|
63
|
+
return false unless @type == other.type
|
|
64
|
+
return false unless @test == other.test
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::WorkspaceDeletedEvent
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::WorkspaceDeletedEvent
|
|
9
|
+
def id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def created_at
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def created_at=(str_)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def data
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def data=(str_)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def type
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def type=(str_)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test=(str_)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -7,8 +7,12 @@ module NoResponse
|
|
|
7
7
|
autoload :Account, "no_response/models/shared/account.rb"
|
|
8
8
|
autoload :AccountDecision, "no_response/models/shared/accountdecision.rb"
|
|
9
9
|
autoload :AccountDecisionsByFlow, "no_response/models/shared/accountdecisionsbyflow.rb"
|
|
10
|
+
autoload :AccountDeleted, "no_response/models/shared/accountdeleted.rb"
|
|
11
|
+
autoload :AccountDeletedEvent, "no_response/models/shared/accountdeletedevent.rb"
|
|
10
12
|
autoload :AccountDeletion, "no_response/models/shared/accountdeletion.rb"
|
|
11
13
|
autoload :AccountRisk, "no_response/models/shared/accountrisk.rb"
|
|
14
|
+
autoload :AccountRiskChanged, "no_response/models/shared/accountriskchanged.rb"
|
|
15
|
+
autoload :AccountRiskChangedEvent, "no_response/models/shared/accountriskchangedevent.rb"
|
|
12
16
|
autoload :AccountRiskReason, "no_response/models/shared/accountriskreason.rb"
|
|
13
17
|
autoload :Assessment, "no_response/models/shared/assessment.rb"
|
|
14
18
|
autoload :AssessmentDeletion, "no_response/models/shared/assessmentdeletion.rb"
|
|
@@ -16,6 +20,7 @@ module NoResponse
|
|
|
16
20
|
autoload :AssessmentDetail, "no_response/models/shared/assessmentdetail.rb"
|
|
17
21
|
autoload :AssessmentDetailAuthContext, "no_response/models/shared/assessmentdetailauthcontext.rb"
|
|
18
22
|
autoload :AssessmentDetailTiming, "no_response/models/shared/assessmentdetailtiming.rb"
|
|
23
|
+
autoload :AssessmentExpired, "no_response/models/shared/assessmentexpired.rb"
|
|
19
24
|
autoload :AssessmentList, "no_response/models/shared/assessmentlist.rb"
|
|
20
25
|
autoload :AssessmentOutcome, "no_response/models/shared/assessmentoutcome.rb"
|
|
21
26
|
autoload :AssessmentOutcomeRequest, "no_response/models/shared/assessmentoutcomerequest.rb"
|
|
@@ -25,6 +30,8 @@ module NoResponse
|
|
|
25
30
|
autoload :AssessmentRequestIdentifiers, "no_response/models/shared/assessmentrequestidentifiers.rb"
|
|
26
31
|
autoload :AssessmentRequestIssuedCredential, "no_response/models/shared/assessmentrequestissuedcredential.rb"
|
|
27
32
|
autoload :AssessmentRequestPolicyContext, "no_response/models/shared/assessmentrequestpolicycontext.rb"
|
|
33
|
+
autoload :AssessmentUpdatedData, "no_response/models/shared/assessmentupdateddata.rb"
|
|
34
|
+
autoload :AssessmentUpdatedEvent, "no_response/models/shared/assessmentupdatedevent.rb"
|
|
28
35
|
autoload :AssuranceLevel, "no_response/models/shared/assurancelevel.rb"
|
|
29
36
|
autoload :AuthContext, "no_response/models/shared/authcontext.rb"
|
|
30
37
|
autoload :AuthContextMfa, "no_response/models/shared/authcontextmfa.rb"
|
|
@@ -42,6 +49,9 @@ module NoResponse
|
|
|
42
49
|
autoload :ConsistencyValue, "no_response/models/shared/consistencyvalue.rb"
|
|
43
50
|
autoload :Country, "no_response/models/shared/country.rb"
|
|
44
51
|
autoload :Depth, "no_response/models/shared/depth.rb"
|
|
52
|
+
autoload :EndpointVerification, "no_response/models/shared/endpointverification.rb"
|
|
53
|
+
autoload :EndpointVerificationEvent, "no_response/models/shared/endpointverificationevent.rb"
|
|
54
|
+
autoload :Environment, "no_response/models/shared/environment.rb"
|
|
45
55
|
autoload :Failure, "no_response/models/shared/failure.rb"
|
|
46
56
|
autoload :FailureReason, "no_response/models/shared/failurereason.rb"
|
|
47
57
|
autoload :Flow, "no_response/models/shared/flow.rb"
|
|
@@ -100,9 +110,12 @@ module NoResponse
|
|
|
100
110
|
autoload :WebhookDeliveryList, "no_response/models/shared/webhookdeliverylist.rb"
|
|
101
111
|
autoload :WebhookEndpoint, "no_response/models/shared/webhookendpoint.rb"
|
|
102
112
|
autoload :WebhookEndpointCreated, "no_response/models/shared/webhookendpointcreated.rb"
|
|
113
|
+
autoload :WebhookEndpointDisabled, "no_response/models/shared/webhookendpointdisabled.rb"
|
|
114
|
+
autoload :WebhookEndpointDisabledEvent, "no_response/models/shared/webhookendpointdisabledevent.rb"
|
|
103
115
|
autoload :WebhookEndpointList, "no_response/models/shared/webhookendpointlist.rb"
|
|
104
116
|
autoload :WebhookEndpointRequest, "no_response/models/shared/webhookendpointrequest.rb"
|
|
105
117
|
autoload :WebhookEndpointState, "no_response/models/shared/webhookendpointstate.rb"
|
|
118
|
+
autoload :WebhookEvent, "no_response/models/shared/webhookevent.rb"
|
|
106
119
|
autoload :WebhookKeyRotation, "no_response/models/shared/webhookkeyrotation.rb"
|
|
107
120
|
autoload :WebhookKeyRotationRequest, "no_response/models/shared/webhookkeyrotationrequest.rb"
|
|
108
121
|
autoload :WebhookReplay, "no_response/models/shared/webhookreplay.rb"
|
|
@@ -110,6 +123,9 @@ module NoResponse
|
|
|
110
123
|
autoload :WebhookTest, "no_response/models/shared/webhooktest.rb"
|
|
111
124
|
autoload :WebhookTestRequest, "no_response/models/shared/webhooktestrequest.rb"
|
|
112
125
|
autoload :WebhookTestRequestEvent, "no_response/models/shared/webhooktestrequestevent.rb"
|
|
126
|
+
autoload :WebhookVerificationResponse, "no_response/models/shared/webhookverificationresponse.rb"
|
|
127
|
+
autoload :WorkspaceDeleted, "no_response/models/shared/workspacedeleted.rb"
|
|
128
|
+
autoload :WorkspaceDeletedEvent, "no_response/models/shared/workspacedeletedevent.rb"
|
|
113
129
|
autoload :AlternateName, "no_response/models/shared/alternate_name.rb"
|
|
114
130
|
autoload :AlternateNameUnion, "no_response/models/shared/alternate_name_union.rb"
|
|
115
131
|
autoload :Email, "no_response/models/shared/email.rb"
|
|
@@ -95,9 +95,9 @@ module NoResponse
|
|
|
95
95
|
|
|
96
96
|
@language = "ruby"
|
|
97
97
|
@openapi_doc_version = "1"
|
|
98
|
-
@sdk_version = "
|
|
98
|
+
@sdk_version = "6.0.0"
|
|
99
99
|
@gen_version = "internal"
|
|
100
|
-
@user_agent = "noresponse-sdk/ruby
|
|
100
|
+
@user_agent = "noresponse-sdk/ruby 6.0.0 internal 1 noresponse"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
sig { returns([String, T::Hash[Symbol, String]]) }
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
require "openssl"
|
|
6
|
+
|
|
7
|
+
module NoResponse
|
|
8
|
+
# Verifies webhook deliveries and parses them into typed events.
|
|
9
|
+
module WebhookVerification
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
# How far the NR-Webhook-Timestamp header may be from the receiver's clock, in seconds.
|
|
13
|
+
DEFAULT_TOLERANCE_SECONDS = 300
|
|
14
|
+
|
|
15
|
+
# Raised by construct_event for a delivery that must not be processed:
|
|
16
|
+
# answer the delivery with a 400 and do not process it. code is one of
|
|
17
|
+
# "missing_header", "duplicate_header", "invalid_timestamp", "unknown_key",
|
|
18
|
+
# "invalid_signature" or "invalid_payload".
|
|
19
|
+
class VerificationError < StandardError
|
|
20
|
+
extend T::Sig
|
|
21
|
+
|
|
22
|
+
sig { returns(String) }
|
|
23
|
+
attr_reader :code
|
|
24
|
+
|
|
25
|
+
sig { params(code: String, message: String).void }
|
|
26
|
+
def initialize(code, message)
|
|
27
|
+
super("webhook verification failed: #{message} (#{code})")
|
|
28
|
+
@code = code
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
HEADER_NAMES = [
|
|
33
|
+
"NR-Webhook-Id",
|
|
34
|
+
"NR-Webhook-Timestamp",
|
|
35
|
+
"NR-Webhook-Key-Id",
|
|
36
|
+
"NR-Webhook-Signature"
|
|
37
|
+
].freeze
|
|
38
|
+
private_constant :HEADER_NAMES
|
|
39
|
+
EVENT_TYPE = Crystalline::DiscriminatedUnion.new(
|
|
40
|
+
"type",
|
|
41
|
+
{
|
|
42
|
+
"assessment.updated" => Models::Shared::AssessmentUpdatedEvent,
|
|
43
|
+
"endpoint.verification" => Models::Shared::EndpointVerificationEvent,
|
|
44
|
+
"account.deleted" => Models::Shared::AccountDeletedEvent,
|
|
45
|
+
"workspace.deleted" => Models::Shared::WorkspaceDeletedEvent,
|
|
46
|
+
"webhook_endpoint.disabled" => Models::Shared::WebhookEndpointDisabledEvent,
|
|
47
|
+
"account.risk_changed" => Models::Shared::AccountRiskChangedEvent
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
private_constant :EVENT_TYPE
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
extend T::Sig
|
|
54
|
+
|
|
55
|
+
# Verifies a webhook delivery and parses its body.
|
|
56
|
+
#
|
|
57
|
+
# payload is the raw request body exactly as received: re-encoding parsed JSON breaks the signature.
|
|
58
|
+
# headers is a Hash, or an Array of name/value pairs, whose values are Strings or Arrays of Strings.
|
|
59
|
+
# A header repeated in any letter case, or sent as a comma-joined list, is refused.
|
|
60
|
+
# secrets maps each key id, sent in NR-Webhook-Key-Id, to its secret, so a receiver can hold two during a rotation.
|
|
61
|
+
# now is the receiver's clock (a Time or Unix seconds) used for the tolerance check.
|
|
62
|
+
sig do
|
|
63
|
+
params(
|
|
64
|
+
payload: String,
|
|
65
|
+
headers: T::Enumerable[T.untyped],
|
|
66
|
+
secrets: T::Hash[String, String],
|
|
67
|
+
tolerance_seconds: Integer,
|
|
68
|
+
now: T.nilable(T.any(Time, Integer))
|
|
69
|
+
)
|
|
70
|
+
.returns(
|
|
71
|
+
T.any(
|
|
72
|
+
Models::Shared::AssessmentUpdatedEvent,
|
|
73
|
+
Models::Shared::EndpointVerificationEvent,
|
|
74
|
+
Models::Shared::AccountDeletedEvent,
|
|
75
|
+
Models::Shared::WorkspaceDeletedEvent,
|
|
76
|
+
Models::Shared::WebhookEndpointDisabledEvent,
|
|
77
|
+
Models::Shared::AccountRiskChangedEvent
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
def construct_event(payload, headers, secrets, tolerance_seconds: DEFAULT_TOLERANCE_SECONDS, now: nil)
|
|
82
|
+
raw = payload.b
|
|
83
|
+
values = header_values(headers)
|
|
84
|
+
id = values.fetch("NR-Webhook-Id")
|
|
85
|
+
timestamp = values.fetch("NR-Webhook-Timestamp")
|
|
86
|
+
key_id = values.fetch("NR-Webhook-Key-Id")
|
|
87
|
+
signature = values.fetch("NR-Webhook-Signature")
|
|
88
|
+
|
|
89
|
+
unless timestamp.match?(/\A[0-9]{1,12}\z/)
|
|
90
|
+
raise VerificationError.new("invalid_timestamp", "NR-Webhook-Timestamp is not a Unix time in seconds")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if ((now || Time.now).to_i - timestamp.to_i).abs > tolerance_seconds
|
|
94
|
+
raise VerificationError.new("invalid_timestamp", "NR-Webhook-Timestamp is outside the tolerance")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
unless secrets.key?(key_id)
|
|
98
|
+
raise VerificationError.new("unknown_key", "NR-Webhook-Key-Id names a key this receiver does not hold")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
secret = secrets.fetch(key_id)
|
|
102
|
+
raise VerificationError.new("invalid_signature", "the webhook secret is empty") if secret.empty?
|
|
103
|
+
|
|
104
|
+
received = decode_signature(signature)
|
|
105
|
+
substitutions = {"{timestamp}" => timestamp, "{id}" => id}
|
|
106
|
+
signed = "{timestamp}.".gsub(/\{(?:timestamp|id)\}/, substitutions).b + raw
|
|
107
|
+
expected = OpenSSL::HMAC.digest("SHA256", secret, signed)
|
|
108
|
+
unless received.bytesize == expected.bytesize && OpenSSL.fixed_length_secure_compare(expected, received)
|
|
109
|
+
raise VerificationError.new("invalid_signature", "NR-Webhook-Signature does not match")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
body = begin
|
|
113
|
+
JSON.parse(raw)
|
|
114
|
+
rescue JSON::ParserError, EncodingError
|
|
115
|
+
raise VerificationError.new("invalid_payload", "the body is not JSON")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
unless body.is_a?(::Hash) && body["id"].is_a?(::String) && body["id"] == id
|
|
119
|
+
raise VerificationError.new("invalid_payload", "the body's id does not equal NR-Webhook-Id")
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
event = begin
|
|
123
|
+
Crystalline.unmarshal_json(body, EVENT_TYPE)
|
|
124
|
+
rescue StandardError
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if event.nil? || Crystalline.unknown?(event)
|
|
129
|
+
raise VerificationError.new("invalid_payload", "the body is not a known webhook event")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
event
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
sig { params(headers: T::Enumerable[T.untyped]).returns(T::Hash[String, String]) }
|
|
138
|
+
def header_values(headers)
|
|
139
|
+
HEADER_NAMES.to_h do |name|
|
|
140
|
+
found = T.let([], T::Array[String])
|
|
141
|
+
headers.each do |key, value|
|
|
142
|
+
found.concat(Array(value).map(&:to_s)) if key.to_s.casecmp?(name)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if found.length > 1 || found.first&.include?(",")
|
|
146
|
+
raise VerificationError.new("duplicate_header", "#{name} is repeated")
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
raise VerificationError.new("missing_header", "#{name} is missing") if found.first.to_s.empty?
|
|
150
|
+
|
|
151
|
+
[name, found.first.to_s]
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
sig { params(signature: String).returns(String) }
|
|
156
|
+
def decode_signature(signature)
|
|
157
|
+
encoded = signature.delete_prefix("v1=")
|
|
158
|
+
if encoded.length == signature.length
|
|
159
|
+
raise VerificationError.new("invalid_signature", "NR-Webhook-Signature is malformed")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
unless encoded.match?(/\A(?:[0-9a-fA-F]{2})*\z/)
|
|
163
|
+
raise VerificationError.new("invalid_signature", "NR-Webhook-Signature is malformed")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
[encoded].pack("H*")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
data/lib/noresponse.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: noresponse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- NoResponse
|
|
@@ -356,10 +356,18 @@ files:
|
|
|
356
356
|
- lib/no_response/models/shared/accountdecision.rbi
|
|
357
357
|
- lib/no_response/models/shared/accountdecisionsbyflow.rb
|
|
358
358
|
- lib/no_response/models/shared/accountdecisionsbyflow.rbi
|
|
359
|
+
- lib/no_response/models/shared/accountdeleted.rb
|
|
360
|
+
- lib/no_response/models/shared/accountdeleted.rbi
|
|
361
|
+
- lib/no_response/models/shared/accountdeletedevent.rb
|
|
362
|
+
- lib/no_response/models/shared/accountdeletedevent.rbi
|
|
359
363
|
- lib/no_response/models/shared/accountdeletion.rb
|
|
360
364
|
- lib/no_response/models/shared/accountdeletion.rbi
|
|
361
365
|
- lib/no_response/models/shared/accountrisk.rb
|
|
362
366
|
- lib/no_response/models/shared/accountrisk.rbi
|
|
367
|
+
- lib/no_response/models/shared/accountriskchanged.rb
|
|
368
|
+
- lib/no_response/models/shared/accountriskchanged.rbi
|
|
369
|
+
- lib/no_response/models/shared/accountriskchangedevent.rb
|
|
370
|
+
- lib/no_response/models/shared/accountriskchangedevent.rbi
|
|
363
371
|
- lib/no_response/models/shared/accountriskreason.rb
|
|
364
372
|
- lib/no_response/models/shared/accountriskreason.rbi
|
|
365
373
|
- lib/no_response/models/shared/alternate_name.rb
|
|
@@ -378,6 +386,8 @@ files:
|
|
|
378
386
|
- lib/no_response/models/shared/assessmentdetailauthcontext.rbi
|
|
379
387
|
- lib/no_response/models/shared/assessmentdetailtiming.rb
|
|
380
388
|
- lib/no_response/models/shared/assessmentdetailtiming.rbi
|
|
389
|
+
- lib/no_response/models/shared/assessmentexpired.rb
|
|
390
|
+
- lib/no_response/models/shared/assessmentexpired.rbi
|
|
381
391
|
- lib/no_response/models/shared/assessmentlist.rb
|
|
382
392
|
- lib/no_response/models/shared/assessmentlist.rbi
|
|
383
393
|
- lib/no_response/models/shared/assessmentoutcome.rb
|
|
@@ -396,6 +406,10 @@ files:
|
|
|
396
406
|
- lib/no_response/models/shared/assessmentrequestissuedcredential.rbi
|
|
397
407
|
- lib/no_response/models/shared/assessmentrequestpolicycontext.rb
|
|
398
408
|
- lib/no_response/models/shared/assessmentrequestpolicycontext.rbi
|
|
409
|
+
- lib/no_response/models/shared/assessmentupdateddata.rb
|
|
410
|
+
- lib/no_response/models/shared/assessmentupdateddata.rbi
|
|
411
|
+
- lib/no_response/models/shared/assessmentupdatedevent.rb
|
|
412
|
+
- lib/no_response/models/shared/assessmentupdatedevent.rbi
|
|
399
413
|
- lib/no_response/models/shared/assurancelevel.rb
|
|
400
414
|
- lib/no_response/models/shared/assurancelevel.rbi
|
|
401
415
|
- lib/no_response/models/shared/authcontext.rb
|
|
@@ -434,6 +448,12 @@ files:
|
|
|
434
448
|
- lib/no_response/models/shared/email.rbi
|
|
435
449
|
- lib/no_response/models/shared/email_union.rb
|
|
436
450
|
- lib/no_response/models/shared/email_union.rbi
|
|
451
|
+
- lib/no_response/models/shared/endpointverification.rb
|
|
452
|
+
- lib/no_response/models/shared/endpointverification.rbi
|
|
453
|
+
- lib/no_response/models/shared/endpointverificationevent.rb
|
|
454
|
+
- lib/no_response/models/shared/endpointverificationevent.rbi
|
|
455
|
+
- lib/no_response/models/shared/environment.rb
|
|
456
|
+
- lib/no_response/models/shared/environment.rbi
|
|
437
457
|
- lib/no_response/models/shared/failure.rb
|
|
438
458
|
- lib/no_response/models/shared/failure.rbi
|
|
439
459
|
- lib/no_response/models/shared/failurereason.rb
|
|
@@ -568,12 +588,18 @@ files:
|
|
|
568
588
|
- lib/no_response/models/shared/webhookendpoint.rbi
|
|
569
589
|
- lib/no_response/models/shared/webhookendpointcreated.rb
|
|
570
590
|
- lib/no_response/models/shared/webhookendpointcreated.rbi
|
|
591
|
+
- lib/no_response/models/shared/webhookendpointdisabled.rb
|
|
592
|
+
- lib/no_response/models/shared/webhookendpointdisabled.rbi
|
|
593
|
+
- lib/no_response/models/shared/webhookendpointdisabledevent.rb
|
|
594
|
+
- lib/no_response/models/shared/webhookendpointdisabledevent.rbi
|
|
571
595
|
- lib/no_response/models/shared/webhookendpointlist.rb
|
|
572
596
|
- lib/no_response/models/shared/webhookendpointlist.rbi
|
|
573
597
|
- lib/no_response/models/shared/webhookendpointrequest.rb
|
|
574
598
|
- lib/no_response/models/shared/webhookendpointrequest.rbi
|
|
575
599
|
- lib/no_response/models/shared/webhookendpointstate.rb
|
|
576
600
|
- lib/no_response/models/shared/webhookendpointstate.rbi
|
|
601
|
+
- lib/no_response/models/shared/webhookevent.rb
|
|
602
|
+
- lib/no_response/models/shared/webhookevent.rbi
|
|
577
603
|
- lib/no_response/models/shared/webhookkeyrotation.rb
|
|
578
604
|
- lib/no_response/models/shared/webhookkeyrotation.rbi
|
|
579
605
|
- lib/no_response/models/shared/webhookkeyrotationrequest.rb
|
|
@@ -588,10 +614,16 @@ files:
|
|
|
588
614
|
- lib/no_response/models/shared/webhooktestrequest.rbi
|
|
589
615
|
- lib/no_response/models/shared/webhooktestrequestevent.rb
|
|
590
616
|
- lib/no_response/models/shared/webhooktestrequestevent.rbi
|
|
617
|
+
- lib/no_response/models/shared/webhookverificationresponse.rb
|
|
618
|
+
- lib/no_response/models/shared/webhookverificationresponse.rbi
|
|
591
619
|
- lib/no_response/models/shared/website.rb
|
|
592
620
|
- lib/no_response/models/shared/website.rbi
|
|
593
621
|
- lib/no_response/models/shared/website_union.rb
|
|
594
622
|
- lib/no_response/models/shared/website_union.rbi
|
|
623
|
+
- lib/no_response/models/shared/workspacedeleted.rb
|
|
624
|
+
- lib/no_response/models/shared/workspacedeleted.rbi
|
|
625
|
+
- lib/no_response/models/shared/workspacedeletedevent.rb
|
|
626
|
+
- lib/no_response/models/shared/workspacedeletedevent.rbi
|
|
595
627
|
- lib/no_response/noresponseclient.rb
|
|
596
628
|
- lib/no_response/sdk_hooks/hooks.rb
|
|
597
629
|
- lib/no_response/sdk_hooks/idempotency_key_hook.rb
|
|
@@ -608,8 +640,8 @@ files:
|
|
|
608
640
|
- lib/no_response/utils/url.rb
|
|
609
641
|
- lib/no_response/utils/utils.rb
|
|
610
642
|
- lib/no_response/wait.rb
|
|
643
|
+
- lib/no_response/webhook_verification.rb
|
|
611
644
|
- lib/no_response/webhookendpoints.rb
|
|
612
|
-
- lib/no_response/webhooks.rb
|
|
613
645
|
- lib/noresponse.rb
|
|
614
646
|
homepage:
|
|
615
647
|
licenses:
|