class Issue::Webhook
Attributes
accept_events[RW]
accept_origin[RW]
discard_sender[RW]
error[RW]
payload[RW]
request[RW]
secret_token[RW]
Public Class Methods
new(settings={})
click to toggle source
Initialize the Issue::Webhook
object This method should receive a Hash with the following settings:
* secret_token: the GitHub secret token needed to verify the request signature * accept_events: an Array of valid values for the HTTP_X_GITHUB_EVENT header. If empty any event will be precessed. * origin: the respository where the webhook should be sent to be accepted. If empty any request will be precessed. * discard_sender: an optional GitHub user handle to discard all events triggered by it.
# File lib/issue/webhook.rb, line 22 def initialize(settings={}) @secret_token = settings[:secret_token] @accept_origin = settings[:origin] @discard_sender = settings[:discard_sender] @accept_events = [settings[:accept_events]].flatten.compact.uniq.map(&:to_s) end
Public Instance Methods
errored?()
click to toggle source
This method returns True if parsing a request has generated an Issue::Error
object That object will be available at the error
accessor method.
# File lib/issue/webhook.rb, line 50 def errored? !error.nil? end
parse_request(request)
click to toggle source
This method will parse the passed request. If the request signature is incorrect or any of the conditions set via the initialization settings are not met an error will be created with the appropiate html status and message. Otherwise a Issue::Payload
object will be created with the information contained in the request payload.
This method returns a pair [payload, error] where only one of them will be nil
# File lib/issue/webhook.rb, line 36 def parse_request(request) @payload = nil @error = nil @request = request if verify_signature parse_payload end return [payload, error] end
Private Instance Methods
error!(status, msg)
click to toggle source
# File lib/issue/webhook.rb, line 87 def error!(status, msg) @error = Issue::Error.new(status, msg) false end
parse_payload()
click to toggle source
# File lib/issue/webhook.rb, line 67 def parse_payload begin request.body.rewind json_payload = JSON.parse(request.body.read) event = request.get_header "HTTP_X_GITHUB_EVENT" sender = json_payload.dig("sender", "login") origin = json_payload.dig("repository", "full_name") rescue JSON::ParserError return error!(400, "Malformed request") end return error!(422, "No payload") if json_payload.nil? || json_payload.empty? return error!(422, "No event") if event.nil? return error!(200, "Event discarded") unless (accept_events.empty? || accept_events.include?(event)) return error!(200, "Event origin discarded") if (discard_sender && sender == discard_sender) return error!(403, "Event origin not allowed") if (accept_origin && origin != accept_origin) @payload = Issue::Payload.new(json_payload, event) end
verify_signature()
click to toggle source
# File lib/issue/webhook.rb, line 56 def verify_signature gh_signature = request.get_header "HTTP_X_HUB_SIGNATURE" return error!(500, "Can't compute signature") if secret_token.nil? || secret_token.empty? return error!(403, "Request missing signature") if gh_signature.nil? || gh_signature.empty? request.body.rewind payload_body = request.body.read signature = "sha1=" + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), secret_token, payload_body) return error!(403, "Signatures didn't match!") unless Rack::Utils.secure_compare(signature, gh_signature) true end