From 8f8b36617a85562db34aac3e042de260a6a378f6 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Fri, 10 Apr 2026 11:07:19 +0300 Subject: [PATCH] fix first party download from preview --- .../submissions_download_controller.rb | 60 +++-------------- .../submissions_preview_controller.rb | 8 ++- .../submitters_download_controller.rb | 66 +++++++++++++++++++ app/views/submissions/show.html.erb | 7 +- config/routes.rb | 3 +- lib/submitters.rb | 32 +++++++++ 6 files changed, 118 insertions(+), 58 deletions(-) create mode 100644 app/controllers/submitters_download_controller.rb diff --git a/app/controllers/submissions_download_controller.rb b/app/controllers/submissions_download_controller.rb index 39dee165..98e369be 100644 --- a/app/controllers/submissions_download_controller.rb +++ b/app/controllers/submissions_download_controller.rb @@ -5,30 +5,20 @@ class SubmissionsDownloadController < ApplicationController skip_authorization_check TTL = 40.minutes - FILES_TTL = 5.minutes def index - @submitter = Submitter.find_signed(params[:sig], purpose: :download_completed) if params[:sig].present? + @submission = Submission.find_by!(slug: params[:submission_slug] || params[:submissions_preview_slug]) - signature_valid = - if @submitter&.slug == params[:submitter_slug] - true - else - @submitter = nil - end - - @submitter ||= Submitter.find_by!(slug: params[:submitter_slug]) - - Submissions::EnsureResultGenerated.call(@submitter) - - last_submitter = @submitter.submission.submitters.where.not(completed_at: nil).order(:completed_at).last - - return head :not_found unless last_submitter + last_submitter = @submission.submitters.where.not(completed_at: nil).order(:completed_at).last Submissions::EnsureResultGenerated.call(last_submitter) - if !signature_valid && !current_user_submitter?(last_submitter) - return head :not_found unless Submitters::AuthorizedForForm.call(@submitter, current_user, request) + unless current_user_submitter?(last_submitter) + unless Submitters::AuthorizedForForm.call(last_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 Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar) @@ -40,14 +30,14 @@ class SubmissionsDownloadController < ApplicationController if params[:combined] == 'true' respond_with_combined(last_submitter) else - render json: build_urls(last_submitter) + render json: Submitters.build_document_urls(last_submitter) end end private def respond_with_combined(submitter) - url = build_combined_url(submitter) + url = Submitters.build_combined_url(submitter) if url render json: [url] @@ -59,34 +49,4 @@ class SubmissionsDownloadController < ApplicationController def current_user_submitter?(submitter) current_user && current_ability.can?(:read, submitter) end - - def build_urls(submitter) - filename_format = AccountConfig.find_or_initialize_by(account_id: submitter.account_id, - key: AccountConfig::DOCUMENT_FILENAME_FORMAT_KEY)&.value - - Submitters.select_attachments_for_download(submitter).map do |attachment| - ActiveStorage::Blob.proxy_path( - attachment.blob, - expires_at: FILES_TTL.from_now.to_i, - filename: Submitters.build_document_filename(submitter, attachment.blob, filename_format) - ) - end - end - - def build_combined_url(submitter) - return if submitter.submission.submitters.exists?(completed_at: nil) - return if submitter.submission.submitters.order(:completed_at).last != submitter - - attachment = submitter.submission.combined_document_attachment - attachment ||= Submissions::EnsureCombinedGenerated.call(submitter) - - filename_format = AccountConfig.find_or_initialize_by(account_id: submitter.account_id, - key: AccountConfig::DOCUMENT_FILENAME_FORMAT_KEY)&.value - - ActiveStorage::Blob.proxy_path( - attachment.blob, - expires_at: FILES_TTL.from_now.to_i, - filename: Submitters.build_document_filename(submitter, attachment.blob, filename_format) - ) - end end diff --git a/app/controllers/submissions_preview_controller.rb b/app/controllers/submissions_preview_controller.rb index 6163c36b..10e45358 100644 --- a/app/controllers/submissions_preview_controller.rb +++ b/app/controllers/submissions_preview_controller.rb @@ -10,13 +10,15 @@ class SubmissionsPreviewController < ApplicationController TTL = 40.minutes def show - submitter = Submitter.find_signed(params[:sig], purpose: :download_completed) if params[:sig].present? + @sig_submitter = Submitter.find_signed(params[:sig], purpose: :download_completed) if params[:sig].present? signature_valid = - if submitter && submitter.submission.slug == params[:slug] - @submission = submitter.submission + if @sig_submitter && @sig_submitter.submission.slug == params[:slug] + @submission = @sig_submitter.submission true + else + @sig_submitter = nil end @submission ||= Submission.find_by!(slug: params[:slug]) diff --git a/app/controllers/submitters_download_controller.rb b/app/controllers/submitters_download_controller.rb new file mode 100644 index 00000000..28a354bc --- /dev/null +++ b/app/controllers/submitters_download_controller.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +class SubmittersDownloadController < ApplicationController + skip_before_action :authenticate_user! + skip_authorization_check + + TTL = 40.minutes + FILES_TTL = 5.minutes + + def index + @submitter = Submitter.find_signed(params[:sig], purpose: :download_completed) if params[:sig].present? + + signature_valid = + if @submitter&.slug == params[:submitter_slug] + true + else + @submitter = nil + end + + @submitter ||= Submitter.find_by!(slug: params[:submitter_slug]) + + Submissions::EnsureResultGenerated.call(@submitter) + + last_submitter = @submitter.submission.submitters.where.not(completed_at: nil).order(:completed_at).last + + return head :not_found unless last_submitter + + Submissions::EnsureResultGenerated.call(last_submitter) + + if !signature_valid && !current_user_submitter?(last_submitter) + 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 + Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar) + + return head :not_found + end + end + + if params[:combined] == 'true' + respond_with_combined(last_submitter) + else + render json: Submitters.build_document_urls(last_submitter) + end + end + + private + + def respond_with_combined(submitter) + url = Submitters.build_combined_url(submitter) + + if url + render json: [url] + else + head :not_found + end + end + + def current_user_submitter?(submitter) + current_user && current_ability.can?(:read, submitter) + end +end diff --git a/app/views/submissions/show.html.erb b/app/views/submissions/show.html.erb index f925f6ce..bf8e6eba 100644 --- a/app/views/submissions/show.html.erb +++ b/app/views/submissions/show.html.erb @@ -15,7 +15,6 @@ <% (@submission.name || @submission.template.name).split(/(_)/).each do |item| %><%= item %><% end %>
- <% last_submitter = @submission.submitters.to_a.select(&:completed_at?).max_by(&:completed_at) %> <% is_all_completed = @submission.submitters.to_a.all?(&:completed_at?) %> <% if signed_in? && can?(:create, @submission) && @submission.archived_at? && !is_all_completed %> <%= button_to button_title(title: t('unarchive'), disabled_with: t('unarchive')[0..-2], icon: svg_icon('rotate', class: 'w-6 h-6')), submission_unarchive_index_path(@submission), class: 'btn btn-primary btn-ghost text-base hidden md:flex' %> @@ -31,10 +30,10 @@ <% end %> <% end %> - <% if last_submitter %> + <% if is_all_completed || @submission.submitters.to_a.any?(&:completed_at?) %> <% if is_all_completed || !is_combined_enabled %>
- + <%= svg_icon('download', class: 'w-6 h-6') %> @@ -53,7 +52,7 @@