Class: Anvil::Webhook
Constant Summary
collapse
- ACTIONS =
%w[
weldCreate
forgeComplete
weldComplete
signerComplete
signerUpdateStatus
etchPacketComplete
documentGroupCreate
webhookTest
].freeze
Instance Attribute Summary collapse
#attributes, #client
Class Method Summary
collapse
Instance Method Summary
collapse
#==, build_from_response, create, find, #inspect, list, #method_missing, #respond_to_missing?, #to_h, #to_json, with_client
Constructor Details
#initialize(payload:, token: nil, **options) ⇒ Webhook
Returns a new instance of Webhook.
21
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/anvil/resources/webhook.rb', line 21
def initialize(payload:, token: nil, **options)
@raw_payload = payload.is_a?(String) ? payload : payload.to_json
@token = token
begin
parsed = JSON.parse(@raw_payload, symbolize_names: true)
super(parsed, **options)
rescue JSON::ParserError => e
raise WebhookError, "Invalid webhook payload: #{e.message}"
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
in the class Anvil::Resources::Base
Instance Attribute Details
#raw_payload ⇒ Object
Returns the value of attribute raw_payload.
19
20
21
|
# File 'lib/anvil/resources/webhook.rb', line 19
def raw_payload
@raw_payload
end
|
#token ⇒ Object
Returns the value of attribute token.
19
20
21
|
# File 'lib/anvil/resources/webhook.rb', line 19
def token
@token
end
|
Class Method Details
.create_test(action: 'webhookTest', data: {}) ⇒ Object
Create a test webhook for development
165
166
167
168
169
170
171
172
173
174
175
176
|
# File 'lib/anvil/resources/webhook.rb', line 165
def create_test(action: 'webhookTest', data: {})
payload = {
action: action,
data: data,
timestamp: Time.now.iso8601
}
new(
payload: payload.to_json,
token: Anvil.configuration.webhook_token
)
end
|
.from_request(request) ⇒ Webhook
Verify and parse a webhook request
155
156
157
158
159
160
161
162
|
# File 'lib/anvil/resources/webhook.rb', line 155
def from_request(request)
payload = request.body.read
token = (request)
webhook = new(payload: payload, token: token)
webhook.valid!
webhook
end
|
Instance Method Details
#action ⇒ Object
33
34
35
|
# File 'lib/anvil/resources/webhook.rb', line 33
def action
attributes[:action]
end
|
#data ⇒ Object
37
38
39
|
# File 'lib/anvil/resources/webhook.rb', line 37
def data
attributes[:data]
end
|
#decrypt(private_key_path = nil) ⇒ Object
Decrypt the webhook data (requires RSA private key)
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# File 'lib/anvil/resources/webhook.rb', line 69
def decrypt(private_key_path = nil)
return data unless encrypted?
private_key_path ||= ENV.fetch('ANVIL_RSA_PRIVATE_KEY_PATH', nil)
unless private_key_path && File.exist?(private_key_path)
raise WebhookError, 'Private key not found for decrypting webhook data'
end
begin
private_key = OpenSSL::PKey::RSA.new(File.read(private_key_path))
encrypted_data = Base64.decode64(data)
decrypted = private_key.private_decrypt(encrypted_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
JSON.parse(decrypted, symbolize_names: true)
rescue StandardError => e
raise WebhookError, "Failed to decrypt webhook data: #{e.message}"
end
end
|
#document_group_created? ⇒ Boolean
113
114
115
|
# File 'lib/anvil/resources/webhook.rb', line 113
def document_group_created?
action == 'documentGroupCreate'
end
|
#encrypted? ⇒ Boolean
Check if data is encrypted
64
65
66
|
# File 'lib/anvil/resources/webhook.rb', line 64
def encrypted?
data.is_a?(String) && data.match?(%r{^[A-Za-z0-9+/=]+$})
end
|
#packet_eid ⇒ Object
126
127
128
|
# File 'lib/anvil/resources/webhook.rb', line 126
def packet_eid
data[:packetEid] if signature_packet_complete? || signer_complete?
end
|
#signature_packet_complete? ⇒ Boolean
109
110
111
|
# File 'lib/anvil/resources/webhook.rb', line 109
def signature_packet_complete?
action == 'etchPacketComplete'
end
|
#signer_complete? ⇒ Boolean
101
102
103
|
# File 'lib/anvil/resources/webhook.rb', line 101
def signer_complete?
action == 'signerComplete'
end
|
#signer_eid ⇒ Object
Extract specific data based on webhook type
122
123
124
|
# File 'lib/anvil/resources/webhook.rb', line 122
def signer_eid
data[:signerEid] if signer_complete? || signer_status_updated?
end
|
#signer_email ⇒ Object
146
147
148
|
# File 'lib/anvil/resources/webhook.rb', line 146
def signer_email
data[:signerEmail] if signer_complete? || signer_status_updated?
end
|
#signer_name ⇒ Object
142
143
144
|
# File 'lib/anvil/resources/webhook.rb', line 142
def signer_name
data[:signerName] if signer_complete? || signer_status_updated?
end
|
#signer_status ⇒ Object
138
139
140
|
# File 'lib/anvil/resources/webhook.rb', line 138
def signer_status
data[:status] if signer_status_updated?
end
|
#signer_status_updated? ⇒ Boolean
105
106
107
|
# File 'lib/anvil/resources/webhook.rb', line 105
def signer_status_updated?
action == 'signerUpdateStatus'
end
|
#test? ⇒ Boolean
117
118
119
|
# File 'lib/anvil/resources/webhook.rb', line 117
def test?
action == 'webhookTest'
end
|
#timestamp ⇒ Object
41
42
43
|
# File 'lib/anvil/resources/webhook.rb', line 41
def timestamp
attributes[:timestamp] || attributes[:created_at]
end
|
#valid! ⇒ Object
57
58
59
60
61
|
# File 'lib/anvil/resources/webhook.rb', line 57
def valid!
raise WebhookVerificationError, 'Invalid webhook token' unless valid?
true
end
|
#valid?(expected_token = nil) ⇒ Boolean
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/anvil/resources/webhook.rb', line 46
def valid?(expected_token = nil)
expected_token ||= Anvil.configuration.webhook_token
raise WebhookVerificationError, 'No webhook token configured' if expected_token.nil? || expected_token.empty?
return false unless token
secure_compare(token, expected_token)
end
|
93
94
95
|
# File 'lib/anvil/resources/webhook.rb', line 93
def webform_complete?
action == 'forgeComplete'
end
|
134
135
136
|
# File 'lib/anvil/resources/webhook.rb', line 134
def webform_eid
data[:forgeEid] if webform_complete?
end
|
#workflow_complete? ⇒ Boolean
97
98
99
|
# File 'lib/anvil/resources/webhook.rb', line 97
def workflow_complete?
action == 'weldComplete'
end
|
#workflow_created? ⇒ Boolean
Helper methods for specific webhook types
89
90
91
|
# File 'lib/anvil/resources/webhook.rb', line 89
def workflow_created?
action == 'weldCreate'
end
|
#workflow_eid ⇒ Object
130
131
132
|
# File 'lib/anvil/resources/webhook.rb', line 130
def workflow_eid
data[:weldEid] || data[:eid] if workflow_created? || workflow_complete?
end
|