Module: Codebot::WebListener

Defined in:
lib/codebot/web_listener.rb

Overview

This module provides methods for processing incoming webhooks and dispatching them to the IRC client.

Instance Method Summary collapse

Instance Method Details

#create_github_event(request) ⇒ Object



58
59
60
61
62
63
# File 'lib/codebot/web_listener.rb', line 58

def create_github_event(request)
  event = request.env['HTTP_X_GITHUB_EVENT']
  return [400, 'Missing event header'] if event.nil? || event.empty?

  Event.symbolize(event)
end

#create_gitlab_event(request) ⇒ Object



51
52
53
54
55
56
# File 'lib/codebot/web_listener.rb', line 51

def create_gitlab_event(request)
  event = request.env['HTTP_X_GITLAB_EVENT']
  return [400, 'Missing event header'] if event.nil? || event.empty?

  Event.symbolize("Gitlab #{event}".tr(' ', '_'))
end

#create_request(integration, request, payload) ⇒ Request, Array<Integer, String>

Creates a new request for the webhook.

Parameters:

  • integration (Integration)

    the integration for which the request was made

  • request (Sinatra::Request)

    the request received by the web server

  • payload (String)

    the payload that was sent to the endpoint

Returns:

  • (Request, Array<Integer, String>)

    the created request, or an array containing HTTP status code and response if the request was invalid



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/codebot/web_listener.rb', line 75

def create_request(integration, request, payload)
  event = if integration.gitlab
            create_gitlab_event(request)
          else
            create_github_event(request)
          end
  return event if event.is_a? Array

  return [501, 'Event not yet supported'] if event.nil?

  Request.new(integration, event, payload)
end

#dispatch(core, request, endpoint, payload) ⇒ Array<Integer, String>

Dispatches a received payload to the IRC client.

Parameters:

  • core (Core)

    the bot to dispatch this request to

  • request (Sinatra::Request)

    the request received by the web server

  • endpoint (String)

    the endpoint at which the request was received

  • payload (String)

    the payload that was sent to the endpoint

Returns:

  • (Array<Integer, String>)

    HTTP status code and response



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/codebot/web_listener.rb', line 39

def dispatch(core, request, endpoint, payload)
  intg = integration_for(core.config, endpoint)
  return [404, 'Endpoint not registered'] if intg.nil?
  return [403, 'Invalid signature'] unless valid?(request, intg, payload)

  req = create_request(intg, request, payload)
  return req if req.is_a? Array

  core.irc_client.dispatch(req)
  [202, 'Accepted']
end

#handle_post(core, request, params) ⇒ Object

Handles a POST request.

Parameters:

  • core (Core)

    the bot to dispatch requests to

  • request (Sinatra::Request)

    the request to handle

  • params (Hash)

    the request parameters



17
18
19
20
21
22
# File 'lib/codebot/web_listener.rb', line 17

def handle_post(core, request, params)
  payload = params['payload'] || request.body.read
  dispatch(core, request, *params['splat'], payload)
rescue JSON::ParserError
  [400, 'Invalid JSON payload']
end

#integration_for(config, endpoint) ⇒ Object

Finds the integration associated with an endpoint.

Parameters:

  • config (Config)

    the configuration containing the integrations

  • endpoint (String)

    the endpoint



28
29
30
# File 'lib/codebot/web_listener.rb', line 28

def integration_for(config, endpoint)
  IntegrationManager.new(config).find_integration_by_endpoint(endpoint)
end

#valid?(request, integration, payload) ⇒ Boolean

Verifies a webhook signature.

Parameters:

  • request (Sinatra::Request)

    the request received by the web server

  • integration (Integration)

    the integration for which the request was made

  • payload (String)

    the payload that was sent to the endpoint

Returns:

  • (Boolean)

    whether the signature is valid



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/codebot/web_listener.rb', line 95

def valid?(request, integration, payload)
  return true unless integration.verify_payloads?

  secret = integration.secret
  if integration.gitlab
    secret == request.env['HTTP_X_GITLAB_TOKEN']
  else
    request_signature = request.env['HTTP_X_HUB_SIGNATURE']
    Cryptography.valid_signature?(payload, secret, request_signature)
  end
end