Module: Sinatra::Slack::InstanceHelpers
- Defined in:
- lib/sinatra/slack/instance_helpers.rb
Overview
Instance level helper methods
Instance Method Summary collapse
- #action ⇒ Object
-
#authorized? ⇒ Boolean
Checks for Slack defined HTTP headers and computes the request signature (HMAC).
- #channel ⇒ Object
- #command ⇒ Object
- #compute_signature(secret) ⇒ Object
- #handle_request(request_handler:, request_params:, quick_reply: '...') ⇒ Object
- #handle_with_rescue ⇒ Object
- #hmac_signed(to_sign, hmac_key) ⇒ Object
- #slack_error_notification ⇒ Object
- #slack_response(callback_id) {|s_resp| ... } ⇒ Object
-
#slack_signature ⇒ Object
Helper methods for Slack request validation.
- #slack_timestamp ⇒ Object
- #valid_headers? ⇒ Boolean
Instance Method Details
#action ⇒ Object
16 17 18 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 16 def action @action ||= Helpers::ActionRequest.parse(params) end |
#authorized? ⇒ Boolean
Checks for Slack defined HTTP headers and computes the request signature (HMAC). If provided signature is the same as the computed one, the request is valid.
Go to this page for the verification process: api.slack.com/docs/verifying-requests-from-slack
62 63 64 65 66 67 68 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 62 def logger.warn 'Missing Slack signing token' unless settings.slack_secret return true unless settings.slack_secret valid_headers? && compute_signature(settings.slack_secret) == slack_signature end |
#channel ⇒ Object
20 21 22 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 20 def channel @channel ||= Helpers::Channel.parse(params) end |
#command ⇒ Object
12 13 14 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 12 def command @command ||= Helpers::CommandRequest.new(params) end |
#compute_signature(secret) ⇒ Object
87 88 89 90 91 92 93 94 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 87 def compute_signature(secret) # in case someone already read it request.body.rewind # From Slack API docs, the "v0" is always fixed for now sig_basestring = "v0:#{slack_timestamp}:#{request.body.read}" "v0=#{hmac_signed(sig_basestring, secret)}" end |
#handle_request(request_handler:, request_params:, quick_reply: '...') ⇒ Object
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 36 def handle_request(request_handler:, request_params:, quick_reply: '...') EM.defer do handle_with_rescue do = request_handler.bind(self).call(*request_params) channel.send() end end body quick_reply end |
#handle_with_rescue ⇒ Object
47 48 49 50 51 52 53 54 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 47 def handle_with_rescue return unless block_given? yield rescue StandardError => ex logger.error ex. channel.send(slack_error_notification) end |
#hmac_signed(to_sign, hmac_key) ⇒ Object
96 97 98 99 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 96 def hmac_signed(to_sign, hmac_key) sha256 = OpenSSL::Digest.new('sha256') OpenSSL::HMAC.hexdigest(sha256, hmac_key, to_sign) end |
#slack_error_notification ⇒ Object
30 31 32 33 34 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 30 def slack_error_notification slack_response '' do |r| r.text = 'Ups, something went wrong' end end |
#slack_response(callback_id) {|s_resp| ... } ⇒ Object
24 25 26 27 28 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 24 def slack_response(callback_id) s_resp = Helpers::SlackResponse.new(callback_id) yield s_resp if block_given? s_resp end |
#slack_signature ⇒ Object
Helper methods for Slack request validation
71 72 73 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 71 def slack_signature @slack_signature ||= env['HTTP_X_SLACK_SIGNATURE'] end |
#slack_timestamp ⇒ Object
75 76 77 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 75 def ||= env['HTTP_X_SLACK_REQUEST_TIMESTAMP'] end |
#valid_headers? ⇒ Boolean
79 80 81 82 83 84 85 |
# File 'lib/sinatra/slack/instance_helpers.rb', line 79 def valid_headers? return false unless slack_signature || # The request timestamp is more than five minutes from local time. # It could be a replay attack, so let's ignore it. (Time.now.to_i - .to_i).abs <= 60 * 5 end |