add option to toggle single digital sign

pull/150/merge
Pete Matsyburka 2 years ago
parent 17323074ca
commit 2562c4f432

@ -6,7 +6,8 @@ class AccountConfigsController < ApplicationController
ALLOWED_KEYS = [ ALLOWED_KEYS = [
AccountConfig::ALLOW_TYPED_SIGNATURE, AccountConfig::ALLOW_TYPED_SIGNATURE,
AccountConfig::FORCE_MFA AccountConfig::FORCE_MFA,
AccountConfig::ESIGNING_PREFERENCE_KEY
].freeze ].freeze
def create def create

@ -29,6 +29,7 @@ class AccountConfig < ApplicationRecord
ALLOW_TYPED_SIGNATURE = 'allow_typed_signature' ALLOW_TYPED_SIGNATURE = 'allow_typed_signature'
SUBMITTER_REMAILERS = 'submitter_reminders' SUBMITTER_REMAILERS = 'submitter_reminders'
FORM_COMPLETED_BUTTON_KEY = 'form_completed_button' FORM_COMPLETED_BUTTON_KEY = 'form_completed_button'
ESIGNING_PREFERENCE_KEY = 'esigning_preference'
DEFAULT_VALUES = { DEFAULT_VALUES = {
SUBMITTER_INVITATION_EMAIL_KEY => { SUBMITTER_INVITATION_EMAIL_KEY => {

@ -121,7 +121,28 @@
<%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %> <%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
</div> </div>
<% end %> <% end %>
</div>
<% 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) %>
<div class="px-1 mt-8 max-w-xl">
<div class="flex justify-between items-end mb-4 mt-8">
<h2 class="text-3xl font-bold">Preferences</h2>
</div>
<% if can?(:manage, account_config) %>
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
<%= f.hidden_field :key %>
<div class="flex items-center justify-between py-2.5">
<span>
Apply multiple PDF digital signatures in the document per each signer
</span>
<%= f.check_box :value, { class: 'toggle', checked: account_config.value == 'multiple', onchange: 'this.form.requestSubmit()' }, 'multiple', 'single' %>
</div>
<% end %>
<% end %>
</div>
<% end %> <% end %>
</div> <% end %>
</div> </div>
</div> </div>

@ -257,7 +257,7 @@ module Submissions
if event.event_type.include?('sms') || event.event_type.include?('phone') if event.event_type.include?('sms') || event.event_type.include?('phone')
submitter.phone submitter.phone
else else
(submitter.name || submitter.email || submitter.phone) submitter.name || submitter.email || submitter.phone
end end
] ]
) )

@ -11,7 +11,8 @@ module Submissions
end end
INFO_CREATOR = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})".freeze INFO_CREATOR = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})".freeze
SIGN_REASON = 'Signed by %<email>s with DocuSeal.co' SIGN_REASON = 'Signed by %<name>s with DocuSeal.co'
SIGN_SIGNLE_REASON = 'Digitally signed with DocuSeal.co'
TEXT_LEFT_MARGIN = 1 TEXT_LEFT_MARGIN = 1
TEXT_TOP_MARGIN = 1 TEXT_TOP_MARGIN = 1
@ -200,9 +201,9 @@ module Submissions
submitter.submission.template_schema.map do |item| submitter.submission.template_schema.map do |item|
pdf = pdfs_index[item['attachment_uuid']] pdf = pdfs_index[item['attachment_uuid']]
attachment = save_signed_pdf(pdf:, submitter:, pkcs:, tsa_url:, attachment = save_pdf(pdf:, submitter:, pkcs:, tsa_url:,
uuid: item['attachment_uuid'], uuid: item['attachment_uuid'],
name: item['name']) name: item['name'])
image_pdfs << pdf if original_documents.find { |a| a.uuid == item['attachment_uuid'] }.image? image_pdfs << pdf if original_documents.find { |a| a.uuid == item['attachment_uuid'] }.image?
@ -217,7 +218,7 @@ module Submissions
end end
images_pdf_result = images_pdf_result =
save_signed_pdf( save_pdf(
pdf: images_pdf, pdf: images_pdf,
submitter:, submitter:,
tsa_url:, tsa_url:,
@ -230,30 +231,34 @@ module Submissions
end end
# rubocop:enable Metrics # 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 io = StringIO.new
pdf.trailer.info[:Creator] = info_creator pdf.trailer.info[:Creator] = info_creator
sign_params = { sign_reason = fetch_sign_reason(submitter)
reason: sign_reason(submitter.email),
certificate: pkcs.certificate,
key: pkcs.key,
certificate_chain: pkcs.ca_certs || []
}
if tsa_url if sign_reason
sign_params[:timestamp_handler] = Submissions::TimestampHandler.new(tsa_url:) sign_params = {
sign_params[:signature_size] = 10_000 reason: sign_reason,
end 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!( ActiveStorage::Attachment.create!(
uuid:, uuid:,
blob: ActiveStorage::Blob.create_and_upload!( blob: ActiveStorage::Blob.create_and_upload!(io: StringIO.new(io.string), filename: "#{name}.pdf"),
io: StringIO.new(io.string), filename: "#{name}.pdf"
),
metadata: { sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) }, metadata: { sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) },
name: 'documents', name: 'documents',
record: submitter record: submitter
@ -308,8 +313,27 @@ module Submissions
pdf pdf
end end
def sign_reason(email) def sign_reason(name)
format(SIGN_REASON, email:) 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 end
def info_creator def info_creator

Loading…
Cancel
Save