diff --git a/app/controllers/start_form_controller.rb b/app/controllers/start_form_controller.rb index d4df3664..2a4cb1fc 100644 --- a/app/controllers/start_form_controller.rb +++ b/app/controllers/start_form_controller.rb @@ -59,6 +59,8 @@ class StartFormController < ApplicationController elsif @submitter.errors.blank? && @submitter.save Submitters::StartForm.enqueue_new_submitter_jobs(@submitter) if is_new_record + Submitters::StartForm.assign_start_form_cookie(request, @submitter) + redirect_to submit_form_path(@submitter.slug) else render :show, status: :unprocessable_content @@ -90,7 +92,7 @@ class StartFormController < ApplicationController def find_or_initialize_submitter(template, submitter_params) submitter = Submitters::StartForm.find_or_initialize_submitter( template, submitter_params, exclude_completed: params[:resubmit].present?, - current_user:, ability: current_user && current_ability + request:, current_user:, ability: current_user && current_ability ) template.preferences.fetch('link_form_fields', ['email']).each do |key| @@ -102,6 +104,7 @@ class StartFormController < ApplicationController def require_link_2fa?(submitter, is_new_record:) return true if @template.preferences['shared_link_2fa'] == true + return false if cookies.encrypted[:start_form_slug] == submitter.slug !is_new_record && (current_user&.email != submitter.email || !current_ability.can?(:read, submitter)) end diff --git a/app/controllers/start_form_resubmit_controller.rb b/app/controllers/start_form_resubmit_controller.rb index ac11370d..52d060b4 100644 --- a/app/controllers/start_form_resubmit_controller.rb +++ b/app/controllers/start_form_resubmit_controller.rb @@ -13,7 +13,7 @@ class StartFormResubmitController < ApplicationController def update @submitter = Submitters::StartForm.find_or_initialize_submitter( - @template, submitter_params, exclude_completed: true + @template, submitter_params, exclude_completed: true, request: ) if Templates.filter_undefined_submitters(@template.submitters).size > 1 && @submitter.new_record? @@ -38,6 +38,8 @@ class StartFormResubmitController < ApplicationController elsif @submitter.save Submitters::StartForm.enqueue_new_submitter_jobs(@submitter) if is_new_record + Submitters::StartForm.assign_start_form_cookie(request, @submitter) + redirect_to submit_form_path(@submitter.slug) else render 'start_form/show', status: :unprocessable_content diff --git a/app/controllers/start_form_self_controller.rb b/app/controllers/start_form_self_controller.rb index bc371eee..989b4af8 100644 --- a/app/controllers/start_form_self_controller.rb +++ b/app/controllers/start_form_self_controller.rb @@ -26,6 +26,8 @@ class StartFormSelfController < ApplicationController Submitters::StartForm.enqueue_new_submitter_jobs(@submitter) if is_new_record + Submitters::StartForm.assign_start_form_cookie(request, @submitter) + redirect_to submit_form_path(@submitter.slug) end diff --git a/lib/submitters/start_form.rb b/lib/submitters/start_form.rb index a6e4dd5f..ee45b196 100644 --- a/lib/submitters/start_form.rb +++ b/lib/submitters/start_form.rb @@ -3,7 +3,8 @@ module Submitters module StartForm COOKIES_TTL = 12.hours - RESUBMIT_TTL = 8.days + START_FORM_COOKIES_TTL = 7.days + RESUBMIT_TTL = 3.days COOKIES_DEFAULTS = { httponly: true, secure: Rails.env.production? }.freeze NotSaved = Class.new(StandardError) @@ -16,28 +17,40 @@ module Submitters submitter.account.account_configs.find_or_initialize_by(key: AccountConfig::ALLOW_TO_RESUBMIT).value != false end - def can_reopen?(template, submitter, current_user:, ability:) - Docuseal.multitenant? || !submitter.persisted? || submitter.completed_at? || - (current_user&.email == submitter.email && ability.can?(:read, submitter)) || - template.preferences['shared_link_2fa'] == true || Accounts.can_send_emails?(template.account) + def can_reopen?(template, submitter, request:, current_user:, ability:) + return false if submitter.submission&.completed_at? && submitter.viewer? + return true if request.cookie_jar.encrypted[:start_form_slug] == submitter.slug + return false if submitter.email.blank? + return true if submitter.completed_at? || Docuseal.multitenant? + return true if current_user&.email == submitter.email && ability.can?(:read, submitter) + return true if template.preferences['shared_link_2fa'] == true + + Accounts.can_send_emails?(template.account) + end + + def assign_start_form_cookie(request, submitter) + request.cookie_jar.encrypted[:start_form_slug] = + { value: submitter.slug, expires: START_FORM_COOKIES_TTL.from_now, **COOKIES_DEFAULTS } end - def find_or_initialize_submitter(template, submitter_params, exclude_completed:, current_user: nil, ability: nil) + def find_or_initialize_submitter(template, submitter_params, exclude_completed:, request:, + current_user: nil, ability: nil) required_fields = template.preferences.fetch('link_form_fields', ['email']) required_params = required_fields.index_with { |key| submitter_params[key] } find_params = required_params.except('name') - submitter = Submitter.new if find_params.compact_blank.blank? - - submitter ||= build_submitters_scope(template, exclude_completed:).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? + submitter = + if find_params.compact_blank.blank? + Submitter.new + else + build_submitters_scope(template, exclude_completed:).find_or_initialize_by(find_params) + end - submitter = Submitter.new(find_params) unless can_reopen?(template, submitter, current_user:, ability:) + if submitter.persisted? && !can_reopen?(template, submitter, request:, current_user:, ability:) + submitter = Submitter.new(find_params) + end submitter.name = required_params['name'] if submitter.new_record? @@ -99,6 +112,8 @@ module Submitters enqueue_new_submitter_jobs(submitter) if is_new_record + assign_start_form_cookie(request, submitter) + if is_otp_verified SubmissionEvents.create_with_tracking_data(submitter, 'email_verified', request)