From e4bb5466f51eb0b58d8c9488364254562296972b Mon Sep 17 00:00:00 2001 From: Alex Turchyn Date: Sat, 5 Aug 2023 15:25:16 +0300 Subject: [PATCH] add webhook settings --- app/controllers/application_controller.rb | 4 +- app/controllers/submit_form_controller.rb | 19 +++++-- .../webhook_settings_controller.rb | 31 +++++++++++ app/jobs/send_webhook_request_job.rb | 24 +++++++++ app/models/account.rb | 2 + app/models/encrypted_config.rb | 1 + app/models/submission.rb | 1 + app/models/submitter.rb | 2 + app/views/api_settings/index.html.erb | 26 +++++---- app/views/shared/_button_title.html.erb | 2 +- app/views/shared/_clipboard_copy.html.erb | 4 +- app/views/shared/_settings_nav.html.erb | 3 ++ app/views/webhook_settings/show.html.erb | 42 +++++++++++++++ config/routes.rb | 1 + lib/submitters/serialize_for_webhook.rb | 54 +++++++++++++++++++ 15 files changed, 198 insertions(+), 18 deletions(-) create mode 100644 app/controllers/webhook_settings_controller.rb create mode 100644 app/jobs/send_webhook_request_job.rb create mode 100644 app/views/webhook_settings/show.html.erb create mode 100644 lib/submitters/serialize_for_webhook.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 44e39e6a..3d0f96b9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -34,8 +34,8 @@ class ApplicationController < ActionController::Base redirect_to setup_index_path unless User.exists? end - def button_title(title: 'Submit', disabled_with: 'Submitting', icon: nil) - render_to_string(partial: 'shared/button_title', locals: { title:, disabled_with:, icon: }) + def button_title(title: 'Submit', disabled_with: 'Submitting', icon: nil, icon_disabled: nil) + render_to_string(partial: 'shared/button_title', locals: { title:, disabled_with:, icon:, icon_disabled: }) end def svg_icon(icon_name, class: '') diff --git a/app/controllers/submit_form_controller.rb b/app/controllers/submit_form_controller.rb index 57188d98..dea2bb87 100644 --- a/app/controllers/submit_form_controller.rb +++ b/app/controllers/submit_form_controller.rb @@ -17,11 +17,8 @@ class SubmitFormController < ApplicationController def update submitter = Submitter.find_by!(slug: params[:slug]) - submitter.values.merge!(normalized_values) - submitter.completed_at = Time.current if params[:completed] == 'true' - submitter.opened_at ||= Time.current - submitter.save! + update_submitter!(submitter) Submissions.update_template_fields!(submitter.submission) if submitter.submission.template_fields.blank? @@ -30,6 +27,10 @@ class SubmitFormController < ApplicationController if submitter.completed_at? GenerateSubmitterResultAttachmentsJob.perform_later(submitter) + if submitter.account.encrypted_configs.exists?(key: EncryptedConfig::WEBHOOK_URL_KEY) + SendWebhookRequestJob.perform_later(submitter) + end + submitter.submission.template.account.users.active.each do |user| SubmitterMailer.completed_email(submitter, user).deliver_later! end @@ -44,6 +45,16 @@ class SubmitFormController < ApplicationController private + def update_submitter!(submitter) + submitter.values.merge!(normalized_values) + submitter.completed_at = Time.current if params[:completed] == 'true' + submitter.opened_at ||= Time.current + + submitter.save! + + submitter + end + def normalized_values params.fetch(:values, {}).to_unsafe_h.transform_values do |v| if params[:cast_boolean] == 'true' diff --git a/app/controllers/webhook_settings_controller.rb b/app/controllers/webhook_settings_controller.rb new file mode 100644 index 00000000..4d0cc119 --- /dev/null +++ b/app/controllers/webhook_settings_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class WebhookSettingsController < ApplicationController + def show + @encrypted_config = + current_account.encrypted_configs.find_or_initialize_by(key: EncryptedConfig::WEBHOOK_URL_KEY) + end + + def create + @encrypted_config = + current_account.encrypted_configs.find_or_initialize_by(key: EncryptedConfig::WEBHOOK_URL_KEY) + + @encrypted_config.update!(encrypted_config_params) + + redirect_back(fallback_location: settings_webhooks_path, notice: 'Webhook URL has been saved.') + end + + def update + submitter = current_account.submitters.where.not(completed_at: nil).order(:id).last + + SendWebhookRequestJob.perform_later(submitter) + + redirect_back(fallback_location: settings_webhooks_path, notice: 'Webhook request has been sent.') + end + + private + + def encrypted_config_params + params.require(:encrypted_config).permit(:value) + end +end diff --git a/app/jobs/send_webhook_request_job.rb b/app/jobs/send_webhook_request_job.rb new file mode 100644 index 00000000..0ca7c919 --- /dev/null +++ b/app/jobs/send_webhook_request_job.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class SendWebhookRequestJob < ApplicationJob + USER_AGENT = 'DocuSeal.co Webhook' + + def perform(submitter) + config = submitter.submission.account.encrypted_configs.find_by(key: EncryptedConfig::WEBHOOK_URL_KEY) + + return if config.blank? || config.value.blank? + + Submissions::EnsureResultGenerated.call(submitter) + + ActiveStorage::Current.url_options = Docuseal.default_url_options + + Faraday.post(config.value, + { + event_type: 'form.submitted', + timestamp: Time.current.iso8601, + data: Submitters::SerializeForWebhook.call(submitter) + }.to_json, + 'Content-Type' => 'application/json', + 'User-Agent' => USER_AGENT) + end +end diff --git a/app/models/account.rb b/app/models/account.rb index 60d03ebd..96a1d9f3 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -15,6 +15,8 @@ class Account < ApplicationRecord has_many :users, dependent: :destroy has_many :encrypted_configs, dependent: :destroy has_many :templates, dependent: :destroy + has_many :submissions, through: :templates + has_many :submitters, through: :submissions has_many :active_users, -> { active }, dependent: :destroy, inverse_of: :account, class_name: 'User' diff --git a/app/models/encrypted_config.rb b/app/models/encrypted_config.rb index e06e5f52..e3600bb0 100644 --- a/app/models/encrypted_config.rb +++ b/app/models/encrypted_config.rb @@ -25,6 +25,7 @@ class EncryptedConfig < ApplicationRecord EMAIL_SMTP_KEY = 'action_mailer_smtp' ESIGN_CERTS_KEY = 'esign_certs' APP_URL_KEY = 'app_url' + WEBHOOK_URL_KEY = 'webhook_url' belongs_to :account diff --git a/app/models/submission.rb b/app/models/submission.rb index 116ade07..c7f3e0c2 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -26,6 +26,7 @@ # class Submission < ApplicationRecord belongs_to :template + has_one :account, through: :template belongs_to :created_by_user, class_name: 'User', optional: true has_many :submitters, dependent: :destroy diff --git a/app/models/submitter.rb b/app/models/submitter.rb index 35c1a3e6..d09a1288 100644 --- a/app/models/submitter.rb +++ b/app/models/submitter.rb @@ -30,6 +30,8 @@ # class Submitter < ApplicationRecord belongs_to :submission + has_one :template, through: :submission + has_one :account, through: :template attribute :values, :string, default: -> { {} } attribute :slug, :string, default: -> { SecureRandom.base58(14) } diff --git a/app/views/api_settings/index.html.erb b/app/views/api_settings/index.html.erb index 4ef20920..489f2b1e 100644 --- a/app/views/api_settings/index.html.erb +++ b/app/views/api_settings/index.html.erb @@ -5,9 +5,9 @@
-
+
- <%= render 'shared/clipboard_copy', text: jwt, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %> + <%= render 'shared/clipboard_copy', icon: 'copy', text: jwt, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
@@ -25,12 +25,16 @@
-
curl --location '<%= api_submissions_url %>' \
+            <% text = capture do %>curl --location '<%= api_submissions_url %>' \
        --header 'X-Auth-Token: <%= jwt %>' \
        --data-raw '{
