Skip to content

Commit 55d7f4a

Browse files
committed
feat(webhooks): do not require basic auth password to be re-submitted when a webhook is updated - maintain existing value if not present
1 parent 2643d95 commit 55d7f4a

File tree

4 files changed

+64
-4
lines changed

4 files changed

+64
-4
lines changed

lib/pact_broker/api/resources/webhook.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def malformed_request?
3333

3434
def from_json
3535
if webhook
36-
@webhook = webhook_service.update_by_uuid uuid, new_webhook
36+
@webhook = webhook_service.update_by_uuid uuid, params_with_string_keys
3737
response.body = to_json
3838
else
3939
404

lib/pact_broker/test/test_data_builder.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ def create_webhook parameters = {}
228228
params[:events] || [{ name: PactBroker::Webhooks::WebhookEvent::DEFAULT_EVENT_NAME }]
229229
end
230230
events = event_params.collect{ |e| PactBroker::Webhooks::WebhookEvent.new(e) }
231-
default_params = { method: 'POST', url: 'http://example.org', headers: {'Content-Type' => 'application/json'}, username: params[:username], password: params[:password]}
232-
request = PactBroker::Webhooks::WebhookRequestTemplate.new(default_params.merge(params))
231+
template_params = { method: 'POST', url: 'http://example.org', headers: {'Content-Type' => 'application/json'}, username: params[:username], password: params[:password]}
232+
request = PactBroker::Webhooks::WebhookRequestTemplate.new(template_params.merge(params))
233233
@webhook = PactBroker::Webhooks::Repository.new.create uuid, PactBroker::Domain::Webhook.new(request: request, events: events), consumer, provider
234234
self
235235
end

lib/pact_broker/webhooks/service.rb

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require 'pact_broker/webhooks/webhook_event'
1010
require 'pact_broker/verifications/placeholder_verification'
1111
require 'pact_broker/pacts/placeholder_pact'
12+
require 'pact_broker/api/decorators/webhook_decorator'
1213

1314
module PactBroker
1415

@@ -40,7 +41,16 @@ def self.find_by_uuid uuid
4041
webhook_repository.find_by_uuid uuid
4142
end
4243

43-
def self.update_by_uuid uuid, webhook
44+
def self.update_by_uuid uuid, params
45+
webhook = webhook_repository.find_by_uuid(uuid)
46+
# Dirty hack to maintain existing password if it is not submitted
47+
# This is required because the password is not returned in the API response
48+
# for security purposes, so it needs to be re-entered with every response.
49+
# TODO implement proper 'secrets' management.
50+
if webhook.request.password && !params['request'].key?('password')
51+
params['request']['password'] = webhook.request.password
52+
end
53+
PactBroker::Api::Decorators::WebhookDecorator.new(webhook).from_hash(params)
4454
webhook_repository.update_by_uuid uuid, webhook
4555
end
4656

spec/lib/pact_broker/webhooks/service_spec.rb

+50
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,56 @@ module Webhooks
3333
end
3434
end
3535

36+
describe ".update_by_uuid" do
37+
before do
38+
allow_any_instance_of(PactBroker::Webhooks::Repository).to receive(:find_by_uuid).and_return(existing_webhook)
39+
end
40+
41+
let(:request) { PactBroker::Webhooks::WebhookRequestTemplate.new(password: 'password')}
42+
let(:existing_webhook) { PactBroker::Domain::Webhook.new(request: request) }
43+
let(:params) do
44+
{
45+
'request' => {
46+
'url' => "http://url"
47+
}
48+
}
49+
end
50+
51+
subject { Service.update_by_uuid("1234", params) }
52+
53+
context "when the webhook has a password and the incoming parameters do not contain a password" do
54+
it "does not overwite the password" do
55+
updated_webhook = nil
56+
allow_any_instance_of(PactBroker::Webhooks::Repository).to receive(:update_by_uuid) do | instance, uuid, webhook |
57+
updated_webhook = webhook
58+
true
59+
end
60+
subject
61+
expect(updated_webhook.request.password).to eq 'password'
62+
end
63+
end
64+
65+
context "the incoming parameters contain a password" do
66+
let(:params) do
67+
{
68+
'request' => {
69+
'password' => "updated"
70+
}
71+
}
72+
end
73+
74+
it "updates the password" do
75+
updated_webhook = nil
76+
allow_any_instance_of(PactBroker::Webhooks::Repository).to receive(:update_by_uuid) do | instance, uuid, webhook |
77+
updated_webhook = webhook
78+
true
79+
end
80+
subject
81+
expect(updated_webhook.request.password).to eq 'updated'
82+
end
83+
end
84+
end
85+
3686
describe ".trigger_webhooks" do
3787

3888
let(:verification) { instance_double(PactBroker::Domain::Verification)}

0 commit comments

Comments
 (0)