about summary refs log tree commit diff
path: root/app/models/webhook.rb
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2022-06-09 21:57:36 +0200
committerGitHub <noreply@github.com>2022-06-09 21:57:36 +0200
commita2871cd74719a7a5a104daaa3dcc0e2670b7c2df (patch)
treecfd30fe202cd5be1c2984f4031d825d950784da2 /app/models/webhook.rb
parent17ba5e1e616c853a389b9c24a347d873747f2126 (diff)
Add administrative webhooks (#18510)
* Add administrative webhooks

* Fix error when webhook is deleted before delivery worker runs
Diffstat (limited to 'app/models/webhook.rb')
-rw-r--r--app/models/webhook.rb58
1 files changed, 58 insertions, 0 deletions
diff --git a/app/models/webhook.rb b/app/models/webhook.rb
new file mode 100644
index 000000000..431edd75d
--- /dev/null
+++ b/app/models/webhook.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: webhooks
+#
+#  id         :bigint(8)        not null, primary key
+#  url        :string           not null
+#  events     :string           default([]), not null, is an Array
+#  secret     :string           default(""), not null
+#  enabled    :boolean          default(TRUE), not null
+#  created_at :datetime         not null
+#  updated_at :datetime         not null
+#
+
+class Webhook < ApplicationRecord
+  EVENTS = %w(
+    account.created
+    report.created
+  ).freeze
+
+  scope :enabled, -> { where(enabled: true) }
+
+  validates :url, presence: true, url: true
+  validates :secret, presence: true, length: { minimum: 12 }
+  validates :events, presence: true
+
+  validate :validate_events
+
+  before_validation :strip_events
+  before_validation :generate_secret
+
+  def rotate_secret!
+    update!(secret: SecureRandom.hex(20))
+  end
+
+  def enable!
+    update!(enabled: true)
+  end
+
+  def disable!
+    update!(enabled: false)
+  end
+
+  private
+
+  def validate_events
+    errors.add(:events, :invalid) if events.any? { |e| !EVENTS.include?(e) }
+  end
+
+  def strip_events
+    self.events = events.map { |str| str.strip.presence }.compact if events.present?
+  end
+
+  def generate_secret
+    self.secret = SecureRandom.hex(20) if secret.blank?
+  end
+end