|
1 | 1 | module PagerTree::Integrations
|
2 | 2 | class Sentry::V3 < Integration
|
3 | 3 | OPTIONS = [
|
4 |
| - {key: :client_secret, type: :string, default: nil} |
| 4 | + {key: :client_secret, type: :string, default: nil}, |
| 5 | + {key: :authorization_token, type: :string, default: nil}, |
| 6 | + {key: :authorization_token_expires_at, type: :string, default: nil}, |
| 7 | + {key: :authorization_refresh_token, type: :string, default: nil}, |
| 8 | + {key: :code, type: :string, default: nil} |
5 | 9 | ]
|
6 | 10 | store_accessor :options, *OPTIONS.map { |x| x[:key] }.map(&:to_s), prefix: "option"
|
7 | 11 |
|
8 | 12 | after_initialize do
|
9 | 13 | end
|
10 | 14 |
|
| 15 | + after_create_commit do |
| 16 | + verify_installation if initialize_authorization_token! |
| 17 | + end |
| 18 | + |
11 | 19 | def adapter_should_block_incoming?(request)
|
12 | 20 | should_block = false
|
13 | 21 | # https://docs.sentry.io/product/integrations/integration-platform/webhooks/#sentry-hook-signature
|
@@ -53,8 +61,134 @@ def adapter_process_create
|
53 | 61 | )
|
54 | 62 | end
|
55 | 63 |
|
| 64 | + def adapter_process_other |
| 65 | + _installation_process_other if installation? |
| 66 | + end |
| 67 | + |
| 68 | + def verify_installation |
| 69 | + if thirdparty_id.present? |
| 70 | + HTTParty.put("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/", |
| 71 | + headers: { |
| 72 | + "Content-Type" => "application/json", |
| 73 | + "Authorization" => "Bearer #{option_authorization_token}" |
| 74 | + }, body: { |
| 75 | + status: "installed" |
| 76 | + }.to_json) |
| 77 | + |
| 78 | + return true |
| 79 | + end |
| 80 | + |
| 81 | + false |
| 82 | + rescue => e |
| 83 | + Rails.logger.error("Error sending Sentry App Installation Confirmation: #{e.message}") |
| 84 | + false |
| 85 | + end |
| 86 | + |
| 87 | + def initialize_authorization_token! |
| 88 | + if thirdparty_id.present? && option_code.present? |
| 89 | + response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/", |
| 90 | + headers: { |
| 91 | + "Content-Type" => "application/json" |
| 92 | + }, body: { |
| 93 | + grant_type: "authorization_code", |
| 94 | + code: option_code, |
| 95 | + client_id: PagerTree::Integrations.integration_sentry_v3_client_id, |
| 96 | + client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret |
| 97 | + }.to_json) |
| 98 | + |
| 99 | + if response.code == 201 |
| 100 | + json = JSON.parse(response.body) |
| 101 | + self.option_authorization_token = json.dig("token") |
| 102 | + self.option_authorization_refresh_token = json.dig("refreshToken") |
| 103 | + self.option_authorization_token_expires_at = json.dig("expiresAt") |
| 104 | + save! |
| 105 | + |
| 106 | + return true |
| 107 | + end |
| 108 | + end |
| 109 | + |
| 110 | + false |
| 111 | + rescue => e |
| 112 | + Rails.logger.error("Error initializing Sentry App Authorization Token: #{e.message}") |
| 113 | + false |
| 114 | + end |
| 115 | + |
| 116 | + def refresh_authorization_token! |
| 117 | + if thirdparty_id.present? && option_authorization_refresh_token.present? |
| 118 | + response = HTTParty.post("https://sentry.io/api/0/sentry-app-installations/#{thirdparty_id}/authorizations/", |
| 119 | + headers: { |
| 120 | + "Content-Type" => "application/json" |
| 121 | + }, body: { |
| 122 | + grant_type: "refresh_token", |
| 123 | + refresh_token: option_authorization_refresh_token, |
| 124 | + client_id: PagerTree::Integrations.integration_sentry_v3_client_id, |
| 125 | + client_secret: PagerTree::Integrations.integration_sentry_v3_client_secret |
| 126 | + }.to_json) |
| 127 | + |
| 128 | + if response.code == 201 |
| 129 | + json = JSON.parse(response.body) |
| 130 | + self.option_authorization_token = json.dig("token") |
| 131 | + self.option_authorization_refresh_token = json.dig("refreshToken") |
| 132 | + self.option_authorization_token_expires_at = json.dig("expiresAt") |
| 133 | + save! |
| 134 | + |
| 135 | + return true |
| 136 | + end |
| 137 | + end |
| 138 | + |
| 139 | + false |
| 140 | + rescue => e |
| 141 | + Rails.logger.error("Error refreshing Sentry App Authorization Token: #{e.message}") |
| 142 | + false |
| 143 | + end |
| 144 | + |
56 | 145 | private
|
57 | 146 |
|
| 147 | + ############################ |
| 148 | + # START INSTALLATION |
| 149 | + # https://docs.sentry.io/product/integrations/integration-platform/webhooks/installation/ |
| 150 | + ############################ |
| 151 | + |
| 152 | + def _installation_adapter_thirdparty_id |
| 153 | + incoming_json.dig("id") |
| 154 | + end |
| 155 | + |
| 156 | + def _installation_adapter_action |
| 157 | + :other |
| 158 | + end |
| 159 | + |
| 160 | + def _installation_title |
| 161 | + "" |
| 162 | + end |
| 163 | + |
| 164 | + def _installation_description |
| 165 | + "" |
| 166 | + end |
| 167 | + |
| 168 | + def _installation_additional_datums |
| 169 | + [] |
| 170 | + end |
| 171 | + |
| 172 | + def _installation_dedup_keys |
| 173 | + [] |
| 174 | + end |
| 175 | + |
| 176 | + def _installation_process_other |
| 177 | + action = incoming_json.dig("action") |
| 178 | + if action == "created" |
| 179 | + # intentionally left blank |
| 180 | + elsif action == "deleted" |
| 181 | + # clear the thirdparty id off this integration and save |
| 182 | + self.thirdparty_id = nil |
| 183 | + self.discarded_at = Time.current |
| 184 | + save! |
| 185 | + end |
| 186 | + end |
| 187 | + |
| 188 | + ############################ |
| 189 | + # END Installation |
| 190 | + ############################ |
| 191 | + |
58 | 192 | ############################
|
59 | 193 | # START WEBHOOK
|
60 | 194 | # Undocumented webhook format (this is what you get when you just signup for a trial)
|
@@ -89,7 +223,7 @@ def _webhook_dedup_keys
|
89 | 223 | end
|
90 | 224 |
|
91 | 225 | ############################
|
92 |
| - # END ISSUE |
| 226 | + # END WEBHOOK |
93 | 227 | ############################
|
94 | 228 |
|
95 | 229 | ############################
|
@@ -320,12 +454,16 @@ def error?
|
320 | 454 | hook_resource == "error"
|
321 | 455 | end
|
322 | 456 |
|
| 457 | + def installation? |
| 458 | + hook_resource == "installation" |
| 459 | + end |
| 460 | + |
323 | 461 | def webhook?
|
324 | 462 | incoming_headers["HTTP_SENTRY_HOOK_RESOURCE"].blank? && (hook_resource == "webhook")
|
325 | 463 | end
|
326 | 464 |
|
327 | 465 | def should_process?
|
328 |
| - issue? || event_alert? || metric_alert? || error? || webhook? |
| 466 | + issue? || event_alert? || metric_alert? || error? || installation? || webhook? |
329 | 467 | end
|
330 | 468 |
|
331 | 469 | def action
|
|
0 commit comments