discourse/app/models/web_hook.rb

124 lines
3.8 KiB
Ruby

class WebHook < ActiveRecord::Base
has_and_belongs_to_many :web_hook_event_types
has_and_belongs_to_many :groups
has_and_belongs_to_many :categories
has_many :web_hook_events, dependent: :destroy
default_scope { order('id ASC') }
validates :payload_url, presence: true, format: URI::regexp(%w(http https))
validates :secret, length: { minimum: 12 }, allow_blank: true
validates_presence_of :content_type
validates_presence_of :last_delivery_status
validates_presence_of :web_hook_event_types, unless: :wildcard_web_hook?
before_save :strip_url
def self.content_types
@content_types ||= Enum.new('application/json' => 1,
'application/x-www-form-urlencoded' => 2)
end
def self.last_delivery_statuses
@last_delivery_statuses ||= Enum.new(inactive: 1,
failed: 2,
successful: 3)
end
def self.default_event_types
[WebHookEventType.find(WebHookEventType::POST)]
end
def strip_url
self.payload_url = (payload_url || "").strip.presence
end
def self.active_web_hooks(type)
WebHook.where(active: true)
.joins(:web_hook_event_types)
.where("web_hooks.wildcard_web_hook = ? OR web_hook_event_types.name = ?", true, type.to_s)
.uniq
end
def self.enqueue_hooks(type, opts = {}, web_hooks = nil)
(web_hooks || active_web_hooks(type)).each do |web_hook|
Jobs.enqueue(:emit_web_hook_event, opts.merge(
web_hook_id: web_hook.id, event_type: type.to_s
))
end
end
def self.enqueue_object_hooks(type, object, event, serializer = nil)
Scheduler::Defer.later("Enqueue User Webhook") do
web_hooks = active_web_hooks(type)
return if web_hooks.empty?
serializer ||= "WebHook#{type.capitalize}Serializer".constantize
WebHook.enqueue_hooks(type, {
event_name: event.to_s,
payload: serializer.new(object,
scope: self.guardian,
root: false
).to_json
}, web_hooks)
end
end
def self.enqueue_topic_hooks(event, topic)
Scheduler::Defer.later("Enqueue Topic Webhook") do
web_hooks = active_web_hooks('topic')
return if web_hooks.empty?
topic_view = TopicView.new(topic.id, Discourse.system_user)
WebHook.enqueue_hooks(:topic, {
category_id: topic&.category_id,
event_name: event.to_s,
payload: WebHookTopicViewSerializer.new(topic_view,
scope: self.guardian,
root: false
).to_json
}, web_hooks)
end
end
def self.enqueue_post_hooks(event, post)
Scheduler::Defer.later("Enqueue Post Webhook") do
web_hooks = active_web_hooks('post')
return if web_hooks.empty?
WebHook.enqueue_hooks(:post, {
category_id: post&.topic&.category_id,
event_name: event.to_s,
payload: WebHookPostSerializer.new(post,
scope: self.guardian,
root: false
).to_json
}, web_hooks)
end
end
private
def self.guardian
@guardian ||= Guardian.new(Discourse.system_user)
end
end
# == Schema Information
#
# Table name: web_hooks
#
# id :integer not null, primary key
# payload_url :string not null
# content_type :integer default(1), not null
# last_delivery_status :integer default(1), not null
# status :integer default(1), not null
# secret :string default("")
# wildcard_web_hook :boolean default(FALSE), not null
# verify_certificate :boolean default(TRUE), not null
# active :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
#