lib/site_hook/webhook.rb in site_hook-0.8.2 vs lib/site_hook/webhook.rb in site_hook-0.9.3
- old
+ new
@@ -1,31 +1,25 @@
##########
-# -> File: /home/ken/RubymineProjects/site_hook/lib/site_hook/webhook.rb
+# -> File: /site_hook/lib/site_hook/webhook.rb
# -> Project: site_hook
# -> Author: Ken Spencer <me@iotaspencer.me>
# -> Last Modified: 1/10/2018 21:35:44
# -> Copyright (c) 2018 Ken Spencer
# -> License: MIT
##########
-require 'site_hook/persist'
-require 'site_hook/const'
-require 'sinatra'
+require 'rack'
+require 'site_hook/logger'
+require 'json'
+require 'grape'
+require 'grape-route-helpers'
module SiteHook
- class Webhook < Sinatra::Base
+ class Server < Grape::API
+ version nil
+ prefix ''
+ format :json
- set server: %w[thin]
- set quiet: true
- set raise_errors: true
- set views: Pathname(SiteHook::Paths.lib_dir).join('site_hook', 'views')
- set :public_folder, Pathname(SiteHook::Paths.lib_dir).join('site_hook', 'assets')
- use CoffeeHandler
- def self.set_options(host, port)
- self.set bind: host.to_s
- self.set port: port.to_i
- end
-
#
# @param [String] body JSON String of body
# @param [String] sig Signature or token from git service
# @param [String] secret User-defined verification token
# @param [Boolean] plaintext Whether the verification is plaintext
@@ -34,144 +28,141 @@
if plaintext
sig == secret
else
case service
when 'gogs'
- if sig == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, secret, body)
- APPLOG.debug "Secret verified: #{sig} === #{OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, secret, body)}"
+ if sig == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, secret, body.chomp)
+ SiteHook::Log.app.debug "Secret verified: #{sig} === #{OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, secret, body)}"
true
end
when 'github'
- if sig == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, body)
- APPLOG.debug "Secret verified: #{sig} === #{OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, body)}"
+ if sig == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, body.chomp)
+ SiteHook::Log.app.debug "Secret verified: #{sig} === #{OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, body)}"
true
end
else
# This shouldn't happen
end
-
end
end
- CONTENT_TYPE = 'Content-Type'
- get '/' do
- halt 403, {CONTENT_TYPE => 'text/html'}, '<h1>See <a href="/webhooks/">here</a> for the active webhooks</h1>'
+ helpers do
+ def halt(status, message, headers)
+ error!(message, status, headers)
+ end
end
-
APPLICATION_JSON = 'application/json'
- get '/webhooks.json', provides: :json do
- content_type APPLICATION_JSON
- public_projects = JPHRC['projects'].select do |_project, hsh|
- !hsh.fetch('private')
- end
- result = {}
- public_projects.each do |project, hsh|
- result[project] = {}
- hsh.delete('hookpass')
- result[project].merge!(hsh)
- end
- headers CONTENT_TYPE => APPLICATION_JSON, 'Accept' => APPLICATION_JSON
- json result, layout: false
+ before do
+ remote_addr = request.env['REMOTE_ADDR']
+ cf_connecting_ip = request.env.fetch('HTTP_CF_CONNECTING_IP', nil)
+ ip = cf_connecting_ip || remote_addr
+ SiteHook::Log.access.log "#{ip} - #{request.request_method} #{request.path}"
end
-
- get '/webhooks/?' do
- haml :webhooks, locals: {'projects' => JPHRC['projects']}
+ after do
+ SiteHook::Log.access.log "#{status}"
end
+ resource :webhook do
+ route_param :hook_name do
+ get do
+ STDOUT.puts params[:hook_name]
+ project = SiteHook::Config.projects.find_project(StrExt.mkvar(params[:hook_name]))
+ if project.nil?
+ {message: 'project not found or private', status: 1, project: {}}
+ else
+ project_obj = {}
+ %i[src dst repo host].each do |option|
+ project_obj[option] = project.instance_variable_get(StrExt.mkvar(option))
+ end
+ {project: project_obj}
+ end
+ end
+ post do
+ service = nil
+ request.body.rewind
+ req_body = request.body.read
+ project = SiteHook::Config.projects.get(StrExt.mkvar(params[:hook_name]))
+ CONTENT_TYPE = 'Content-Type'
+ if project == :not_found
+ halt 404, {message: 'no such project', status: 1}.to_json, {CONTENT_TYPE => APPLICATION_JSON}
+ elsif project == :no_projects
+ halt 500, {message: 'no projects defined', status: 2}.to_json, {CONTENT_TYPE => APPLICATION_JSON}
+ end
+ plaintext = false
+ signature = nil
+ event = nil
+ gogs = request.env.fetch('HTTP_X_GOGS_EVENT', nil)
+ unless gogs.nil?
+ event = 'push' if gogs == 'push'
+ end
+ github = request.env.fetch('HTTP_X_GITHUB_EVENT', nil)
+ unless github.nil?
+ event = 'push' if github == 'push'
+ end
+ gitlab = request.env.fetch('HTTP_X_GITLAB_EVENT', nil)
+ unless gitlab.nil?
+ event = 'push' if gitlab == 'push'
+ end
- get '/webhook/*' do
- if params[:splat]
- pass
- else
- halt 405, {CONTENT_TYPE => APPLICATION_JSON}, {message: 'GET not allowed'}.to_json
- end
- end
- post '/webhook/:hook_name/?' do
- service = nil
- request.body.rewind
- req_body = request.body.read
- js = RecursiveOpenStruct.new(JSON.parse(req_body))
+ events = {'github' => github, 'gitlab' => gitlab, 'gogs' => gogs}
+ if events['github'] && events['gogs']
+ events['github'] = nil
+ end
+ events_m_e = events.values.one?
+ case events_m_e
+ when true
+ event = 'push'
+ service = events.select { |_key, value| value }.keys.first
+ when false
+ halt 400, {message: 'events are mutually exclusive', status: 'failure'}.to_json, {CONTENT_TYPE => APPLICATION_JSON}
- projects = JPHRC['projects']
- project = projects.fetch(params[:hook_name], nil)
- if project.nil?
- halt 404, {CONTENT_TYPE => APPLICATION_JSON}, {message: 'no such project', status: 1}.to_json
- end
- plaintext = false
- signature = nil
- event = nil
- gogs = request.env.fetch('HTTP_X_GOGS_EVENT', nil)
- unless gogs.nil?
- event = 'push' if gogs == 'push'
- end
- github = request.env.fetch('HTTP_X_GITHUB_EVENT', nil)
- unless github.nil?
- event = 'push' if github == 'push'
- end
- gitlab = request.env.fetch('HTTP_X_GITLAB_EVENT', nil)
- unless gitlab.nil?
- event = 'push' if gitlab == 'push'
- end
+ else
+ halt 400, {'status': 'failure', 'message': 'something weird happened'}, {CONTENT_TYPE => APPLICATION_JSON}
+ end
+ if event != 'push' && event.nil?
+ halt 400, {message: 'no event header', status: 'failure'}.to_json, {CONTENT_TYPE => APPLICATION_JSON}
+ end
+ case service
+ when 'gitlab'
+ signature = request.env.fetch('HTTP_X_GITLAB_TOKEN', '')
+ plaintext = true
+ when 'github'
+ signature = request.env.fetch('HTTP_X_HUB_SIGNATURE', '').sub!(/^sha1=/, '')
+ plaintext = false
- events = {'github' => github, 'gitlab' => gitlab, 'gogs' => gogs}
- if events['github'] && events['gogs']
- events['github'] = nil
- end
- events_m_e = events.values.one?
- case events_m_e
- when true
- event = 'push'
- service = events.select { |_key, value| value }.keys.first
- when false
- halt 400, {CONTENT_TYPE: APPLICATION_JSON}, {message: 'events are mutually exclusive', status: 'failure'}.to_json
-
- else
- halt 400,
- {CONTENT_TYPE: APPLICATION_JSON},
- 'status': 'failure', 'message': 'something weird happened'
- end
- if event != 'push' && event.nil?
- halt 400, {CONTENT_TYPE: APPLICATION_JSON}, {message: 'no event header'}.to_json
- end
- case service
- when 'gitlab'
- signature = request.env.fetch('HTTP_X_GITLAB_TOKEN', '')
- plaintext = true
- when 'github'
- signature = request.env.fetch('HTTP_X_HUB_SIGNATURE', '').sub!(/^sha1=/, '')
- plaintext = false
-
- when 'gogs'
- signature = request.env.fetch('HTTP_X_GOGS_SIGNATURE', '')
- plaintext = false
- else
- # This shouldn't happen
- end
- if Webhook.verified?(req_body.to_s, signature, project['hookpass'], plaintext: plaintext, service: service)
- BUILDLOG.info 'Building...'
- begin
- jekyll_status = SiteHook::Senders::Jekyll.build(project['src'], project['dst'], BUILDLOG, options: {config: project['config']})
- case jekyll_status
-
- when 0
- status 200
- headers CONTENT_TYPE => APPLICATION_JSON
- body { {'status': 'success'}.to_json }
- when -1, -2, -3
- halt 400, {CONTENT_TYPE => APPLICATION_JSON}, {'status': 'exception', error: jekyll_status.fetch(:message).to_s}
+ when 'gogs'
+ signature = request.env.fetch('HTTP_X_GOGS_SIGNATURE', '')
+ plaintext = false
else
# This shouldn't happen
end
+ if Server.verified?(req_body.to_s, signature, project.hookpass, plaintext: plaintext, service: service)
+ SiteHook::Log.build.info 'Building...'
+ begin
+ jekyll_status = SiteHook::Senders::Jekyll.build(project.src, project.dst, SiteHook::Log.build, options: {config: project.config})
+ case jekyll_status[:status]
- rescue => e
- halt 500, {CONTENT_TYPE => APPLICATION_JSON}, {'status': 'exception', error: e.to_s}
-
+ when 0
+ status 200
+ {status: 'success'}
+ when -1, -2, -3
+ halt 400, {'status': 'exception', error: jekyll_status.fetch(:message).to_s}, {CONTENT_TYPE => APPLICATION_JSON}
+ else
+ # This shouldn't happen
+ end
+ rescue => e
+ halt 500, {'status': 'exception', error: e.to_s}, {CONTENT_TYPE => APPLICATION_JSON}
+ end
+ else
+ halt 403, {message: 'incorrect secret', 'status': 'failure'}.to_json, {CONTENT_TYPE => APPLICATION_JSON}
+ end
end
-
- else
- halt 403, {CONTENT_TYPE => APPLICATION_JSON}, {message: 'incorrect secret', 'status': 'failure'}.to_json
end
end
- post '/webhook/?' do
- halt 403, {CONTENT_TYPE => APPLICATION_JSON}, {message: 'pick a hook', error: 'root webhook hit', 'status': 'failure'}.to_json
+
+ resource :webhooks do
+ get do
+ SiteHook::Config.projects.to_h
+ end
+
end
end
end