lex-webhook 0.1.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 +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +53 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +5 -0
- data/README.md +47 -0
- data/lex-webhook.gemspec +35 -0
- data/lib/legion/extensions/webhook/client.rb +21 -0
- data/lib/legion/extensions/webhook/helpers/client.rb +27 -0
- data/lib/legion/extensions/webhook/helpers/signature.rb +34 -0
- data/lib/legion/extensions/webhook/runners/endpoints.rb +41 -0
- data/lib/legion/extensions/webhook/runners/receive.rb +56 -0
- data/lib/legion/extensions/webhook/runners/verify.rb +28 -0
- data/lib/legion/extensions/webhook/version.rb +9 -0
- data/lib/legion/extensions/webhook.rb +17 -0
- metadata +118 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9579600380a6b56342f0243c7ed666aae7cd77ede4a90ac780a0d46af4b772c0
|
|
4
|
+
data.tar.gz: 885f7bf1a903e40cbd07bb033e58de3d8ed6128371cf1eec0fb920e811cfdb4c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 20bf93dd85ec020cf81c6d8b1859585df3dd3f30fb1ea06a2ca80bcdb60402627061ddfa2b92d756e6e060bd76436867f1b1afb87fc0dc3e458da3fdb2ad3ce5
|
|
7
|
+
data.tar.gz: 277c023cee59b78e4457aa42b74a7c514b2ab0ac0e2015df53571a2c22ed376141dd5241705bad0d6672494ffdd4bc5d181e79cb0a8fc93003d4e2fd6dd842f3
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [origin]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/origin'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/LineLength:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
16
|
+
Metrics/MethodLength:
|
|
17
|
+
Max: 50
|
|
18
|
+
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Max: 1500
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 1500
|
|
24
|
+
|
|
25
|
+
Metrics/BlockLength:
|
|
26
|
+
Max: 40
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
|
|
30
|
+
Metrics/AbcSize:
|
|
31
|
+
Max: 60
|
|
32
|
+
|
|
33
|
+
Metrics/CyclomaticComplexity:
|
|
34
|
+
Max: 15
|
|
35
|
+
|
|
36
|
+
Metrics/PerceivedComplexity:
|
|
37
|
+
Max: 17
|
|
38
|
+
|
|
39
|
+
Style/Documentation:
|
|
40
|
+
Enabled: false
|
|
41
|
+
|
|
42
|
+
Style/SymbolArray:
|
|
43
|
+
Enabled: true
|
|
44
|
+
|
|
45
|
+
Style/FrozenStringLiteralComment:
|
|
46
|
+
Enabled: true
|
|
47
|
+
EnforcedStyle: always
|
|
48
|
+
|
|
49
|
+
Naming/FileName:
|
|
50
|
+
Enabled: false
|
|
51
|
+
|
|
52
|
+
Gemspec/DevelopmentDependencies:
|
|
53
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] - 2026-03-21
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Initial release
|
|
7
|
+
- `Helpers::Signature` with HMAC compute, verify, and constant-time secure_compare
|
|
8
|
+
- `Runners::Receive` for webhook ingestion with optional signature verification and JSON body parsing
|
|
9
|
+
- `Runners::Verify` for explicit signature validation and computation
|
|
10
|
+
- `Runners::Endpoints` for in-memory endpoint registry (list, register, remove)
|
|
11
|
+
- Standalone `Client` class including all runner modules
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# lex-webhook
|
|
2
|
+
|
|
3
|
+
Generic webhook receiving and HMAC signature verification for LegionIO.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add to your Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'lex-webhook'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Standalone client
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
client = Legion::Extensions::Webhook::Client.new
|
|
19
|
+
|
|
20
|
+
# Receive a webhook (with optional HMAC verification)
|
|
21
|
+
result = client.receive(
|
|
22
|
+
path: '/hooks/github',
|
|
23
|
+
headers: { 'x-hub-signature-256' => 'sha256=abc123...' },
|
|
24
|
+
body: '{"action":"push"}',
|
|
25
|
+
method: 'POST',
|
|
26
|
+
secret: 'my-secret'
|
|
27
|
+
)
|
|
28
|
+
# => { received: true, path: '/hooks/github', payload: { action: 'push' }, verified: true }
|
|
29
|
+
|
|
30
|
+
# Verify a signature
|
|
31
|
+
result = client.verify(secret: 'my-secret', signature: 'sha256=abc123...', payload: '{"action":"push"}')
|
|
32
|
+
# => { valid: true, algorithm: 'sha256' }
|
|
33
|
+
|
|
34
|
+
# Compute a signature
|
|
35
|
+
result = client.compute_signature(secret: 'my-secret', payload: '{"action":"push"}')
|
|
36
|
+
# => { signature: 'abc123...' }
|
|
37
|
+
|
|
38
|
+
# Endpoint registry
|
|
39
|
+
client.register_endpoint(path: '/hooks/github', secret: 'secret1', description: 'GitHub events')
|
|
40
|
+
client.list_endpoints
|
|
41
|
+
# => { endpoints: [{ path: '/hooks/github', secret: 'secret1', description: 'GitHub events' }] }
|
|
42
|
+
client.remove_endpoint(path: '/hooks/github')
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
MIT
|
data/lex-webhook.gemspec
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require 'legion/extensions/webhook/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = 'lex-webhook'
|
|
9
|
+
spec.version = Legion::Extensions::Webhook::VERSION
|
|
10
|
+
spec.authors = ['Esity']
|
|
11
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
12
|
+
|
|
13
|
+
spec.summary = 'Legion::Extensions::Webhook'
|
|
14
|
+
spec.description = 'Generic webhook receiving and HMAC signature verification for LegionIO'
|
|
15
|
+
spec.homepage = 'https://github.com/LegionIO/lex-webhook'
|
|
16
|
+
spec.license = 'MIT'
|
|
17
|
+
spec.required_ruby_version = '>= 3.4'
|
|
18
|
+
|
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-webhook'
|
|
21
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-webhook/blob/main/CHANGELOG.md'
|
|
22
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-webhook'
|
|
23
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-webhook/issues'
|
|
24
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
25
|
+
|
|
26
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
27
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
28
|
+
end
|
|
29
|
+
spec.require_paths = ['lib']
|
|
30
|
+
|
|
31
|
+
spec.add_development_dependency 'rake'
|
|
32
|
+
spec.add_development_dependency 'rspec'
|
|
33
|
+
spec.add_development_dependency 'rubocop'
|
|
34
|
+
spec.add_development_dependency 'rubocop-rspec'
|
|
35
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/webhook/runners/receive'
|
|
4
|
+
require 'legion/extensions/webhook/runners/verify'
|
|
5
|
+
require 'legion/extensions/webhook/runners/endpoints'
|
|
6
|
+
|
|
7
|
+
module Legion
|
|
8
|
+
module Extensions
|
|
9
|
+
module Webhook
|
|
10
|
+
class Client
|
|
11
|
+
include Runners::Receive
|
|
12
|
+
include Runners::Verify
|
|
13
|
+
include Runners::Endpoints
|
|
14
|
+
|
|
15
|
+
def initialize(**opts)
|
|
16
|
+
@opts = opts
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Webhook
|
|
6
|
+
module Helpers
|
|
7
|
+
module Client
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def settings
|
|
11
|
+
return Legion::Settings[:webhook] if defined?(Legion::Settings)
|
|
12
|
+
|
|
13
|
+
{}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def endpoints_store
|
|
17
|
+
@endpoints_store ||= []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def reset_endpoints!
|
|
21
|
+
@endpoints_store = []
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Webhook
|
|
8
|
+
module Helpers
|
|
9
|
+
module Signature
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def verify(secret:, signature:, payload:, algorithm: 'sha256') # rubocop:disable Naming/PredicateMethod
|
|
13
|
+
computed = compute(secret: secret, payload: payload, algorithm: algorithm)
|
|
14
|
+
bytes_match?(computed, signature)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def compute(secret:, payload:, algorithm: 'sha256')
|
|
18
|
+
OpenSSL::HMAC.hexdigest(algorithm, secret, payload)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def bytes_match?(lhs, rhs)
|
|
22
|
+
return false if lhs.nil? || rhs.nil?
|
|
23
|
+
|
|
24
|
+
lhs_clean = lhs.sub(/\A\w+=/, '')
|
|
25
|
+
rhs_clean = rhs.sub(/\A\w+=/, '')
|
|
26
|
+
return false if lhs_clean.bytesize != rhs_clean.bytesize
|
|
27
|
+
|
|
28
|
+
lhs_clean.bytes.zip(rhs_clean.bytes).reduce(0) { |acc, (x, y)| acc | (x ^ y) }.zero?
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Webhook
|
|
6
|
+
module Runners
|
|
7
|
+
module Endpoints
|
|
8
|
+
def list_endpoints(**)
|
|
9
|
+
{ endpoints: endpoint_registry.dup }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def register_endpoint(path:, secret: nil, description: nil, **)
|
|
13
|
+
existing = endpoint_registry.find { |e| e[:path] == path }
|
|
14
|
+
if existing
|
|
15
|
+
existing[:secret] = secret
|
|
16
|
+
existing[:description] = description
|
|
17
|
+
return { registered: false, updated: true, path: path }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
entry = { path: path, secret: secret, description: description }.compact
|
|
21
|
+
endpoint_registry << entry
|
|
22
|
+
{ registered: true, updated: false, path: path }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def remove_endpoint(path:, **)
|
|
26
|
+
before = endpoint_registry.size
|
|
27
|
+
endpoint_registry.reject! { |e| e[:path] == path }
|
|
28
|
+
removed = endpoint_registry.size < before
|
|
29
|
+
{ removed: removed, path: path }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def endpoint_registry
|
|
35
|
+
@endpoint_registry ||= []
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'legion/extensions/webhook/helpers/signature'
|
|
5
|
+
|
|
6
|
+
module Legion
|
|
7
|
+
module Extensions
|
|
8
|
+
module Webhook
|
|
9
|
+
module Runners
|
|
10
|
+
module Receive
|
|
11
|
+
def receive(path:, **opts)
|
|
12
|
+
headers = opts.fetch(:headers, {})
|
|
13
|
+
body = opts.fetch(:body, '')
|
|
14
|
+
method = opts.fetch(:method, 'POST')
|
|
15
|
+
secret = opts[:secret]
|
|
16
|
+
|
|
17
|
+
verified = verify_signature(headers: headers, body: body, secret: secret)
|
|
18
|
+
payload = parse_body(headers: headers, body: body)
|
|
19
|
+
|
|
20
|
+
{ received: true, path: path, method: method, payload: payload, verified: verified }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def verify_signature(headers:, body:, secret:)
|
|
26
|
+
return false if secret.nil?
|
|
27
|
+
|
|
28
|
+
sig_header = find_signature_header(headers)
|
|
29
|
+
return false if sig_header.nil?
|
|
30
|
+
|
|
31
|
+
Helpers::Signature.verify(secret: secret, signature: sig_header, payload: body)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def find_signature_header(headers)
|
|
35
|
+
normalized = headers.transform_keys { |key| key.to_s.downcase }
|
|
36
|
+
normalized['x-hub-signature-256'] ||
|
|
37
|
+
normalized['x-hub-signature'] ||
|
|
38
|
+
normalized['x-signature'] ||
|
|
39
|
+
normalized['x-webhook-signature']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def parse_body(headers:, body:)
|
|
43
|
+
return body if body.nil? || body.empty?
|
|
44
|
+
|
|
45
|
+
content_type = headers.transform_keys { |key| key.to_s.downcase }['content-type'].to_s
|
|
46
|
+
return ::JSON.parse(body, symbolize_names: true) if content_type.include?('json')
|
|
47
|
+
|
|
48
|
+
body
|
|
49
|
+
rescue ::JSON::ParserError
|
|
50
|
+
body
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/webhook/helpers/signature'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Webhook
|
|
8
|
+
module Runners
|
|
9
|
+
module Verify
|
|
10
|
+
def verify(secret:, signature:, payload:, algorithm: 'sha256', **)
|
|
11
|
+
valid = Helpers::Signature.verify(
|
|
12
|
+
secret: secret,
|
|
13
|
+
signature: signature,
|
|
14
|
+
payload: payload,
|
|
15
|
+
algorithm: algorithm
|
|
16
|
+
)
|
|
17
|
+
{ valid: valid, algorithm: algorithm }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def compute_signature(secret:, payload:, algorithm: 'sha256', **)
|
|
21
|
+
sig = Helpers::Signature.compute(secret: secret, payload: payload, algorithm: algorithm)
|
|
22
|
+
{ signature: sig }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/webhook/version'
|
|
4
|
+
require 'legion/extensions/webhook/helpers/signature'
|
|
5
|
+
require 'legion/extensions/webhook/helpers/client'
|
|
6
|
+
require 'legion/extensions/webhook/runners/receive'
|
|
7
|
+
require 'legion/extensions/webhook/runners/verify'
|
|
8
|
+
require 'legion/extensions/webhook/runners/endpoints'
|
|
9
|
+
require 'legion/extensions/webhook/client'
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module Webhook
|
|
14
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined?(:Core)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-webhook
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rspec
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rubocop
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rubocop-rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
description: Generic webhook receiving and HMAC signature verification for LegionIO
|
|
69
|
+
email:
|
|
70
|
+
- matthewdiverson@gmail.com
|
|
71
|
+
executables: []
|
|
72
|
+
extensions: []
|
|
73
|
+
extra_rdoc_files: []
|
|
74
|
+
files:
|
|
75
|
+
- ".github/workflows/ci.yml"
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- ".rspec"
|
|
78
|
+
- ".rubocop.yml"
|
|
79
|
+
- CHANGELOG.md
|
|
80
|
+
- Gemfile
|
|
81
|
+
- README.md
|
|
82
|
+
- lex-webhook.gemspec
|
|
83
|
+
- lib/legion/extensions/webhook.rb
|
|
84
|
+
- lib/legion/extensions/webhook/client.rb
|
|
85
|
+
- lib/legion/extensions/webhook/helpers/client.rb
|
|
86
|
+
- lib/legion/extensions/webhook/helpers/signature.rb
|
|
87
|
+
- lib/legion/extensions/webhook/runners/endpoints.rb
|
|
88
|
+
- lib/legion/extensions/webhook/runners/receive.rb
|
|
89
|
+
- lib/legion/extensions/webhook/runners/verify.rb
|
|
90
|
+
- lib/legion/extensions/webhook/version.rb
|
|
91
|
+
homepage: https://github.com/LegionIO/lex-webhook
|
|
92
|
+
licenses:
|
|
93
|
+
- MIT
|
|
94
|
+
metadata:
|
|
95
|
+
homepage_uri: https://github.com/LegionIO/lex-webhook
|
|
96
|
+
source_code_uri: https://github.com/LegionIO/lex-webhook
|
|
97
|
+
changelog_uri: https://github.com/LegionIO/lex-webhook/blob/main/CHANGELOG.md
|
|
98
|
+
documentation_uri: https://github.com/LegionIO/lex-webhook
|
|
99
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-webhook/issues
|
|
100
|
+
rubygems_mfa_required: 'true'
|
|
101
|
+
rdoc_options: []
|
|
102
|
+
require_paths:
|
|
103
|
+
- lib
|
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '3.4'
|
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - ">="
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: '0'
|
|
114
|
+
requirements: []
|
|
115
|
+
rubygems_version: 3.6.9
|
|
116
|
+
specification_version: 4
|
|
117
|
+
summary: Legion::Extensions::Webhook
|
|
118
|
+
test_files: []
|