adjust webhooks
This commit is contained in:
@@ -67,10 +67,10 @@ module Api
|
||||
|
||||
submissions = create_submissions(@template, params)
|
||||
|
||||
@template.account.webhook_urls.with_event('submission.created').each do |webhook_url|
|
||||
WebhookUrls.for_account_id(@template.account_id, 'submission.created').each do |webhook_url|
|
||||
submissions.each do |submission|
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async({ 'submission_id' => submission.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async('submission_id' => submission.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -78,7 +78,7 @@ module Api
|
||||
|
||||
submissions.each do |submission|
|
||||
submission.submitters.each do |submitter|
|
||||
ProcessSubmitterCompletionJob.perform_async({ 'submitter_id' => submitter.id }) if submitter.completed_at?
|
||||
ProcessSubmitterCompletionJob.perform_async('submitter_id' => submitter.id) if submitter.completed_at?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,9 +96,9 @@ module Api
|
||||
else
|
||||
@submission.update!(archived_at: Time.current)
|
||||
|
||||
@submission.account.webhook_urls.with_event('submission.archived').each do |webhook_url|
|
||||
SendSubmissionArchivedWebhookRequestJob.perform_async({ 'submission_id' => @submission.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(@submission.account_id, 'submission.archived').each do |webhook_url|
|
||||
SendSubmissionArchivedWebhookRequestJob.perform_async('submission_id' => @submission.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ module Api
|
||||
|
||||
SubmissionEvents.create_with_tracking_data(submitter, 'view_form', request)
|
||||
|
||||
submitter.account.webhook_urls.with_event('form.viewed').each do |webhook_url|
|
||||
SendFormViewedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(submitter.account_id, 'form.viewed').each do |webhook_url|
|
||||
SendFormViewedWebhookRequestJob.perform_async('submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
|
||||
render json: {}
|
||||
|
||||
@@ -68,7 +68,7 @@ module Api
|
||||
end
|
||||
|
||||
if @submitter.completed_at?
|
||||
ProcessSubmitterCompletionJob.perform_async({ 'submitter_id' => @submitter.id })
|
||||
ProcessSubmitterCompletionJob.perform_async('submitter_id' => @submitter.id)
|
||||
elsif normalized_params[:send_email] || normalized_params[:send_sms]
|
||||
Submitters.send_signature_requests([@submitter])
|
||||
end
|
||||
|
||||
@@ -25,9 +25,9 @@ module Api
|
||||
|
||||
schema_documents = Templates::CloneAttachments.call(template: cloned_template, original_template: @template)
|
||||
|
||||
cloned_template.account.webhook_urls.with_event('template.created').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async({ 'template_id' => cloned_template.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(cloned_template.account_id, 'template.created').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async('template_id' => cloned_template.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
|
||||
render json: Templates::SerializeForApi.call(cloned_template, schema_documents)
|
||||
|
||||
@@ -65,9 +65,9 @@ module Api
|
||||
|
||||
@template.update!(template_params)
|
||||
|
||||
@template.account.webhook_urls.with_event('template.updated').each do |webhook_url|
|
||||
SendTemplateUpdatedWebhookRequestJob.perform_async({ 'template_id' => @template.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(@template.account_id, 'template.updated').each do |webhook_url|
|
||||
SendTemplateUpdatedWebhookRequestJob.perform_async('template_id' => @template.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
|
||||
render json: @template.as_json(only: %i[id updated_at])
|
||||
|
||||
@@ -38,9 +38,9 @@ class StartFormController < ApplicationController
|
||||
|
||||
if @submitter.save
|
||||
if is_new_record
|
||||
@submitter.account.webhook_urls.with_event('submission.created').each do |webhook_url|
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async({ 'submission_id' => @submitter.submission_id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(@submitter.account_id, 'submission.created').each do |webhook_url|
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async('submission_id' => @submitter.submission_id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -66,9 +66,9 @@ class SubmissionsController < ApplicationController
|
||||
else
|
||||
@submission.update!(archived_at: Time.current)
|
||||
|
||||
@submission.account.webhook_urls.with_event('submission.archived').each do |webhook_url|
|
||||
SendSubmissionArchivedWebhookRequestJob.perform_async({ 'submission_id' => @submission.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(@submission.account_id, 'submission.archived').each do |webhook_url|
|
||||
SendSubmissionArchivedWebhookRequestJob.perform_async('submission_id' => @submission.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
|
||||
I18n.t('submission_has_been_archived')
|
||||
@@ -87,10 +87,10 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def enqueue_submission_created_webhooks(template, submissions)
|
||||
template.account.webhook_urls.with_event('submission.created').each do |webhook_url|
|
||||
WebhookUrls.for_account_id(template.account_id, 'submission.created').each do |webhook_url|
|
||||
submissions.each do |submission|
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async({ 'submission_id' => submission.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
SendSubmissionCreatedWebhookRequestJob.perform_async('submission_id' => submission.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,9 +25,9 @@ class SubmitFormDeclineController < ApplicationController
|
||||
SubmitterMailer.declined_email(submitter, user).deliver_later!
|
||||
end
|
||||
|
||||
submitter.account.webhook_urls.with_event('form.declined').each do |webhook_url|
|
||||
SendFormDeclinedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(submitter.account_id, 'form.declined').each do |webhook_url|
|
||||
SendFormDeclinedWebhookRequestJob.perform_async('submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
|
||||
redirect_to submit_form_path(submitter.slug)
|
||||
|
||||
@@ -129,16 +129,16 @@ class TemplatesController < ApplicationController
|
||||
end
|
||||
|
||||
def enqueue_template_created_webhooks(template)
|
||||
template.account.webhook_urls.with_event('template.updated').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async({ 'template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(template.account_id, 'template.created').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async('template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
def enqueue_template_updated_webhooks(template)
|
||||
template.account.webhook_urls.with_event('template.updated').each do |webhook_url|
|
||||
SendTemplateUpdatedWebhookRequestJob.perform_async({ 'template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(template.account_id, 'template.updated').each do |webhook_url|
|
||||
SendTemplateUpdatedWebhookRequestJob.perform_async('template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@ class TemplatesUploadsController < ApplicationController
|
||||
end
|
||||
|
||||
def enqueue_template_created_webhooks(template)
|
||||
template.account.webhook_urls.with_event('template.created').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async({ 'template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(template.account_id, 'template.created').each do |webhook_url|
|
||||
SendTemplateCreatedWebhookRequestJob.perform_async('template_id' => template.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class WebhookPreferencesController < ApplicationController
|
||||
load_and_authorize_resource :webhook_url, parent: false
|
||||
|
||||
def update
|
||||
webhook_preferences_params[:events].each do |event, val|
|
||||
@webhook_url.events.delete(event) if val == '0'
|
||||
@webhook_url.events.push(event) if val == '1' && @webhook_url.events.exclude?(event)
|
||||
end
|
||||
|
||||
@webhook_url.save!
|
||||
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def webhook_preferences_params
|
||||
params.require(:webhook_url).permit(events: {})
|
||||
end
|
||||
end
|
||||
@@ -17,8 +17,8 @@ class WebhookSettingsController < ApplicationController
|
||||
def update
|
||||
submitter = current_account.submitters.where.not(completed_at: nil).order(:id).last
|
||||
|
||||
SendFormCompletedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'webhook_url_id' => @webhook_url.id })
|
||||
SendFormCompletedWebhookRequestJob.perform_async('submitter_id' => submitter.id,
|
||||
'webhook_url_id' => @webhook_url.id)
|
||||
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_request_has_been_sent'))
|
||||
end
|
||||
@@ -30,6 +30,6 @@ class WebhookSettingsController < ApplicationController
|
||||
end
|
||||
|
||||
def webhook_params
|
||||
params.require(:webhook_url).permit(:url, events: [])
|
||||
params.require(:webhook_url).permit(:url)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,15 +63,15 @@ class ProcessSubmitterCompletionJob
|
||||
end
|
||||
|
||||
def enqueue_completed_webhooks(submitter, is_all_completed: false)
|
||||
submitter.account.webhook_urls.with_events(%w[form.completed submission.completed]).each do |webhook|
|
||||
WebhookUrls.for_account_id(submitter.account_id, %w[form.completed submission.completed]).each do |webhook|
|
||||
if webhook.events.include?('form.completed')
|
||||
SendFormCompletedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook.id })
|
||||
SendFormCompletedWebhookRequestJob.perform_async('submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook.id)
|
||||
end
|
||||
|
||||
if webhook.events.include?('submission.completed') && is_all_completed
|
||||
SendSubmissionCompletedWebhookRequestJob.perform_async({ 'submission_id' => submitter.submission_id,
|
||||
'webhook_url_id' => webhook.id })
|
||||
SendSubmissionCompletedWebhookRequestJob.perform_async('submission_id' => submitter.submission_id,
|
||||
'webhook_url_id' => webhook.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendFormCompletedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submitter = Submitter.find(params['submitter_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submitter.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('form.completed')
|
||||
|
||||
Submissions::EnsureResultGenerated.call(submitter)
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendFormDeclinedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submitter = Submitter.find(params['submitter_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submitter.submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('form.declined')
|
||||
|
||||
ActiveStorage::Current.url_options = Docuseal.default_url_options
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendFormStartedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submitter = Submitter.find(params['submitter_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submitter.submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('form.started')
|
||||
|
||||
ActiveStorage::Current.url_options = Docuseal.default_url_options
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendFormViewedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submitter = Submitter.find(params['submitter_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submitter.submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('form.viewed')
|
||||
|
||||
ActiveStorage::Current.url_options = Docuseal.default_url_options
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendSubmissionArchivedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submission = Submission.find(params['submission_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.archived')
|
||||
|
||||
resp = begin
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendSubmissionCompletedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submission = Submission.find(params['submission_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.completed')
|
||||
|
||||
resp = begin
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendSubmissionCreatedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
submission = Submission.find(params['submission_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = submission.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('submission.created')
|
||||
|
||||
resp = begin
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendTemplateCreatedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
template = Template.find(params['template_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = template.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('template.created')
|
||||
|
||||
resp = begin
|
||||
|
||||
@@ -11,12 +11,10 @@ class SendTemplateUpdatedWebhookRequestJob
|
||||
|
||||
def perform(params = {})
|
||||
template = Template.find(params['template_id'])
|
||||
webhook_url = WebhookUrl.find(params['webhook_url_id'])
|
||||
|
||||
attempt = params['attempt'].to_i
|
||||
|
||||
webhook_url = template.account.webhook_urls.find_by(id: params['webhook_url_id'])
|
||||
|
||||
return unless webhook_url
|
||||
return if webhook_url.url.blank? || webhook_url.events.exclude?('template.updated')
|
||||
|
||||
resp = begin
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# events :text not null
|
||||
# secret :text
|
||||
# secret :text not null
|
||||
# sha1 :string not null
|
||||
# url :text not null
|
||||
# created_at :datetime not null
|
||||
@@ -37,17 +37,11 @@ class WebhookUrl < ApplicationRecord
|
||||
belongs_to :account
|
||||
|
||||
attribute :events, :string, default: -> { %w[form.viewed form.started form.completed form.declined] }
|
||||
attribute :secret, :string, default: -> { {} }
|
||||
|
||||
serialize :events, coder: JSON
|
||||
serialize :secret, coder: JSON
|
||||
|
||||
scope :with_event, ->(event) { with_events([event]) }
|
||||
scope :with_events, lambda { |events|
|
||||
where(events.map do |event|
|
||||
Arel::Table.new(:webhook_urls)[:events].matches("%\"#{event}\"%")
|
||||
end.reduce(:or))
|
||||
}
|
||||
|
||||
before_validation :set_sha1
|
||||
|
||||
encrypts :url, :secret
|
||||
|
||||
@@ -12,23 +12,27 @@
|
||||
<div class="flex flex-row flex-wrap space-y-2 md:space-y-0 md:flex-nowrap md:space-x-2 mt-2">
|
||||
<%= f.url_field :url, class: 'input font-mono input-bordered w-full', placeholder: 'https://example.com/hook' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button w-full md:w-32' %>
|
||||
<% if @webhook_url.persisted? %>
|
||||
<% if @webhook_url.persisted? %>
|
||||
<a href="<%= webhook_secret_path(@webhook_url) %>" data-turbo-frame="modal" class="white-button w-full md:w-auto">
|
||||
<%= @webhook_url.secret.present? ? t('edit_secret') : t('add_secret') %>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= form_for @webhook_url, url: @webhook_url.url.present? ? webhook_preference_path(@webhook_url) : '', method: :put, html: { autocomplete: 'off' } do |f| %>
|
||||
<% WebhookUrl::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 mt-4 gap-y-2">
|
||||
<%= f.collection_check_boxes(:events, events, :to_s, :to_s, include_hidden: false) do |b| %>
|
||||
<div class="flex">
|
||||
<label class="flex items-center space-x-2">
|
||||
<%= b.check_box class: 'base-checkbox', checked: @webhook_url.events.include?(b.value), onchange: 'this.form.requestSubmit()', disabled: @webhook_url.url.blank? %>
|
||||
<span>
|
||||
<%= b.label %>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<% events.each do |event| %>
|
||||
<%= f.fields_for :events do |ff| %>
|
||||
<div class="flex">
|
||||
<label class="flex items-center space-x-2 cursor-pointer">
|
||||
<%= ff.check_box event, class: 'base-checkbox', checked: @webhook_url.events.include?(event), onchange: 'this.form.requestSubmit()', disabled: @webhook_url.url.blank? %>
|
||||
<span>
|
||||
<%= event %>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -81,6 +81,7 @@ Rails.application.routes.draw do
|
||||
resources :submitters_autocomplete, only: %i[index]
|
||||
resources :template_folders_autocomplete, only: %i[index]
|
||||
resources :webhook_secret, only: %i[show update]
|
||||
resources :webhook_preferences, only: %i[update]
|
||||
resource :templates_upload, only: %i[create]
|
||||
authenticated do
|
||||
resource :templates_upload, only: %i[show], path: 'new'
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddSecretToWebhookUrls < ActiveRecord::Migration[7.2]
|
||||
class MigrationWebhookUrl < ApplicationRecord
|
||||
self.table_name = 'webhook_urls'
|
||||
|
||||
serialize :secret, coder: JSON
|
||||
|
||||
encrypts :url, :secret
|
||||
end
|
||||
|
||||
def change
|
||||
add_column :webhook_urls, :secret, :text
|
||||
|
||||
MigrationWebhookUrl.all.each do |url|
|
||||
url.update_columns(secret: {})
|
||||
end
|
||||
|
||||
change_column_null :webhook_urls, :secret, false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,42 +3,45 @@
|
||||
class PopulateWebhookUrls < ActiveRecord::Migration[7.2]
|
||||
disable_ddl_transaction
|
||||
|
||||
class MigrationWebhookUrl < ApplicationRecord
|
||||
class MigrationWebhookUrl < ActiveRecord::Base
|
||||
self.table_name = 'webhook_urls'
|
||||
|
||||
serialize :events, coder: JSON
|
||||
serialize :secret, coder: JSON
|
||||
encrypts :url, :secret
|
||||
|
||||
before_validation -> { self.sha1 = Digest::SHA1.hexdigest(url) }
|
||||
encrypts :url, :secret
|
||||
end
|
||||
|
||||
class MigrationEncryptedConfig < ApplicationRecord
|
||||
class MigrationEncryptedConfig < ActiveRecord::Base
|
||||
self.table_name = 'encrypted_configs'
|
||||
|
||||
encrypts :value
|
||||
serialize :value, coder: JSON
|
||||
end
|
||||
|
||||
class MigrationAccountConfig < ApplicationRecord
|
||||
class MigrationAccountConfig < ActiveRecord::Base
|
||||
self.table_name = 'account_configs'
|
||||
|
||||
serialize :value, coder: JSON
|
||||
end
|
||||
|
||||
def up
|
||||
MigrationEncryptedConfig.joins('INNER JOIN accounts a ON a.id = encrypted_configs.account_id')
|
||||
.where(key: 'webhook_url')
|
||||
.find_each do |config|
|
||||
webhook_url = MigrationWebhookUrl.find_or_initialize_by(account_id: config.account_id, url: config.value)
|
||||
webhook_url.secret = MigrationEncryptedConfig.find_by(account_id: config.account_id, key: 'webhook_secret')&.value
|
||||
MigrationEncryptedConfig.where(key: 'webhook_url').find_each do |config|
|
||||
webhook_url = MigrationWebhookUrl.find_or_initialize_by(account_id: config.account_id,
|
||||
sha1: Digest::SHA1.hexdigest(config.value))
|
||||
|
||||
webhook_url.secret =
|
||||
MigrationEncryptedConfig.find_by(account_id: config.account_id, key: 'webhook_secret')&.value.to_h
|
||||
|
||||
preferences =
|
||||
MigrationAccountConfig.find_by(account_id: config.account_id, key: 'webhook_preferences')&.value.to_h
|
||||
|
||||
preferences = MigrationAccountConfig.find_by(account_id: config.account_id,
|
||||
key: 'webhook_preferences')&.value.to_h
|
||||
events = %w[form.viewed form.started form.completed form.declined].reject { |event| preferences[event] == false }
|
||||
|
||||
events += preferences.compact_blank.keys
|
||||
|
||||
webhook_url.events = events.uniq
|
||||
webhook_url.url = config.value
|
||||
|
||||
webhook_url.save!
|
||||
end
|
||||
|
||||
+1
-1
@@ -367,7 +367,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_29_192232) do
|
||||
t.string "sha1", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "secret"
|
||||
t.text "secret", null: false
|
||||
t.index ["account_id"], name: "index_webhook_urls_on_account_id"
|
||||
t.index ["sha1"], name: "index_webhook_urls_on_sha1"
|
||||
end
|
||||
|
||||
@@ -14,9 +14,9 @@ module Submitters
|
||||
unless submitter.submission_events.exists?(event_type: 'start_form')
|
||||
SubmissionEvents.create_with_tracking_data(submitter, 'start_form', request)
|
||||
|
||||
submitter.account.webhook_urls.with_event('form.started').each do |webhook_url|
|
||||
SendFormStartedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id })
|
||||
WebhookUrls.for_account_id(submitter.account_id, 'form.started').each do |webhook_url|
|
||||
SendFormStartedWebhookRequestJob.perform_async('submitter_id' => submitter.id,
|
||||
'webhook_url_id' => webhook_url.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ module Submitters
|
||||
|
||||
submitter.submission.save!
|
||||
|
||||
ProcessSubmitterCompletionJob.perform_async({ 'submitter_id' => submitter.id }) if submitter.completed_at?
|
||||
ProcessSubmitterCompletionJob.perform_async('submitter_id' => submitter.id) if submitter.completed_at?
|
||||
|
||||
submitter
|
||||
end
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module WebhookUrls
|
||||
module_function
|
||||
|
||||
def for_account_id(account_id, events)
|
||||
events = Array.wrap(events)
|
||||
|
||||
rel = WebhookUrl.where(account_id:)
|
||||
|
||||
event_arel = events.map { |event| Arel::Table.new(:webhook_urls)[:events].matches("%\"#{event}\"%") }.reduce(:or)
|
||||
|
||||
if Docuseal.multitenant?
|
||||
rel.where(event_arel)
|
||||
else
|
||||
linked_account_rel =
|
||||
AccountLinkedAccount.where(linked_account_id: account_id).where.not(account_type: :testing).select(:account_id)
|
||||
|
||||
webhook_urls = rel.or(WebhookUrl.where(account_id: linked_account_rel).where(event_arel))
|
||||
|
||||
account_urls, linked_urls = webhook_urls.partition { |w| w.account_id == account_id }
|
||||
|
||||
account_urls.select { |w| w.events.intersect?(events) }.presence ||
|
||||
(account_urls.present? ? WebhookUrl.none : linked_urls)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -56,14 +56,6 @@ RSpec.describe SendFormCompletedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submitter doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submitter_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['form.declined'])
|
||||
|
||||
@@ -72,12 +64,6 @@ RSpec.describe SendFormCompletedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submitter_id' => submitter.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -56,14 +56,6 @@ RSpec.describe SendFormDeclinedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submitter doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submitter_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['form.completed'])
|
||||
|
||||
@@ -72,12 +64,6 @@ RSpec.describe SendFormDeclinedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submitter_id' => submitter.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -56,14 +56,6 @@ RSpec.describe SendFormStartedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submitter doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submitter_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['form.declined'])
|
||||
|
||||
@@ -72,12 +64,6 @@ RSpec.describe SendFormStartedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submitter_id' => submitter.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -56,14 +56,6 @@ RSpec.describe SendFormViewedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submitter doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submitter_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['form.started'])
|
||||
|
||||
@@ -72,12 +64,6 @@ RSpec.describe SendFormViewedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submitter_id' => submitter.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -53,14 +53,6 @@ RSpec.describe SendSubmissionArchivedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submission doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submission_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['submission.created'])
|
||||
|
||||
@@ -69,12 +61,6 @@ RSpec.describe SendSubmissionArchivedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submission_id' => submission.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -53,14 +53,6 @@ RSpec.describe SendSubmissionCompletedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submission doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submission_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['submission.archived'])
|
||||
|
||||
@@ -69,12 +61,6 @@ RSpec.describe SendSubmissionCompletedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submission_id' => submission.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -53,14 +53,6 @@ RSpec.describe SendSubmissionCreatedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the submission doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('submission_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['submission.completed'])
|
||||
|
||||
@@ -69,12 +61,6 @@ RSpec.describe SendSubmissionCreatedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('submission_id' => submission.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -52,14 +52,6 @@ RSpec.describe SendTemplateCreatedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the template doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('template_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['template.updated'])
|
||||
|
||||
@@ -68,12 +60,6 @@ RSpec.describe SendTemplateCreatedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('template_id' => template.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -52,14 +52,6 @@ RSpec.describe SendTemplateUpdatedWebhookRequestJob do
|
||||
).once
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the template doesn't exist" do
|
||||
expect do
|
||||
described_class.new.perform('template_id' => 100_500, 'webhook_url_id' => webhook_url.id)
|
||||
end.to raise_error ActiveRecord::RecordNotFound
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the event is not in the webhook's events" do
|
||||
webhook_url.update!(events: ['template.created'])
|
||||
|
||||
@@ -68,12 +60,6 @@ RSpec.describe SendTemplateUpdatedWebhookRequestJob do
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it "doesn't send a webhook request if the webhook doesn't exist" do
|
||||
described_class.new.perform('template_id' => template.id, 'webhook_url_id' => 100_500)
|
||||
|
||||
expect(WebMock).not_to have_requested(:post, webhook_url.url)
|
||||
end
|
||||
|
||||
it 'sends again if the response status is 400 or higher' do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 401)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ RSpec.describe 'Webhook Settings' do
|
||||
|
||||
visit settings_webhooks_path
|
||||
|
||||
expect(webhook_url.secret).to be_nil
|
||||
expect(webhook_url.secret).to eq({})
|
||||
|
||||
click_link 'Add Secret'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user