discourse/spec/system/s3_uploads_spec.rb
Alan Guo Xiang Tan 95ac3a984d
FIX: Enforce content disposition on S3 presigned URLs (#38850)
Presigned S3 URLs only set `Content-Disposition` when `force_download`
was true. Secure uploads and signed paths for dangerous file types
(HTML, SVG, XML) could be served inline.

This commit makes `S3Store#signed_url_for_path` always set
`Content-Disposition` on browser-facing presigned URLs, using
`FileHelper.is_inline_safe?` to choose between `inline` and `attachment`
disposition.

A required `include_content_disposition:` kwarg is added to
`S3Store#signed_url_for_path` so every caller explicitly opts in or out.
Server-side downloads pass `false` since they don't need the header and
the extra query parameter can push presigned URLs over the 2000
character `UrlHelper.normalized_encode` limit.

The S3 multipart upload system spec is also re-enabled as the
intermittent failures are no longer reproducible.
2026-03-27 10:04:00 +08:00

53 lines
1.6 KiB
Ruby

# frozen_string_literal: true
describe "Uploading files in the composer to S3" do
fab!(:current_user, :admin)
let(:modal) { PageObjects::Modals::Base.new }
let(:composer) { PageObjects::Components::Composer.new }
let(:topic) { PageObjects::Pages::Topic.new }
describe "direct S3 uploads" do
describe "single part uploads" do
it "uploads custom avatars to S3" do
setup_or_skip_s3_system_test
sign_in(current_user)
visit "/my/preferences/account"
find("#edit-avatar").click
find("#uploaded-avatar").click
attach_file(
"custom-profile-upload",
File.absolute_path(file_from_fixtures("logo.jpg")),
make_visible: true,
)
expect(page).to have_css(".avatar-uploader .avatar-uploader__button[data-uploaded]")
modal.click_primary_button
expect(modal).to be_closed
expect(page).to have_css(
"#user-avatar-uploads[data-custom-avatar-upload-id]",
visible: :hidden,
)
expect(current_user.reload.uploaded_avatar_id).to eq(
find("#user-avatar-uploads", visible: false)["data-custom-avatar-upload-id"].to_i,
)
end
end
describe "multipart uploads" do
it "uploads a file in the post composer" do
setup_or_skip_s3_system_test
sign_in(current_user)
topic.open_new_topic
file_path = file_from_fixtures("logo.png", "images").path
attach_file("file-uploader", file_path, make_visible: true)
expect(page).to have_no_css("#file-uploading")
expect(composer.preview).to have_css(".image-wrapper")
end
end
end
end