From 2562c4f432ef4ffeee72dfc2dc71d7f056add823 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Thu, 21 Dec 2023 23:29:06 +0200 Subject: [PATCH] add option to toggle single digital sign --- app/controllers/account_configs_controller.rb | 3 +- app/models/account_config.rb | 1 + app/views/esign_settings/show.html.erb | 23 ++++++- lib/submissions/generate_audit_trail.rb | 2 +- .../generate_result_attachments.rb | 68 +++++++++++++------ 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/app/controllers/account_configs_controller.rb b/app/controllers/account_configs_controller.rb index cfa46a14..87baf04c 100644 --- a/app/controllers/account_configs_controller.rb +++ b/app/controllers/account_configs_controller.rb @@ -6,7 +6,8 @@ class AccountConfigsController < ApplicationController ALLOWED_KEYS = [ AccountConfig::ALLOW_TYPED_SIGNATURE, - AccountConfig::FORCE_MFA + AccountConfig::FORCE_MFA, + AccountConfig::ESIGNING_PREFERENCE_KEY ].freeze def create diff --git a/app/models/account_config.rb b/app/models/account_config.rb index 0c435e0e..2c18e6a3 100644 --- a/app/models/account_config.rb +++ b/app/models/account_config.rb @@ -29,6 +29,7 @@ class AccountConfig < ApplicationRecord ALLOW_TYPED_SIGNATURE = 'allow_typed_signature' SUBMITTER_REMAILERS = 'submitter_reminders' FORM_COMPLETED_BUTTON_KEY = 'form_completed_button' + ESIGNING_PREFERENCE_KEY = 'esigning_preference' DEFAULT_VALUES = { SUBMITTER_INVITATION_EMAIL_KEY => { diff --git a/app/views/esign_settings/show.html.erb b/app/views/esign_settings/show.html.erb index 5f93bacd..1e8b5455 100644 --- a/app/views/esign_settings/show.html.erb +++ b/app/views/esign_settings/show.html.erb @@ -121,7 +121,28 @@ <%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %> <% end %> + + <% end %> + <% if !Docuseal.multitenant? %> + <% account_config = AccountConfig.where(account: current_account, key: AccountConfig::ESIGNING_PREFERENCE_KEY).first_or_initialize(value: 'multiple') %> + <% if can?(:manage, account_config) %> +
+
+

Preferences

+
+ <% if can?(:manage, account_config) %> + <%= form_for account_config, url: account_configs_path, method: :post do |f| %> + <%= f.hidden_field :key %> +
+ + Apply multiple PDF digital signatures in the document per each signer + + <%= f.check_box :value, { class: 'toggle', checked: account_config.value == 'multiple', onchange: 'this.form.requestSubmit()' }, 'multiple', 'single' %> +
+ <% end %> + <% end %> +
<% end %> - + <% end %> diff --git a/lib/submissions/generate_audit_trail.rb b/lib/submissions/generate_audit_trail.rb index db55f628..5bdcc317 100644 --- a/lib/submissions/generate_audit_trail.rb +++ b/lib/submissions/generate_audit_trail.rb @@ -257,7 +257,7 @@ module Submissions if event.event_type.include?('sms') || event.event_type.include?('phone') submitter.phone else - (submitter.name || submitter.email || submitter.phone) + submitter.name || submitter.email || submitter.phone end ] ) diff --git a/lib/submissions/generate_result_attachments.rb b/lib/submissions/generate_result_attachments.rb index 845587a5..94a39db6 100644 --- a/lib/submissions/generate_result_attachments.rb +++ b/lib/submissions/generate_result_attachments.rb @@ -11,7 +11,8 @@ module Submissions end INFO_CREATOR = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})".freeze - SIGN_REASON = 'Signed by %s with DocuSeal.co' + SIGN_REASON = 'Signed by %s with DocuSeal.co' + SIGN_SIGNLE_REASON = 'Digitally signed with DocuSeal.co' TEXT_LEFT_MARGIN = 1 TEXT_TOP_MARGIN = 1 @@ -200,9 +201,9 @@ module Submissions submitter.submission.template_schema.map do |item| pdf = pdfs_index[item['attachment_uuid']] - attachment = save_signed_pdf(pdf:, submitter:, pkcs:, tsa_url:, - uuid: item['attachment_uuid'], - name: item['name']) + attachment = save_pdf(pdf:, submitter:, pkcs:, tsa_url:, + uuid: item['attachment_uuid'], + name: item['name']) image_pdfs << pdf if original_documents.find { |a| a.uuid == item['attachment_uuid'] }.image? @@ -217,7 +218,7 @@ module Submissions end images_pdf_result = - save_signed_pdf( + save_pdf( pdf: images_pdf, submitter:, tsa_url:, @@ -230,30 +231,34 @@ module Submissions end # rubocop:enable Metrics - def save_signed_pdf(pdf:, submitter:, pkcs:, tsa_url:, uuid:, name:) + def save_pdf(pdf:, submitter:, pkcs:, tsa_url:, uuid:, name:) io = StringIO.new pdf.trailer.info[:Creator] = info_creator - sign_params = { - reason: sign_reason(submitter.email), - certificate: pkcs.certificate, - key: pkcs.key, - certificate_chain: pkcs.ca_certs || [] - } + sign_reason = fetch_sign_reason(submitter) - if tsa_url - sign_params[:timestamp_handler] = Submissions::TimestampHandler.new(tsa_url:) - sign_params[:signature_size] = 10_000 - end + if sign_reason + sign_params = { + reason: sign_reason, + certificate: pkcs.certificate, + key: pkcs.key, + certificate_chain: pkcs.ca_certs || [] + } + + if tsa_url + sign_params[:timestamp_handler] = Submissions::TimestampHandler.new(tsa_url:) + sign_params[:signature_size] = 10_000 + end - pdf.sign(io, **sign_params) + pdf.sign(io, **sign_params) + else + pdf.write(io, incremental: true) + end ActiveStorage::Attachment.create!( uuid:, - blob: ActiveStorage::Blob.create_and_upload!( - io: StringIO.new(io.string), filename: "#{name}.pdf" - ), + blob: ActiveStorage::Blob.create_and_upload!(io: StringIO.new(io.string), filename: "#{name}.pdf"), metadata: { sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) }, name: 'documents', record: submitter @@ -308,8 +313,27 @@ module Submissions pdf end - def sign_reason(email) - format(SIGN_REASON, email:) + def sign_reason(name) + format(SIGN_REASON, name:) + end + + def single_sign_reason + SIGN_SIGNLE_REASON + end + + def fetch_sign_reason(submitter) + reason_name = submitter.email || submitter.name || submitter.phone + + return sign_reason(reason_name) if Docuseal.multitenant? + + return sign_reason(reason_name) if AccountConfig.where(account: submitter.account, + key: AccountConfig::ESIGNING_PREFERENCE_KEY) + .first_or_initialize(value: 'multiple').value == 'multiple' + + return single_sign_reason if !submitter.submission.submitters.exists?(completed_at: nil) && + submitter.completed_at == submitter.submission.submitters.maximum(:completed_at) + + nil end def info_creator