Skip to content

Commit

Permalink
Add Sentry Oauth Installation Hook (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
armiiller authored Oct 18, 2023
1 parent 400ef61 commit 1df1249
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 22 deletions.
144 changes: 141 additions & 3 deletions app/models/pager_tree/integrations/sentry/v3.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
module PagerTree::Integrations
class Sentry::V3 < Integration
OPTIONS = [
{key: :client_secret, type: :string, default: nil}
{key: :client_secret, type: :string, default: nil},
{key: :authorization_token, type: :string, default: nil},
{key: :authorization_token_expires_at, type: :string, default: nil},
{key: :authorization_refresh_token, type: :string, default: nil},
{key: :code, type: :string, default: nil}
]
store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"

after_initialize do
end

after_create_commit do
verify_installation if initialize_authorization_token!
end

def adapter_should_block_incoming?(request)
should_block = false
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/#sentry-hook-signature
Expand Down Expand Up @@ -53,8 +61,134 @@ def adapter_process_create
)
end

def adapter_process_other
_installation_process_other if installation?
end

def verify_installation
if thirdparty_id.present?
HTTParty.put("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/",
headers: {
"Content-Type" => "application/json",
"Authorization" => "Bearer #{option_authorization_token}"
}, body: {
status: "installed"
}.to_json)

return true
end

false
rescue => e
Rails.logger.error("Error sending Sentry App Installation Confirmation: #{e.message}")
false
end

def initialize_authorization_token!
if thirdparty_id.present? && option_code.present?
response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/",
headers: {
"Content-Type" => "application/json"
}, body: {
grant_type: "authorization_code",
code: option_code,
client_id: PagerTree::Integrations.integration_sentry_v3_client_id,
client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret
}.to_json)

if response.code == 201
json = JSON.parse(response.body)
self.option_authorization_token = json.dig("token")
self.option_authorization_refresh_token = json.dig("refreshToken")
self.option_authorization_token_expires_at = json.dig("expiresAt")
save!

return true
end
end

false
rescue => e
Rails.logger.error("Error initializing Sentry App Authorization Token: #{e.message}")
false
end

def refresh_authorization_token!
if thirdparty_id.present? && option_authorization_refresh_token.present?
response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/",
headers: {
"Content-Type" => "application/json"
}, body: {
grant_type: "refresh_token",
refresh_token: option_authorization_refresh_token,
client_id: PagerTree::Integrations.integration_sentry_v3_client_id,
client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret
}.to_json)

if response.code == 201
json = JSON.parse(response.body)
self.option_authorization_token = json.dig("token")
self.option_authorization_refresh_token = json.dig("refreshToken")
self.option_authorization_token_expires_at = json.dig("expiresAt")
save!

return true
end
end

false
rescue => e
Rails.logger.error("Error refreshing Sentry App Authorization Token: #{e.message}")
false
end

private

############################
# START INSTALLATION
# https://docs.sentry.io/product/integrations/integration-platform/webhooks/installation/
############################

def _installation_adapter_thirdparty_id
incoming_json.dig("id")
end

def _installation_adapter_action
:other
end

def _installation_title
""
end

def _installation_description
""
end

def _installation_additional_datums
[]
end

def _installation_dedup_keys
[]
end

def _installation_process_other
action = incoming_json.dig("action")
if action == "created"
# intentionally left blank
elsif action == "deleted"
# clear the thirdparty id off this integration and save
self.thirdparty_id = nil
self.discarded_at = Time.current
save!
end
end

############################
# END Installation
############################

############################
# START WEBHOOK
# Undocumented webhook format (this is what you get when you just signup for a trial)
Expand Down Expand Up @@ -89,7 +223,7 @@ def _webhook_dedup_keys
end

############################
# END ISSUE
# END WEBHOOK
############################

############################
Expand Down Expand Up @@ -320,12 +454,16 @@ def error?
hook_resource == "error"
end

def installation?
hook_resource == "installation"
end

def webhook?
incoming_headers["HTTP_SENTRY_HOOK_RESOURCE"].blank? && (hook_resource == "webhook")
end

def should_process?
issue? || event_alert? || metric_alert? || error? || webhook?
issue? || event_alert? || metric_alert? || error? || installation? || webhook?
end

def action
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="form-group">
<%= form.label :option_client_secret %>
<%= form.text_field :option_client_secret, class: "form-control" %>
<p class="form-hint"><%== t(".option_client_secret_hint_html") %></p>
</div>
</div>
<%= form.hidden_field :option_code, class: "form-control" %>
Original file line number Diff line number Diff line change
@@ -1,12 +1 @@
<div class="sm:col-span-2">
<dt class="text-sm font-medium text-gray-500">
<%= t("activerecord.attributes.pager_tree/integrations/sentry/v3.option_client_secret") %>
</dt>
<dd class="mt-1 text-sm text-gray-900">
<div class="flex items-center gap-2">
<p class="text-sm truncate">
<%= mask integration.option_client_secret %>
</p>
</div>
</dd>
</div>

6 changes: 6 additions & 0 deletions lib/pager_tree/integrations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@ module Integrations

mattr_accessor :integration_email_v3_inbox
@@integration_email_v3_inbox = "a"

mattr_accessor :integration_sentry_v3_client_id
@@integration_sentry_v3_client_id = ""

mattr_accessor :integration_sentry_v3_client_secret
@@integration_sentry_v3_client_secret = ""
end
end

0 comments on commit 1df1249

Please sign in to comment.