summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Mazetto <gabriel@gitlab.com>2016-04-27 04:24:49 -0300
committerGabriel Mazetto <gabriel@gitlab.com>2016-04-30 05:04:10 -0300
commit0cd5edf35cfaca74344dd389aadd65f0f179d395 (patch)
treed83d697f60126f5b10992dca550751e2182778d9
parent40c38644a88b8f5e88e6fd3317421206d8ee851e (diff)
downloadgitlab-ce-0cd5edf35cfaca74344dd389aadd65f0f179d395.tar.gz
Backported minimal safewebhook implementation to GitLab CE
-rw-r--r--app/models/hooks/project_hook.rb1
-rw-r--r--app/models/hooks/service_hook.rb1
-rw-r--r--app/models/hooks/system_hook.rb1
-rw-r--r--app/models/hooks/web_hook.rb24
-rw-r--r--db/migrate/20160413115152_add_token_to_web_hooks.rb5
-rw-r--r--db/schema.rb1
-rw-r--r--spec/factories/project_hooks.rb4
-rw-r--r--spec/models/hooks/web_hook_spec.rb46
8 files changed, 58 insertions, 25 deletions
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index bc6e0f98c3c..d149511b868 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# token :string
#
class ProjectHook < WebHook
diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb
index 80962264ba2..f45145eeb3a 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# token :string
#
class ServiceHook < WebHook
diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb
index 15dddcc2447..012cc8ec005 100644
--- a/app/models/hooks/system_hook.rb
+++ b/app/models/hooks/system_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# token :string
#
class SystemHook < WebHook
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 3a2e4f546f7..1e3b4815596 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# token :string
#
class WebHook < ActiveRecord::Base
@@ -43,23 +44,17 @@ class WebHook < ActiveRecord::Base
if parsed_url.userinfo.blank?
response = WebHook.post(url,
body: data.to_json,
- headers: {
- "Content-Type" => "application/json",
- "X-Gitlab-Event" => hook_name.singularize.titleize
- },
+ headers: build_headers(hook_name),
verify: enable_ssl_verification)
else
- post_url = url.gsub("#{parsed_url.userinfo}@", "")
+ post_url = url.gsub("#{parsed_url.userinfo}@", '')
auth = {
username: CGI.unescape(parsed_url.user),
password: CGI.unescape(parsed_url.password),
}
response = WebHook.post(post_url,
body: data.to_json,
- headers: {
- "Content-Type" => "application/json",
- "X-Gitlab-Event" => hook_name.singularize.titleize
- },
+ headers: build_headers(hook_name),
verify: enable_ssl_verification,
basic_auth: auth)
end
@@ -73,4 +68,15 @@ class WebHook < ActiveRecord::Base
def async_execute(data, hook_name)
Sidekiq::Client.enqueue(ProjectWebHookWorker, id, data, hook_name)
end
+
+ private
+
+ def build_headers(hook_name)
+ headers = {
+ 'Content-Type' => 'application/json',
+ 'X-Gitlab-Event' => hook_name.singularize.titleize
+ }
+ headers['X-Gitlab-Token'] = token if token.present?
+ headers
+ end
end
diff --git a/db/migrate/20160413115152_add_token_to_web_hooks.rb b/db/migrate/20160413115152_add_token_to_web_hooks.rb
new file mode 100644
index 00000000000..f04225068cd
--- /dev/null
+++ b/db/migrate/20160413115152_add_token_to_web_hooks.rb
@@ -0,0 +1,5 @@
+class AddTokenToWebHooks < ActiveRecord::Migration
+ def change
+ add_column :web_hooks, :token, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 42457d92353..04aee737e4c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1025,6 +1025,7 @@ ActiveRecord::Schema.define(version: 20160421130527) do
t.boolean "enable_ssl_verification", default: true
t.boolean "build_events", default: false, null: false
t.boolean "wiki_page_events", default: false, null: false
+ t.string "token"
end
add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree
diff --git a/spec/factories/project_hooks.rb b/spec/factories/project_hooks.rb
index 94dd935a039..3195fb3ddcc 100644
--- a/spec/factories/project_hooks.rb
+++ b/spec/factories/project_hooks.rb
@@ -1,5 +1,9 @@
FactoryGirl.define do
factory :project_hook do
url { FFaker::Internet.uri('http') }
+
+ trait :token do
+ token { SecureRandom.hex(10) }
+ end
end
end
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 04bc2dcfb16..37a27d73aab 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -43,51 +43,65 @@ describe WebHook, models: true do
end
describe "execute" do
+ let(:project) { create(:project) }
+ let(:project_hook) { create(:project_hook) }
+
before(:each) do
- @project_hook = create(:project_hook)
- @project = create(:project)
- @project.hooks << [@project_hook]
+ project.hooks << [project_hook]
@data = { before: 'oldrev', after: 'newrev', ref: 'ref' }
- WebMock.stub_request(:post, @project_hook.url)
+ WebMock.stub_request(:post, project_hook.url)
+ end
+
+ context 'when token is defined' do
+ let(:project_hook) { create(:project_hook, :token) }
+
+ it 'POSTs to the webhook URL' do
+ project_hook.execute(@data, 'push_hooks')
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: { 'Content-Type' => 'application/json',
+ 'X-Gitlab-Event' => 'Push Hook',
+ 'X-Gitlab-Token' => project_hook.token }
+ ).once
+ end
end
it "POSTs to the webhook URL" do
- @project_hook.execute(@data, 'push_hooks')
- expect(WebMock).to have_requested(:post, @project_hook.url).with(
- headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Push Hook' }
+ project_hook.execute(@data, 'push_hooks')
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Push Hook' }
).once
end
it "POSTs the data as JSON" do
- @project_hook.execute(@data, 'push_hooks')
- expect(WebMock).to have_requested(:post, @project_hook.url).with(
- headers: { 'Content-Type'=>'application/json', 'X-Gitlab-Event'=>'Push Hook' }
+ project_hook.execute(@data, 'push_hooks')
+ expect(WebMock).to have_requested(:post, project_hook.url).with(
+ headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'Push Hook' }
).once
end
it "catches exceptions" do
expect(WebHook).to receive(:post).and_raise("Some HTTP Post error")
- expect { @project_hook.execute(@data, 'push_hooks') }.to raise_error(RuntimeError)
+ expect { project_hook.execute(@data, 'push_hooks') }.to raise_error(RuntimeError)
end
it "handles SSL exceptions" do
expect(WebHook).to receive(:post).and_raise(OpenSSL::SSL::SSLError.new('SSL error'))
- expect(@project_hook.execute(@data, 'push_hooks')).to eq([false, 'SSL error'])
+ expect(project_hook.execute(@data, 'push_hooks')).to eq([false, 'SSL error'])
end
it "handles 200 status code" do
- WebMock.stub_request(:post, @project_hook.url).to_return(status: 200, body: "Success")
+ WebMock.stub_request(:post, project_hook.url).to_return(status: 200, body: "Success")
- expect(@project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success'])
+ expect(project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success'])
end
it "handles 2xx status codes" do
- WebMock.stub_request(:post, @project_hook.url).to_return(status: 201, body: "Success")
+ WebMock.stub_request(:post, project_hook.url).to_return(status: 201, body: "Success")
- expect(@project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success'])
+ expect(project_hook.execute(@data, 'push_hooks')).to eq([true, 'Success'])
end
end
end