Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,37 @@ puts "Card Template ID: #{response.card_template_identifier}"
puts "Environment ID: #{response.environment_identifier}"
```

### Webhooks

#### Create a webhook

```ruby
webhook = client.console.webhooks.create(
name: 'Production',
url: 'https://example.com/webhooks',
subscribed_events: ['ag.access_pass.issued']
)

puts "Webhook created: #{webhook.id}"
puts "Private key: #{webhook.private_key}"
```

#### List webhooks

```ruby
webhooks = client.console.webhooks.list

webhooks.each do |webhook|
puts "ID: #{webhook.id}, Name: #{webhook.name}"
end
```

#### Delete a webhook

```ruby
client.console.webhooks.delete('abc123')
```

## Configuration

The SDK can be configured with a custom API endpoint:
Expand Down Expand Up @@ -329,9 +360,9 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/access
| GET /v1/console/pass-template-pairs | `console.list_pass_template_pairs()` | Y |
| POST /v1/console/card-templates/{id}/ios_preflight | `console.ios_preflight()` | Y |
| GET /v1/console/ledger-items | `console.list_ledger_items()` / `console.ledger_items()` | Y |
| GET /v1/console/webhooks | `console.webhooks.list()` | - |
| POST /v1/console/webhooks | `console.webhooks.create()` | - |
| DELETE /v1/console/webhooks/{id} | `console.webhooks.delete()` | - |
| GET /v1/console/webhooks | `console.webhooks.list()` | Y |
| POST /v1/console/webhooks | `console.webhooks.create()` | Y |
| DELETE /v1/console/webhooks/{id} | `console.webhooks.delete()` | Y |
| POST /v1/console/hid/orgs | `console.hid.orgs.create()` | - |
| POST /v1/console/hid/orgs/activate | `console.hid.orgs.activate()` | - |
| GET /v1/console/hid/orgs | `console.hid.orgs.list()` | - |
Expand Down
1 change: 1 addition & 0 deletions lib/accessgrid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def execute_and_process_request!(request)

def handle_response(response)
case response.code.to_i
when 204 then {}
when 200, 201, 202 then JSON.parse(response.body)
when 401 then raise AuthenticationError, 'Invalid credentials'
when 402 then raise Error, 'Insufficient account balance'
Expand Down
48 changes: 48 additions & 0 deletions lib/accessgrid/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
module AccessGrid
# Manages enterprise template and logging operations.
class Console
attr_reader :webhooks

def initialize(client)
@client = client
@webhooks = Webhooks.new(client)
end

def create_template(params)
Expand Down Expand Up @@ -200,4 +203,49 @@ def initialize(data)
@use_case = data['use_case']
end
end

# Manages webhook operations.
class Webhooks
def initialize(client)
@client = client
end

def create(name:, url:, subscribed_events:, auth_method: 'bearer_token')
data = {
name: name,
url: url,
subscribed_events: subscribed_events,
auth_method: auth_method
}
response = @client.make_request(:post, '/v1/console/webhooks', data)
Webhook.new(response)
end

def list(**params)
response = @client.make_request(:get, '/v1/console/webhooks', nil, params)
(response['webhooks'] || []).map { |wh| Webhook.new(wh) }
end

def delete(webhook_id)
@client.make_request(:delete, "/v1/console/webhooks/#{webhook_id}")
end
end

# Represents a webhook configuration.
class Webhook
attr_reader :id, :name, :url, :auth_method, :subscribed_events,
:created_at, :private_key, :client_cert, :cert_expires_at

def initialize(data)
@id = data['id']
@name = data['name']
@url = data['url']
@auth_method = data['auth_method']
@subscribed_events = data['subscribed_events']
@created_at = data['created_at']
@private_key = data['private_key']
@client_cert = data['client_cert']
@cert_expires_at = data['cert_expires_at']
end
end
end
26 changes: 15 additions & 11 deletions lib/accessgrid/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ module AccessGrid
# Builds and configures HTTP requests for the AccessGrid API.
class Request
PAYLOAD_SIGNATURE_PARAM = :sig_payload
HTTP_METHODS = {
get: Net::HTTP::Get,
post: Net::HTTP::Post,
put: Net::HTTP::Put,
patch: Net::HTTP::Patch,
delete: Net::HTTP::Delete
}.freeze

attr_reader :account_id, :body, :http_method, :params, :payload, :uri

Expand Down Expand Up @@ -40,16 +47,9 @@ def net_http_request
private

def generate_net_http_request!
klass =
case http_method
when :get then Net::HTTP::Get
when :post then Net::HTTP::Post
when :put then Net::HTTP::Put
when :patch then Net::HTTP::Patch
else
raise ArgumentError, "Unsupported HTTP method: #{http_method}"
end

klass = HTTP_METHODS.fetch(http_method) do
raise ArgumentError, "Unsupported HTTP method: #{http_method}"
end
klass.new(uri.request_uri)
end

Expand Down Expand Up @@ -89,6 +89,10 @@ def get?
http_method == :get
end

def delete?
http_method == :delete
end

def post?
http_method == :post
end
Expand All @@ -98,7 +102,7 @@ def empty_body?
end

def post_without_body_or_get?
get? || (post? && empty_body?)
get? || delete? || (post? && empty_body?)
end

def default_payload
Expand Down
86 changes: 86 additions & 0 deletions spec/console_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -658,4 +658,90 @@
expect(result.environment_identifier).to eq('env_abc')
end
end

describe '#webhooks' do
let(:webhooks_service) { console.webhooks }

describe '#create' do
let(:create_response) do
{
id: 'wh_123',
name: 'Production',
url: 'https://example.com/webhooks',
auth_method: 'bearer_token',
subscribed_events: ['ag.access_pass.issued'],
created_at: '2025-01-01T00:00:00Z',
private_key: 'pk_secret_123'
}
end

it 'creates a webhook' do
stub_api_request(
:post,
'/v1/console/webhooks',
body: create_response,
request_body: {
name: 'Production',
url: 'https://example.com/webhooks',
subscribed_events: ['ag.access_pass.issued'],
auth_method: 'bearer_token'
}
)

webhook = webhooks_service.create(
name: 'Production',
url: 'https://example.com/webhooks',
subscribed_events: ['ag.access_pass.issued']
)

expect(webhook).to be_a(AccessGrid::Webhook)
expect(webhook.id).to eq('wh_123')
expect(webhook.name).to eq('Production')
expect(webhook.private_key).to eq('pk_secret_123')
end
end

describe '#list' do
let(:list_response) do
{
webhooks: [
{ id: 'wh_1', name: 'Prod', url: 'https://example.com/wh1', auth_method: 'bearer_token' },
{ id: 'wh_2', name: 'Staging', url: 'https://example.com/wh2', auth_method: 'bearer_token' }
],
pagination: { current_page: 1, total_pages: 1 }
}
end

it 'lists webhooks' do
stub_api_request(
:get,
'/v1/console/webhooks',
body: list_response,
query: generate_sig_payload(id: :webhooks)
)

webhooks = webhooks_service.list

expect(webhooks).to be_an(Array)
expect(webhooks.length).to eq(2)
expect(webhooks.first).to be_a(AccessGrid::Webhook)
expect(webhooks.first.id).to eq('wh_1')
end
end

describe '#delete' do
it 'deletes a webhook' do
stub_api_request(
:delete,
'/v1/console/webhooks/wh_123',
status: 204,
body: {},
query: generate_sig_payload(id: :wh_123)
)

result = webhooks_service.delete('wh_123')
expect(result).to eq({})
end
end
end
end
7 changes: 6 additions & 1 deletion spec/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,13 @@ def build_request(overrides = {})
expect(request.net_http_request).to be_a(Net::HTTP::Patch)
end

it 'raises ArgumentError for unsupported HTTP method' do
it 'returns Net::HTTP::Delete for :delete method' do
request = build_request(http_method: :delete)
expect(request.net_http_request).to be_a(Net::HTTP::Delete)
end

it 'raises ArgumentError for unsupported HTTP method' do
request = build_request(http_method: :options)
expect { request.net_http_request }.to raise_error(ArgumentError, /Unsupported HTTP method/)
end

Expand Down