mirror of
https://github.com/docusealco/docuseal.git
synced 2026-08-07 07:14:43 +00:00
adjust view only
This commit is contained in:
@@ -101,7 +101,7 @@ module Api
|
|||||||
private
|
private
|
||||||
|
|
||||||
def maybe_return_submitter_error
|
def maybe_return_submitter_error
|
||||||
if @submitter.completed_at?
|
if @submitter.completed_at? || @submitter.submission.completed_at?
|
||||||
return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content
|
return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -16,18 +16,16 @@ class SendSubmissionEmailController < ApplicationController
|
|||||||
@submitter =
|
@submitter =
|
||||||
Submitter.completed.where(submission: template.submissions).find_by(email: params[:email].to_s.downcase)
|
Submitter.completed.where(submission: template.submissions).find_by(email: params[:email].to_s.downcase)
|
||||||
elsif params[:submission_slug]
|
elsif params[:submission_slug]
|
||||||
submission = Submission.find_by(slug: params[:submission_slug])
|
submission = Submission.find_by!(slug: params[:submission_slug])
|
||||||
|
|
||||||
if submission
|
@submitter = submission.submitters.order(:completed_at).find_by(email: params[:email].to_s.downcase)
|
||||||
@submitter = Submitter.completed.find_by(submission: submission, email: params[:email].to_s.downcase)
|
|
||||||
end
|
|
||||||
|
|
||||||
return redirect_to submissions_preview_completed_path(params[:submission_slug], status: :error) unless @submitter
|
return redirect_to submissions_preview_completed_path(params[:submission_slug], status: :error) unless @submitter
|
||||||
else
|
else
|
||||||
@submitter = Submitter.completed.find_by!(slug: params[:submitter_slug])
|
@submitter = Submitter.find_by!(slug: params[:submitter_slug])
|
||||||
end
|
end
|
||||||
|
|
||||||
if @submitter
|
if @submitter && completed_submitter?(@submitter)
|
||||||
RateLimit.call("send-email-#{@submitter.id}", limit: 2, ttl: 5.minutes)
|
RateLimit.call("send-email-#{@submitter.id}", limit: 2, ttl: 5.minutes)
|
||||||
|
|
||||||
SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later! if can_send?(@submitter)
|
SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later! if can_send?(@submitter)
|
||||||
@@ -41,6 +39,10 @@ class SendSubmissionEmailController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def completed_submitter?(submitter)
|
||||||
|
submitter.completed_at? || (submitter.viewer? && submitter.submission.completed_at?)
|
||||||
|
end
|
||||||
|
|
||||||
def can_send?(submitter)
|
def can_send?(submitter)
|
||||||
return false if submitter.account.archived_at?
|
return false if submitter.account.archived_at?
|
||||||
return false if EmailEvent.exists?(tag: :submitter_documents_copy, email: submitter.email, emailable: submitter,
|
return false if EmailEvent.exists?(tag: :submitter_documents_copy, email: submitter.email, emailable: submitter,
|
||||||
|
|||||||
@@ -141,8 +141,7 @@ class StartFormController < ApplicationController
|
|||||||
|
|
||||||
submitter ||=
|
submitter ||=
|
||||||
Submitter
|
Submitter
|
||||||
.where(submission: template.submissions.where(expire_at: Time.current..)
|
.where(submission: template.submissions.non_expired.active)
|
||||||
.or(template.submissions.where(expire_at: nil)).where(archived_at: nil))
|
|
||||||
.order(id: :desc)
|
.order(id: :desc)
|
||||||
.where(declined_at: nil)
|
.where(declined_at: nil)
|
||||||
.where(external_id: nil)
|
.where(external_id: nil)
|
||||||
@@ -150,6 +149,8 @@ class StartFormController < ApplicationController
|
|||||||
.then { |rel| params[:resubmit].present? || params[:selfsign].present? ? rel.where(completed_at: nil) : rel }
|
.then { |rel| params[:resubmit].present? || params[:selfsign].present? ? rel.where(completed_at: nil) : rel }
|
||||||
.find_or_initialize_by(find_params)
|
.find_or_initialize_by(find_params)
|
||||||
|
|
||||||
|
submitter = Submitter.new(find_params) if submitter.submission&.completed_at? && submitter.viewer?
|
||||||
|
|
||||||
submitter.name = required_params['name'] if submitter.new_record?
|
submitter.name = required_params['name'] if submitter.new_record?
|
||||||
|
|
||||||
unless @resubmit_submitter
|
unless @resubmit_submitter
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class SubmitFormCompletedDownloadController < ApplicationController
|
|||||||
|
|
||||||
@submitter ||= Submitter.find_by!(slug: submitter_slug)
|
@submitter ||= Submitter.find_by!(slug: submitter_slug)
|
||||||
|
|
||||||
Submissions::EnsureResultGenerated.call(@submitter)
|
Submissions::EnsureResultGenerated.call(@submitter) if @submitter.completed_at?
|
||||||
|
|
||||||
last_submitter = @submitter.submission.submitters.where.not(completed_at: nil).order(:completed_at).last
|
last_submitter = @submitter.submission.submitters.where.not(completed_at: nil).order(:completed_at).last
|
||||||
|
|
||||||
@@ -28,11 +28,7 @@ class SubmitFormCompletedDownloadController < ApplicationController
|
|||||||
Submissions::EnsureResultGenerated.call(last_submitter)
|
Submissions::EnsureResultGenerated.call(last_submitter)
|
||||||
|
|
||||||
if !signature_valid && !current_user_submitter?(last_submitter)
|
if !signature_valid && !current_user_submitter?(last_submitter)
|
||||||
unless Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
return head :not_found unless Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||||
Rollbar.info("2FA download error: #{last_submitter.id}") if defined?(Rollbar)
|
|
||||||
|
|
||||||
return head :not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
if last_submitter.completed_at < TTL.ago
|
if last_submitter.completed_at < TTL.ago
|
||||||
Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar)
|
Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar)
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ class SubmitFormController < ApplicationController
|
|||||||
submission = @submitter.submission
|
submission = @submitter.submission
|
||||||
|
|
||||||
return render :email_2fa unless Submitters::AuthorizedForForm.pass_email_2fa?(@submitter, request)
|
return render :email_2fa unless Submitters::AuthorizedForForm.pass_email_2fa?(@submitter, request)
|
||||||
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
|
||||||
|
if @submitter.completed_at? || submission.completed_at?
|
||||||
|
return redirect_to submit_form_completed_path(@submitter.slug)
|
||||||
|
end
|
||||||
|
|
||||||
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class SubmitFormDownloadController < ApplicationController
|
|||||||
return head :unprocessable_content if @submitter.declined_at? ||
|
return head :unprocessable_content if @submitter.declined_at? ||
|
||||||
@submitter.submission.archived_at? ||
|
@submitter.submission.archived_at? ||
|
||||||
@submitter.submission.expired? ||
|
@submitter.submission.expired? ||
|
||||||
|
@submitter.submission.completed_at? ||
|
||||||
@submitter.submission.template&.archived_at? ||
|
@submitter.submission.template&.archived_at? ||
|
||||||
AccountConfig.exists?(account_id: @submitter.account_id,
|
AccountConfig.exists?(account_id: @submitter.account_id,
|
||||||
key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||||
|
|||||||
@@ -7,13 +7,7 @@ class SubmitFormMetadataController < ApplicationController
|
|||||||
def index
|
def index
|
||||||
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
||||||
|
|
||||||
return head :not_found if @submitter.declined_at? ||
|
return head :not_found unless authorized_submitter?(@submitter)
|
||||||
@submitter.completed_at? ||
|
|
||||||
@submitter.submission.archived_at? ||
|
|
||||||
@submitter.submission.expired? ||
|
|
||||||
@submitter.submission.template&.archived_at? ||
|
|
||||||
@submitter.account.archived_at? ||
|
|
||||||
!Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
|
||||||
|
|
||||||
submission = @submitter.submission
|
submission = @submitter.submission
|
||||||
values = submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) }
|
values = submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) }
|
||||||
@@ -34,4 +28,17 @@ class SubmitFormMetadataController < ApplicationController
|
|||||||
|
|
||||||
render json: { text_runs: }
|
render json: { text_runs: }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def authorized_submitter?(submitter)
|
||||||
|
!submitter.declined_at? &&
|
||||||
|
!submitter.completed_at? &&
|
||||||
|
!submitter.submission.archived_at? &&
|
||||||
|
!submitter.submission.completed_at? &&
|
||||||
|
!submitter.submission.expired? &&
|
||||||
|
!submitter.submission.template&.archived_at? &&
|
||||||
|
!submitter.account.archived_at? &&
|
||||||
|
Submitters::AuthorizedForForm.call(submitter, current_user, request)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class SubmittersController < ApplicationController
|
|||||||
|
|
||||||
def submitter_editable?(submission)
|
def submitter_editable?(submission)
|
||||||
!@submitter.submission_events.exists?(event_type: 'start_form') &&
|
!@submitter.submission_events.exists?(event_type: 'start_form') &&
|
||||||
!@submitter.completed_at? && !@submitter.declined_at? &&
|
!@submitter.completed_at? && !@submitter.declined_at? && !submission.completed_at? &&
|
||||||
!submission.archived_at? && !submission.expired? && !submission.template&.archived_at?
|
!submission.archived_at? && !submission.expired? && !submission.template&.archived_at?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
|
|
||||||
template_preferences = @submission.template&.preferences || {}
|
template_preferences = @submission.template&.preferences || {}
|
||||||
|
|
||||||
Submissions::EnsureResultGenerated.call(submitter)
|
|
||||||
|
|
||||||
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY)
|
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY)
|
||||||
|
|
||||||
add_completed_email_attachments!(
|
add_completed_email_attachments!(
|
||||||
@@ -148,8 +146,6 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
|
|
||||||
template_preferences = @submitter.template&.preferences || {}
|
template_preferences = @submitter.template&.preferences || {}
|
||||||
|
|
||||||
Submissions::EnsureResultGenerated.call(@submitter)
|
|
||||||
|
|
||||||
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY)
|
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY)
|
||||||
|
|
||||||
add_completed_email_attachments!(
|
add_completed_email_attachments!(
|
||||||
@@ -211,7 +207,7 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_completed_email_attachments!(submitter, with_audit_log: true, with_documents: true)
|
def add_completed_email_attachments!(submitter, with_audit_log: true, with_documents: true)
|
||||||
documents = with_documents ? Submitters.select_attachments_for_download(submitter) : []
|
documents = with_documents ? select_completed_documents(submitter) : []
|
||||||
|
|
||||||
filename_format = AccountConfig.find_or_initialize_by(account_id: submitter.account_id,
|
filename_format = AccountConfig.find_or_initialize_by(account_id: submitter.account_id,
|
||||||
key: AccountConfig::DOCUMENT_FILENAME_FORMAT_KEY)&.value
|
key: AccountConfig::DOCUMENT_FILENAME_FORMAT_KEY)&.value
|
||||||
@@ -268,6 +264,14 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
submitter.template&.preferences&.dig('submitters').to_a.index_by { |e| e['uuid'] }
|
submitter.template&.preferences&.dig('submitters').to_a.index_by { |e| e['uuid'] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_completed_documents(submitter)
|
||||||
|
last_submitter = Submitter.where(submission_id: submitter.submission_id).completed.order(:completed_at).last
|
||||||
|
|
||||||
|
Submissions::EnsureResultGenerated.call(last_submitter)
|
||||||
|
|
||||||
|
Submitters.select_attachments_for_download(last_submitter)
|
||||||
|
end
|
||||||
|
|
||||||
def add_attachments_with_size_limit(submitter, storage_attachments, current_size, filename_format = nil)
|
def add_attachments_with_size_limit(submitter, storage_attachments, current_size, filename_format = nil)
|
||||||
total_size = current_size
|
total_size = current_size
|
||||||
|
|
||||||
|
|||||||
@@ -92,9 +92,8 @@ class Submission < ApplicationRecord
|
|||||||
|
|
||||||
scope :active, -> { where(archived_at: nil) }
|
scope :active, -> { where(archived_at: nil) }
|
||||||
scope :archived, -> { where.not(archived_at: nil) }
|
scope :archived, -> { where.not(archived_at: nil) }
|
||||||
scope :pending, lambda {
|
scope :non_expired, -> { where(expire_at: nil).or(where(expire_at: Time.current..)) }
|
||||||
where(expire_at: nil).or(where(expire_at: Time.current..)).where(completed_at: nil)
|
scope :pending, -> { non_expired.where(completed_at: nil) }
|
||||||
}
|
|
||||||
scope :completed, -> { where.not(completed_at: nil) }
|
scope :completed, -> { where.not(completed_at: nil) }
|
||||||
scope :declined, lambda {
|
scope :declined, lambda {
|
||||||
where(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]))
|
where(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]))
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<% completed_at = @submitter.completed_at || @submitter.submission.completed_at %>
|
||||||
<main class="max-w-md mx-auto px-2 mt-12 mb-4">
|
<main class="max-w-md mx-auto px-2 mt-12 mb-4">
|
||||||
<div class="space-y-6 mx-auto">
|
<div class="space-y-6 mx-auto">
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
@@ -12,7 +13,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<p dir="auto" class="text-lg font-bold mb-1"><%= @submitter.submission.name || @submitter.submission.template&.name %></p>
|
<p dir="auto" class="text-lg font-bold mb-1"><%= @submitter.submission.name || @submitter.submission.template&.name %></p>
|
||||||
<p dir="auto" class="text-sm">
|
<p dir="auto" class="text-sm">
|
||||||
<%= t(@submitter.with_signature_fields? ? 'signed_on_time' : 'completed_on_time', time: l(@submitter.completed_at.to_date, format: :long)) %>
|
<%= t(@submitter.with_signature_fields? ? 'signed_on_time' : 'completed_on_time', time: l(completed_at.to_date, format: :long)) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
<div class="py-2"></div>
|
<div class="py-2"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if @submitter.completed_at > 30.minutes.ago || (current_user && current_user.account.submitters.exists?(id: @submitter.id)) %>
|
<% if completed_at > 30.minutes.ago || (current_user && current_user.account.submitters.exists?(id: @submitter.id)) %>
|
||||||
<download-button role="button" tabindex="0" aria-label="<%= t('download_documents') %>" data-src="<%= submit_form_documents_path(@submitter.slug) %>" class="base-button w-full">
|
<download-button role="button" tabindex="0" aria-label="<%= t('download_documents') %>" data-src="<%= submit_form_documents_path(@submitter.slug) %>" class="base-button w-full">
|
||||||
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
|
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
|
||||||
<%= svg_icon('download', class: 'w-6 h-6') %>
|
<%= svg_icon('download', class: 'w-6 h-6') %>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
||||||
<%= submitter.name || submitter.email || submitter.phone %>
|
<%= submitter.name || submitter.email || submitter.phone %>
|
||||||
</a>
|
</a>
|
||||||
<% if !submitter.completed_at? && can?(:update, submission) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
<% if !submitter.completed_at? && !submission.completed_at? && can?(:update, submission) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
||||||
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
||||||
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
||||||
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
||||||
<%= submitter.name || submitter.email || submitter.phone %>
|
<%= submitter.name || submitter.email || submitter.phone %>
|
||||||
</a>
|
</a>
|
||||||
<% if !submitter.completed_at? && can?(:update, submission) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
<% if !submitter.completed_at? && !submission.completed_at? && can?(:update, submission) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
||||||
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
||||||
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
||||||
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ module Submissions
|
|||||||
def call(submitter)
|
def call(submitter)
|
||||||
return nil unless submitter
|
return nil unless submitter
|
||||||
|
|
||||||
raise NotCompletedYet unless submitter.completed_at?
|
raise NotCompletedYet if !submitter.completed_at? ||
|
||||||
|
!submitter.submission.completed_at?
|
||||||
|
|
||||||
total_wait_time ||= 0
|
total_wait_time ||= 0
|
||||||
key = [KEY_PREFIX, submitter.id].join(':')
|
key = [KEY_PREFIX, submitter.id].join(':')
|
||||||
|
|||||||
+8
-6
@@ -105,7 +105,7 @@ module Submitters
|
|||||||
end
|
end
|
||||||
|
|
||||||
def select_attachments_for_download(submitter)
|
def select_attachments_for_download(submitter)
|
||||||
if AccountConfig.exists?(account_id: submitter.submission.account_id,
|
if AccountConfig.exists?(account_id: submitter.account_id,
|
||||||
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
|
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
|
||||||
value: true) &&
|
value: true) &&
|
||||||
submitter.submission.completed_at? &&
|
submitter.submission.completed_at? &&
|
||||||
@@ -229,10 +229,12 @@ module Submitters
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
filename = filename.gsub(
|
filename = filename.gsub('{submission.completed_at}') do
|
||||||
'{submission.completed_at}',
|
completed_at = submitter.submission.completed_at ||
|
||||||
I18n.l(submitter.completed_at.in_time_zone(submitter.account.timezone), format: :short)
|
submitter.submission.submitters.select(&:completed_at).max_by(&:completed_at).completed_at
|
||||||
)
|
|
||||||
|
I18n.l(completed_at.in_time_zone(submitter.account.timezone), format: :short)
|
||||||
|
end
|
||||||
|
|
||||||
"#{filename}.#{blob.filename.extension}"
|
"#{filename}.#{blob.filename.extension}"
|
||||||
end
|
end
|
||||||
@@ -275,7 +277,7 @@ module Submitters
|
|||||||
|
|
||||||
def build_combined_url(submitter, ttl: FILES_TTL)
|
def build_combined_url(submitter, ttl: FILES_TTL)
|
||||||
return unless submitter.submission.completed_at?
|
return unless submitter.submission.completed_at?
|
||||||
return if submitter.submission.submitters.order(:completed_at).last != submitter
|
return if submitter.submission.submitters.completed.order(:completed_at).last != submitter
|
||||||
|
|
||||||
attachment = submitter.submission.combined_document_attachment
|
attachment = submitter.submission.combined_document_attachment
|
||||||
attachment ||= Submissions::EnsureCombinedGenerated.call(submitter)
|
attachment ||= Submissions::EnsureCombinedGenerated.call(submitter)
|
||||||
|
|||||||
Reference in New Issue
Block a user