Files
docuseal/app/controllers/api/submissions_controller.rb
T

220 lines
7.9 KiB
Ruby
Raw Normal View History

2023-08-04 00:40:13 +03:00
# frozen_string_literal: true
module Api
class SubmissionsController < ApiBaseController
2023-10-01 01:57:47 +03:00
load_and_authorize_resource :template, only: :create
2023-11-16 01:55:57 +02:00
load_and_authorize_resource :submission, only: %i[show index destroy]
2023-09-17 00:45:57 +03:00
2023-10-01 01:57:47 +03:00
before_action only: :create do
2023-09-17 00:45:57 +03:00
authorize!(:create, Submission)
end
2023-08-04 00:40:13 +03:00
2023-10-01 01:57:47 +03:00
def index
2025-06-05 13:16:55 +03:00
submissions = Submissions.search(current_user, @submissions, params[:q])
2025-04-15 13:22:02 +03:00
submissions = filter_submissions(submissions, params)
2025-01-03 20:27:55 +02:00
2024-04-11 16:36:53 +03:00
submissions = paginate(submissions.preload(:created_by_user, :submitters,
2025-07-20 08:28:19 +03:00
template: { folder: :parent_folder },
2024-08-23 23:46:22 +03:00
combined_document_attachment: :blob,
2023-11-01 12:17:35 +02:00
audit_trail_attachment: :blob))
2023-10-01 01:57:47 +03:00
2025-08-31 16:40:18 +03:00
expires_at = Accounts.link_expires_at(current_account)
2023-10-01 01:57:47 +03:00
render json: {
2024-08-27 01:50:26 +03:00
data: submissions.map do |s|
Submissions::SerializeForApi.call(s, s.submitters, params,
2025-08-31 16:40:18 +03:00
with_events: false, with_documents: false, with_values: false, expires_at:)
2024-08-27 01:50:26 +03:00
end,
2023-10-01 01:57:47 +03:00
pagination: {
count: submissions.size,
next: submissions.last&.id,
prev: submissions.first&.id
}
}
end
def show
submitters = @submission.submitters.preload(documents_attachments: :blob, attachments_attachments: :blob)
2023-10-01 01:57:47 +03:00
2024-02-10 19:38:03 +02:00
submitters.each do |submitter|
if submitter.completed_at? && submitter.documents_attachments.blank?
submitter.documents_attachments = Submissions::EnsureResultGenerated.call(submitter)
end
end
2024-02-10 19:38:03 +02:00
if @submission.audit_trail_attachment.blank? && submitters.all?(&:completed_at?)
2025-09-15 09:10:03 +03:00
@submission.audit_trail_attachment = Submissions::EnsureAuditGenerated.call(@submission)
end
2023-10-01 01:57:47 +03:00
2024-07-01 12:06:05 +03:00
render json: Submissions::SerializeForApi.call(@submission, submitters, params)
2023-10-01 01:57:47 +03:00
end
2023-09-17 00:45:57 +03:00
def create
2024-04-27 21:35:20 +03:00
Params::SubmissionCreateValidator.call(params)
2024-01-19 03:03:45 +02:00
2025-08-14 09:25:35 +03:00
return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil?
2023-12-28 17:39:09 +02:00
2026-06-09 19:34:58 +03:00
if @template.archived_at?
Rollbar.warning("Archived template submission: #{@template.id}") if defined?(Rollbar)
return render json: { error: 'Template has been archived' }, status: :unprocessable_content
end
2024-01-14 00:49:07 +02:00
if @template.fields.blank?
2024-02-16 19:44:59 +02:00
Rollbar.warning("Template does not contain fields: #{@template.id}") if defined?(Rollbar)
2024-01-14 00:49:07 +02:00
2025-08-14 09:25:35 +03:00
return render json: { error: 'Template does not contain fields' }, status: :unprocessable_content
2024-01-14 00:49:07 +02:00
end
2023-11-23 20:03:52 +02:00
params[:send_email] = true unless params.key?(:send_email)
params[:send_sms] = false unless params.key?(:send_sms)
2023-08-04 00:40:13 +03:00
2023-11-23 20:03:52 +02:00
submissions = create_submissions(@template, params)
2025-07-04 21:11:08 +03:00
WebhookUrls.enqueue_events(submissions, 'submission.created')
2024-05-17 13:28:10 +03:00
2023-11-23 20:03:52 +02:00
Submissions.send_signature_requests(submissions)
2023-08-04 00:40:13 +03:00
2024-02-10 19:38:03 +02:00
submissions.each do |submission|
2024-10-26 19:42:16 +03:00
submission.submitters.each do |submitter|
2024-12-09 01:06:57 +02:00
next unless submitter.completed_at?
ProcessSubmitterCompletionJob.perform_async('submitter_id' => submitter.id, 'send_invitation_email' => false)
2024-02-10 19:38:03 +02:00
end
end
2025-06-05 13:16:55 +03:00
SearchEntries.enqueue_reindex(submissions)
2024-07-18 23:59:27 +03:00
render json: build_create_json(submissions)
2024-10-22 22:26:08 +03:00
rescue Submitters::NormalizeValues::BaseError, Submissions::CreateFromSubmitters::BaseError,
DownloadUtils::UnableToDownload => e
2024-02-16 19:44:59 +02:00
Rollbar.warning(e) if defined?(Rollbar)
2024-02-13 22:02:15 +02:00
2025-08-14 09:25:35 +03:00
render json: { error: e.message }, status: :unprocessable_content
2023-08-04 00:40:13 +03:00
end
2023-10-01 01:57:47 +03:00
def destroy
2024-12-13 13:31:54 +02:00
if params[:permanently].in?(['true', true])
2024-06-18 16:45:07 +03:00
@submission.destroy!
else
@submission.update!(archived_at: Time.current)
2023-10-01 01:57:47 +03:00
2025-07-04 21:11:08 +03:00
WebhookUrls.enqueue_events(@submission, 'submission.archived')
2024-06-18 16:45:07 +03:00
end
2024-04-09 18:11:58 +03:00
2024-06-18 16:45:07 +03:00
render json: @submission.as_json(only: %i[id archived_at])
2023-10-01 01:57:47 +03:00
end
2023-08-04 00:40:13 +03:00
private
2025-04-15 13:22:02 +03:00
def filter_submissions(submissions, params)
submissions = submissions.where(template_id: params[:template_id]) if params[:template_id].present?
submissions = submissions.where(slug: params[:slug]) if params[:slug].present?
if params[:template_folder].present?
2025-07-20 08:28:19 +03:00
folders =
TemplateFolders.filter_by_full_name(TemplateFolder.accessible_by(current_ability), params[:template_folder])
2025-06-16 16:48:20 +03:00
2025-07-20 08:28:19 +03:00
submissions = submissions.joins(:template).where(template: { folder_id: folders.pluck(:id) })
2025-04-15 13:22:02 +03:00
end
if params.key?(:archived)
submissions = params[:archived].in?(['true', true]) ? submissions.archived : submissions.active
end
Submissions::Filter.call(submissions, current_user, params)
end
2024-07-18 23:59:27 +03:00
def build_create_json(submissions)
json = submissions.flat_map do |submission|
submission.submitters.map do |s|
Submitters::SerializeForApi.call(s, with_documents: false, with_urls: true, params:)
end
end
2025-01-02 13:18:17 +02:00
if request.path.ends_with?('/init')
json =
if submissions.size == 1
{
id: submissions.first.id,
submitters: json,
expire_at: submissions.first.expire_at,
created_at: submissions.first.created_at
}
else
{ submitters: json }
end
end
2024-07-18 23:59:27 +03:00
json
end
2023-11-23 20:03:52 +02:00
def create_submissions(template, params)
is_send_email = !params[:send_email].in?(['false', false])
2024-01-28 14:31:16 +02:00
if (emails = (params[:emails] || params[:email]).presence) &&
2025-10-04 18:33:37 +03:00
params[:submission].blank? && params[:submitters].blank?
2023-11-23 20:03:52 +02:00
Submissions.create_from_emails(template:,
user: current_user,
source: :api,
mark_as_sent: is_send_email,
emails:,
params:)
else
2023-12-17 18:39:10 +02:00
submissions_attrs, attachments =
2026-04-10 15:20:35 +03:00
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_params, template, purpose: :api)
2023-11-23 20:03:52 +02:00
submissions = Submissions.create_from_submitters(
template:,
user: current_user,
source: :api,
submitters_order: params[:submitters_order] || params[:order] || 'preserved',
submissions_attrs:,
params:
)
2024-02-10 19:38:03 +02:00
submitters = submissions.flat_map(&:submitters)
Submissions::NormalizeParamUtils.save_default_value_attachments!(attachments, submitters)
submitters.each do |submitter|
2026-02-20 12:27:39 +02:00
if submitter.completed_at?
Submitters::SubmitValues.maybe_invite_via_field(submitter, request)
SubmissionEvents.create_with_tracking_data(submitter, 'api_complete_form', request)
end
2024-02-10 19:38:03 +02:00
end
2023-11-23 20:03:52 +02:00
submissions
end
end
2023-08-04 00:40:13 +03:00
def submissions_params
2024-01-28 14:31:16 +02:00
permitted_attrs = [
2024-04-13 15:33:05 +03:00
:send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last,
2025-12-09 11:46:57 +02:00
:require_phone_2fa, :require_email_2fa, :expire_at, :name,
2024-01-28 14:31:16 +02:00
{
2025-09-12 12:17:26 +03:00
variables: {},
2024-01-28 14:31:16 +02:00
message: %i[subject body],
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
2024-04-13 15:33:05 +03:00
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
2026-01-29 12:57:26 +02:00
:require_phone_2fa, :require_email_2fa, :order, :index, :invite_by,
2025-03-16 21:56:30 +02:00
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
2024-04-27 21:35:09 +03:00
fields: [:name, :uuid, :default_value, :value, :title, :description,
2025-06-10 11:26:12 +03:00
:readonly, :required, :validation_pattern, :invalid_message,
2025-08-20 18:19:23 +03:00
{ default_value: [], value: [], preferences: {}, validation: {} }] }]]
2024-01-28 14:31:16 +02:00
}
]
if params.key?(:submitters)
params.permit(*permitted_attrs)
else
key = params.key?(:submission) ? :submission : :submissions
params.permit(
2024-12-24 00:29:25 +02:00
{ key => [permitted_attrs] }, { key => permitted_attrs }
2024-01-28 14:31:16 +02:00
).fetch(key, [])
end
2023-08-11 18:32:33 +03:00
end
2023-08-04 00:40:13 +03:00
end
end