Class: Webhookdb::ServiceIntegration
- Inherits:
-
Object
- Object
- Webhookdb::ServiceIntegration
- Defined in:
- lib/webhookdb/service_integration.rb
Defined Under Namespace
Classes: Stats, TableRenameError
Constant Summary collapse
- INTEGRATION_INFO_FIELDS =
We limit the information that a user can access through the CLI to these fields. Blank string returns all info.
["id", "service", "table", "url", "webhook_secret", ""].freeze
Instance Attribute Summary collapse
-
#api_url ⇒ String
Root Url of the api to backfill from.
-
#backfill_key ⇒ String
Key for backfilling.
-
#backfill_secret ⇒ String
Password/secret for backfilling.
-
#data_encryption_secret ⇒ String
The encryption key used to encrypt data for this organization.
- #depends_on ⇒ Webhookdb::ServiceIntegration
- #opaque_id ⇒ String
- #organization ⇒ Webhookdb::Organization
-
#service_name ⇒ String
Lookup name of the service.
-
#skip_webhook_verification ⇒ Boolean
Set this to disable webhook verification on this integration.
-
#table_name ⇒ String
Name of the table.
-
#webhook_secret ⇒ String
Secret used to sign webhooks.
Class Method Summary collapse
Instance Method Summary collapse
- #authed_api_path ⇒ Object
-
#before_create ⇒ Object
:Sequel Hooks:.
- #can_be_modified_by?(customer) ⇒ Boolean
-
#dependency_candidates ⇒ Array<Webhookdb::ServiceIntegration>
Return service integrations that can be used as the dependency for this integration.
- #destroy_self_and_all_dependents ⇒ Object
- #ensure_sequence(skip_check: false) ⇒ Object
- #ensure_sequence_sql(skip_check: false) ⇒ Object
- #log_tags ⇒ Object
- #plan_supports_integration? ⇒ Boolean
- #recursive_dependents ⇒ Object
- #rename_table(to:) ⇒ Object
- #replicator ⇒ Webhookdb::Replicator::Base
- #requires_sequence? ⇒ Boolean
- #sequence_name ⇒ Object
- #sequence_nextval ⇒ Object
- #stats ⇒ Webhookdb::ServiceIntegration::Stats
- #unauthed_webhook_endpoint ⇒ Object
- #unauthed_webhook_path ⇒ Object
Instance Attribute Details
#api_url ⇒ String
Returns Root Url of the api to backfill from.
|
# File 'lib/webhookdb/service_integration.rb', line 277
|
#backfill_key ⇒ String
Returns Key for backfilling.
|
# File 'lib/webhookdb/service_integration.rb', line 280
|
#backfill_secret ⇒ String
Returns Password/secret for backfilling.
|
# File 'lib/webhookdb/service_integration.rb', line 283
|
#data_encryption_secret ⇒ String
Returns The encryption key used to encrypt data for this organization. Note that this field is itself encrypted using Sequel encryption; its decrypted value is meant to be used as the data encryption key.
|
# File 'lib/webhookdb/service_integration.rb', line 292
|
#opaque_id ⇒ String
|
# File 'lib/webhookdb/service_integration.rb', line 274
|
#service_name ⇒ String
Returns Lookup name of the service.
|
# File 'lib/webhookdb/service_integration.rb', line 271
|
#skip_webhook_verification ⇒ Boolean
Returns Set this to disable webhook verification on this integration. Useful when replaying logged webhooks.
|
# File 'lib/webhookdb/service_integration.rb', line 297
|
#table_name ⇒ String
Returns Name of the table.
|
# File 'lib/webhookdb/service_integration.rb', line 268
|
#webhook_secret ⇒ String
Returns Secret used to sign webhooks.
|
# File 'lib/webhookdb/service_integration.rb', line 286
|
Class Method Details
.create_disambiguated(service_name, **kwargs) ⇒ Object
67 68 69 70 |
# File 'lib/webhookdb/service_integration.rb', line 67 def self.create_disambiguated(service_name, **kwargs) kwargs[:table_name] ||= "#{service_name}_#{SecureRandom.hex(2)}" return self.create(service_name:, **kwargs) end |
Instance Method Details
#authed_api_path ⇒ Object
90 91 92 |
# File 'lib/webhookdb/service_integration.rb', line 90 def authed_api_path return "/v1/organizations/#{self.organization_id}/service_integrations/#{self.opaque_id}" end |
#before_create ⇒ Object
:Sequel Hooks:
261 262 263 |
# File 'lib/webhookdb/service_integration.rb', line 261 def before_create self[:opaque_id] ||= Webhookdb::Id.new_opaque_id("svi") end |
#can_be_modified_by?(customer) ⇒ Boolean
72 73 74 |
# File 'lib/webhookdb/service_integration.rb', line 72 def can_be_modified_by?(customer) return customer.verified_member_of?(self.organization) end |
#dependency_candidates ⇒ Array<Webhookdb::ServiceIntegration>
Return service integrations that can be used as the dependency for this integration.
120 121 122 123 124 125 |
# File 'lib/webhookdb/service_integration.rb', line 120 def dependency_candidates dep_descr = self.replicator.descriptor.dependency_descriptor return [] if dep_descr.nil? return self.organization.service_integrations. select { |si| si.service_name == dep_descr.name } end |
#destroy_self_and_all_dependents ⇒ Object
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/webhookdb/service_integration.rb', line 131 def destroy_self_and_all_dependents self.dependents.each(&:destroy_self_and_all_dependents) begin self.replicator.admin_dataset(timeout: :fast) { |ds| ds.db << "DROP TABLE #{self.table_name}" } rescue Sequel::DatabaseError => e raise unless e.wrapped_exception.is_a?(PG::UndefinedTable) end self.destroy end |
#ensure_sequence(skip_check: false) ⇒ Object
243 244 245 |
# File 'lib/webhookdb/service_integration.rb', line 243 def ensure_sequence(skip_check: false) self.db << self.ensure_sequence_sql(skip_check:) end |
#ensure_sequence_sql(skip_check: false) ⇒ Object
247 248 249 250 251 |
# File 'lib/webhookdb/service_integration.rb', line 247 def ensure_sequence_sql(skip_check: false) raise Webhookdb::InvalidPrecondition, "#{self.service_name} does not require sequence" if !skip_check && !self.requires_sequence? return "CREATE SEQUENCE IF NOT EXISTS #{self.sequence_name}" end |
#log_tags ⇒ Object
81 82 83 84 85 86 87 88 |
# File 'lib/webhookdb/service_integration.rb', line 81 def return { service_integration_id: self.id, service_integration_name: self.service_name, service_integration_table: self.table_name, **self.organization., } end |
#plan_supports_integration? ⇒ Boolean
102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/webhookdb/service_integration.rb', line 102 def plan_supports_integration? # if the sint's organization has an active subscription, return true return true if self.organization.active_subscription? # if there is no active subscription, check whether the integration is one of the first two # created by the organization limit = Webhookdb::Subscription.max_free_integrations free_integrations = Webhookdb::ServiceIntegration. where(organization: self.organization).order(:created_at, :id).limit(limit).all free_integrations.each do |sint| return true if sint.id == self.id end # if not, the integration is not supported return false end |
#recursive_dependents ⇒ Object
127 128 129 |
# File 'lib/webhookdb/service_integration.rb', line 127 def recursive_dependents return self.dependents + self.dependents.flat_map(&:recursive_dependents) end |
#rename_table(to:) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/webhookdb/service_integration.rb', line 209 def rename_table(to:) Webhookdb::Organization::DatabaseMigration.guard_ongoing!(self.organization) unless Webhookdb::DBAdapter::VALID_IDENTIFIER.match?(to) msg = "Sorry, this is not a valid table name. " + Webhookdb::DBAdapter::INVALID_IDENTIFIER_MESSAGE msg += " And we see you what you did there ;)" if to.include?(";") && to.downcase.include?("drop") raise TableRenameError, msg end self.db.transaction do begin self.organization.admin_connection { |db| db << "ALTER TABLE #{self.table_name} RENAME TO #{to}" } rescue Sequel::DatabaseError => e case e.wrapped_exception when PG::DuplicateTable raise TableRenameError, "There is already a table named \"#{to}\". Run `webhookdb db tables` to see available tables." when PG::SyntaxError raise TableRenameError, "Please try again with double quotes around '#{to}' since it contains invalid identifier characters." else raise e end end self.update(table_name: to) end end |
#replicator ⇒ Webhookdb::Replicator::Base
77 78 79 |
# File 'lib/webhookdb/service_integration.rb', line 77 def replicator return Webhookdb::Replicator.create(self) end |
#requires_sequence? ⇒ Boolean
235 236 237 |
# File 'lib/webhookdb/service_integration.rb', line 235 def requires_sequence? return self.replicator.requires_sequence? end |
#sequence_name ⇒ Object
239 240 241 |
# File 'lib/webhookdb/service_integration.rb', line 239 def sequence_name return "replicator_seq_org_#{self.organization_id}_#{self.service_name}_#{self.id}_seq" end |
#sequence_nextval ⇒ Object
253 254 255 |
# File 'lib/webhookdb/service_integration.rb', line 253 def sequence_nextval return self.db.select(Sequel.function(:nextval, self.sequence_name)).single_value end |
#stats ⇒ Webhookdb::ServiceIntegration::Stats
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/webhookdb/service_integration.rb', line 168 def stats all_logged_webhooks = Webhookdb::LoggedWebhook.where( service_integration_opaque_id: self.opaque_id, ).where { inserted_at > 7.days.ago } if all_logged_webhooks.empty? return Stats.new( "We have no record of receiving webhooks for that integration in the past seven days.", {}, ) end # rubocop:disable Naming/VariableNumber count_last_7_days = all_logged_webhooks.count rejected_last_7_days = all_logged_webhooks.where { response_status >= 400 }.count success_last_7_days = (count_last_7_days - rejected_last_7_days) rejected_last_7_days_percent = (rejected_last_7_days.to_f / count_last_7_days) success_last_7_days_percent = (success_last_7_days.to_f / count_last_7_days) last_10 = Webhookdb::LoggedWebhook.order_by(Sequel.desc(:inserted_at)).limit(10).select_map(:response_status) last_10_success, last_10_rejected = last_10.partition { |rs| rs < 400 } data = { count_last_7_days:, count_last_7_days_formatted: count_last_7_days.to_s, success_last_7_days:, success_last_7_days_formatted: success_last_7_days.to_s, success_last_7_days_percent:, success_last_7_days_percent_formatted: "%.1f%%" % (success_last_7_days_percent * 100), rejected_last_7_days:, rejected_last_7_days_formatted: rejected_last_7_days.to_s, rejected_last_7_days_percent:, rejected_last_7_days_percent_formatted: "%.1f%%" % (rejected_last_7_days_percent * 100), successful_of_last_10: last_10_success.size, successful_of_last_10_formatted: last_10_success.size.to_s, rejected_of_last_10: last_10_rejected.size, rejected_of_last_10_formatted: last_10_rejected.size.to_s, } # rubocop:enable Naming/VariableNumber return Stats.new("", data) end |
#unauthed_webhook_endpoint ⇒ Object
98 99 100 |
# File 'lib/webhookdb/service_integration.rb', line 98 def unauthed_webhook_endpoint return Webhookdb.api_url + self.unauthed_webhook_path end |
#unauthed_webhook_path ⇒ Object
94 95 96 |
# File 'lib/webhookdb/service_integration.rb', line 94 def unauthed_webhook_path return "/v1/service_integrations/#{self.opaque_id}" end |