Files
once-campfire/test/controllers/active_storage/direct_uploads_controller_test.rb
T
Jeremy Daer ed5a172871 Require authentication for ActiveStorage direct-upload write endpoints
ActiveStorage's direct-upload endpoints ship unauthenticated by Rails
default: ActiveStorage::DirectUploadsController and DiskController inherit
from ActionController::Base, so they bypass the app's Authentication
concern. That leaves the write path open — anyone could mint blob records
and PUT bytes to local disk storage.

Campfire never uses direct upload for legitimate attachments. Those flow
through MessagesController#create (already authenticated), and Trix file
drops are disabled in the composer. Gating the write path is therefore
pure defense-in-depth with no functional cost.

Require an authenticated session on the two write actions
(DirectUploadsController#create and DiskController#update) by including the
existing Authentication concern. Blob serving stays public —
DiskController#show keeps its auth skip, and the Blobs/Representations
controllers are untouched — so message attachments and the account logo
keep loading. Because these controllers live in ActiveStorage::Engine and
only see the engine's url helpers, also include the application route
helpers so the concern can redirect to new_session_url on failure (302,
write blocked).
2026-06-15 13:00:29 -07:00

43 lines
1.2 KiB
Ruby

require "test_helper"
class ActiveStorage::DirectUploadsControllerTest < ActionDispatch::IntegrationTest
setup do
host! "once.campfire.test"
end
test "create requires authentication" do
assert_no_difference -> { ActiveStorage::Blob.count } do
post rails_direct_uploads_url, params: { blob: blob_params }
end
assert_redirected_to new_session_url
end
test "create succeeds for an authenticated session" do
sign_in :david
assert_difference -> { ActiveStorage::Blob.count }, 1 do
post rails_direct_uploads_url, params: { blob: blob_params }
end
assert_response :success
end
test "disk show stays reachable without authentication" do
blob = ActiveStorage::Blob.create_and_upload! \
io: StringIO.new("hello"), filename: "hello.txt", content_type: "text/plain"
ActiveStorage::Current.url_options = { host: "once.campfire.test", protocol: "http" }
get blob.url
assert_response :success
end
private
def blob_params
content = "hello"
{ filename: "hello.txt", byte_size: content.bytesize, content_type: "text/plain", \
checksum: Digest::MD5.base64digest(content) }
end
end