From 807463c46555b2f783753b986c3676ff8f7b8362 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Sun, 16 Aug 2026 13:21:02 +0300 Subject: [PATCH] optimize shared link --- app/controllers/start_form_controller.rb | 46 +++++++++++++------ .../start_form_email_2fa_send_controller.rb | 21 ++++++++- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/app/controllers/start_form_controller.rb b/app/controllers/start_form_controller.rb index accf6798..e8aa1614 100644 --- a/app/controllers/start_form_controller.rb +++ b/app/controllers/start_form_controller.rb @@ -23,8 +23,7 @@ class StartFormController < ApplicationController if @template.shared_link? @submitter = @template.submissions.new(account_id: @template.account_id) .submitters.new(account_id: @template.account_id, - uuid: (filter_undefined_submitters(@template).first || - @template.submitters.first)['uuid']) + uuid: first_submitter_uuid(@template)) render :email_verification if params[:email_verification] else Rollbar.warning("Not shared template: #{@template.id}") if defined?(Rollbar) @@ -55,7 +54,10 @@ class StartFormController < ApplicationController @submitter.assign_attributes(ip: request.remote_ip, ua: request.user_agent) end - if @template.preferences['shared_link_2fa'] == true + if @template.preferences['shared_link_2fa'] == true || + (!is_new_record && @resubmit_submitter.blank? && !own_submitter?(@submitter)) + Rollbar.info("2FA requested: #{@submitter.id}") if !is_new_record && defined?(Rollbar) + handle_require_2fa(@submitter, is_new_record:) elsif @submitter.errors.blank? && @submitter.save enqueue_new_submitter_jobs(@submitter) if is_new_record @@ -110,6 +112,10 @@ class StartFormController < ApplicationController end end + def own_submitter?(submitter) + current_user&.email == submitter.email && current_ability.can?(:read, submitter) + end + def can_resubmit?(submitter) submitter.completed_at? && submitter.completed_at > 14.days.ago && %w[api embed mcp].exclude?(submitter.submission.source) && @@ -139,18 +145,18 @@ class StartFormController < ApplicationController submitter = Submitter.new if find_params.compact_blank.blank? - submitter ||= - Submitter - .where(submission: template.submissions.non_expired.active) - .order(id: :desc) - .where(declined_at: nil) - .where(external_id: nil) - .where(template.preferences['shared_link_2fa'] == true ? {} : { ip: [nil, request.remote_ip] }) - .then { |rel| params[:resubmit].present? || params[:selfsign].present? ? rel.where(completed_at: nil) : rel } - .find_or_initialize_by(find_params) + submitter ||= build_submitters_scope(template).find_or_initialize_by(find_params) + + submitter = Submitter.new(find_params) if submitter.persisted? && submitter.email.blank? submitter = Submitter.new(find_params) if submitter.submission&.completed_at? && submitter.viewer? + if !Docuseal.multitenant? && submitter.persisted? && !submitter.completed_at? && + @resubmit_submitter.blank? && !own_submitter?(submitter) && + template.preferences['shared_link_2fa'] != true && !Accounts.can_send_emails?(template.account) + submitter = Submitter.new(find_params) + end + submitter.name = required_params['name'] if submitter.new_record? unless @resubmit_submitter @@ -162,9 +168,19 @@ class StartFormController < ApplicationController submitter end + def build_submitters_scope(template) + Submitter + .where(submission: template.submissions.non_expired.active) + .where(uuid: template.submitters.pluck('uuid')) + .order(id: :desc) + .where(declined_at: nil) + .where(external_id: nil) + .then { |rel| params[:resubmit].present? || params[:selfsign].present? ? rel.where(completed_at: nil) : rel } + end + def assign_submission_attributes(submitter, template) submitter.assign_attributes( - uuid: (filter_undefined_submitters(template).first || @template.submitters.first)['uuid'], + uuid: first_submitter_uuid(template), ip: request.remote_ip, ua: request.user_agent, values: @resubmit_submitter&.preferences&.fetch('default_values', nil) || {}, @@ -198,6 +214,10 @@ class StartFormController < ApplicationController Templates.filter_undefined_submitters(template.submitters) end + def first_submitter_uuid(template) + (filter_undefined_submitters(template).first || template.submitters.first)['uuid'] + end + def submitter_params return { 'email' => current_user.email, 'name' => current_user.full_name } if params[:selfsign] return @resubmit_submitter.slice(:name, :phone, :email) if @resubmit_submitter.present? diff --git a/app/controllers/start_form_email_2fa_send_controller.rb b/app/controllers/start_form_email_2fa_send_controller.rb index eb20dfc7..8b619f78 100644 --- a/app/controllers/start_form_email_2fa_send_controller.rb +++ b/app/controllers/start_form_email_2fa_send_controller.rb @@ -13,6 +13,11 @@ class StartFormEmail2faSendController < ApplicationController @submitter = @template.submissions.new(account_id: @template.account_id) .submitters.new(**submitter_params, account_id: @template.account_id) + if @submitter.email.blank? + return redirect_to start_form_path(@template.slug), + alert: I18n.t(:provide_your_email_to_start), status: :unprocessable_content + end + Submitters.send_shared_link_email_verification_code(@submitter, request:) redir_params = { notice: I18n.t(:code_has_been_resent) } if params[:resend] @@ -36,13 +41,27 @@ class StartFormEmail2faSendController < ApplicationController return redirect_to start_form_path(@template.slug) if is_archived return if (@template.shared_link? || (current_user && current_ability.can?(:read, @template))) && - @template.preferences['shared_link_2fa'] == true + (@template.preferences['shared_link_2fa'] == true || submitter_exists?(@template, params)) Rollbar.warning("Not shared template: #{@template.id}") if defined?(Rollbar) redirect_to start_form_path(@template.slug) end + def submitter_exists?(template, params) + email = Submissions.normalize_email(params.dig(:submitter, :email)) + + return false if email.blank? + + Submitter + .where(submission: template.submissions.non_expired.active) + .where(uuid: template.submitters.pluck('uuid')) + .where(declined_at: nil) + .where(external_id: nil) + .where(completed_at: nil) + .exists?(email:) + end + def submitter_params params.require(:submitter).permit(:name, :email, :phone) end