module ActiveHook module Client module Recieve REQUEST_HEADERS = { "Content-Type" => "application/json", "Accept" => "application/json", "User-Agent" => "ActiveHook/#{ActiveHook::VERSION}" }.freeze attr_accessor :request def initialize(options = {}) options.each { |key, value| send("#{key}=", value) } end def signature_valid? @signature_valid ||= validate_signature end def server_valid? @server_valid ||= validate_server end def payload parsed_body['payload'] rescue nil end def validated_payload raise StandardError, 'Webhook is invalid.' unless signature_valid? @payload end private def parsed_body @parsed_body ||= JSON.parse(request.body.read) rescue {} end def hook_id parsed_body['hook_id'] end def hook_key parsed_body['hook_key'] end def hook_uri @hook_uri ||= URI.parse(self.class::VALIDATION_URI) end def hook_signature @request.env['HTTP_X-Webhook-Signature'] end def validate_server http = Net::HTTP.new(hook_uri.host, hook_uri.port) response = http.post(hook_uri.path, hook_json, REQUEST_HEADERS) response.code.to_i == 200 ? true : false rescue false end def validate_signature signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), self.class::VALIDATION_TOKEN, payload) Rack::Utils.secure_compare(signature, hook_signature) rescue false end def hook_json { id: hook_id, key: hook_key }.to_json end end end class Recieve include ActiveHook::Client::Recieve VALIDATION_URI = (ActiveHook.config.validation_uri).freeze VALIDATION_TOKEN = (ActiveHook.config.validation_token).freeze end end