-           "template_id": <%= current_account.templates.last.id %>,
+           "template_id": <%= current_account.templates.last&.id || 1 %>,
            "emails":  "<%= current_user.email.sub('@', '+test@') %>, <%= current_user.email.sub('@', '+test2@') %>"
-       }'
+ }'<% end.to_str %> + + <%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %> + +
<%= text %>
@@ -47,19 +51,23 @@
-
curl --location '<%= api_submissions_url %>' \
+            <% text = capture do %>curl --location '<%= api_submissions_url %>' \
        --header 'X-Auth-Token: <%= jwt %>' \
        --data-raw '{
-         "template_id": <%= current_account.templates.last.id %>,
+         "template_id": <%= current_account.templates.last&.id || 1 %>,
          "submission": [
            {
              "submitters": [
-               { "name": "<%= current_account.templates.last.submitters.first['name'] %>", "email": "<%= current_user.email.sub('@', '+test@') %>" },
+               { "name": "<%= current_account.templates.last ? current_account.templates.last.submitters.first['name'] : 'First Submitter' %>", "email": "<%= current_user.email.sub('@', '+test@') %>" },
                { "name": "Second Submitter", "email": "<%= current_user.email.sub('@', '+test2@') %>" }
              ]
            }
          ]
-       }'
+ }'<% end.to_str %> + + <%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %> + +
<%= text %>
diff --git a/app/views/shared/_button_title.html.erb b/app/views/shared/_button_title.html.erb index 1ec9c5c9..5f33090a 100644 --- a/app/views/shared/_button_title.html.erb +++ b/app/views/shared/_button_title.html.erb @@ -8,7 +8,7 @@ - <%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %> + <%= local_assigns[:icon_disabled] || svg_icon('loader', class: 'w-6 h-6 animate-spin') %> <%= disabled_with %>... diff --git a/app/views/shared/_clipboard_copy.html.erb b/app/views/shared/_clipboard_copy.html.erb index 9757d3e3..c4579794 100644 --- a/app/views/shared/_clipboard_copy.html.erb +++ b/app/views/shared/_clipboard_copy.html.erb @@ -2,13 +2,13 @@