2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/spec/requests/uploads_controller_multisite_spec.rb
Martin Brennan 0d07d7fd55
FIX: Multisite prevent anons from downloading files (#37979)
Fixes an issue where, on the upload show route, the current user wass
cached when calling the endpoint, but then not looked up again when
calling RailsMultisite::ConnectionManagement.with_connection with the
site param. This meant that in theory an a logged in user on SITE A
could download a file on SITE B even though they would be anonymous
on SITE B, because the current user was cached at the start of the
request.

This commit fixes the issue by looking up the current user again when
switching to the other site.
2026-02-24 10:49:14 +10:00

121 lines
4.1 KiB
Ruby

# frozen_string_literal: true
RSpec.describe UploadsController, type: %i[multisite request] do
let!(:user) { Fabricate(:user) }
before { freeze_time }
describe "show_short" do
before { sign_in(user) }
context "when s3 uploads is enabled" do
before { setup_s3 }
fab!(:upload, :upload_s3)
context "when secure uploads is enabled and the upload is secure" do
before do
SiteSetting.secure_uploads = true
upload.update(secure: true)
end
it "redirects to the signed_url_for_path with the multisite DB name in the url" do
get(upload.short_path)
expect(response).to redirect_to(/#{RailsMultisite::ConnectionManagement.current_db}/)
end
end
end
end
describe "show" do
let!(:user) { Fabricate(:user) }
let(:upload) do
UploadCreator.new(file_from_fixtures("logo.jpg"), "logo.jpg").create_for(user.id)
end
context "when user is signed in" do
before { sign_in(user) }
it "returns a 200" do
get(
"/uploads/#{RailsMultisite::ConnectionManagement.current_db}/#{upload.sha1}.#{upload.extension}",
)
expect(response).to have_http_status(:ok)
end
end
context "when user is not signed in" do
context "when prevent_anons_from_downloading_files is enabled" do
before { SiteSetting.prevent_anons_from_downloading_files = true }
it "returns a 404" do
get(
"/uploads/#{RailsMultisite::ConnectionManagement.current_db}/#{upload.sha1}.#{upload.extension}",
)
expect(response).to have_http_status(:not_found)
end
end
end
context "when requesting an upload from a different site (logged in on request site, anon on target site)" do
before do
sign_in(user)
RailsMultisite::ConnectionManagement.with_connection("second") do
second_user =
Fabricate(
:user,
username: "s2_#{SecureRandom.hex(3)}",
email: "s2_#{SecureRandom.hex(4)}@example.com",
)
upload =
UploadCreator.new(file_from_fixtures("logo.jpg"), "logo.jpg").create_for(second_user.id)
@upload_on_second_sha1 = upload.sha1
@upload_on_second_extension = upload.extension
end
RailsMultisite::ConnectionManagement.establish_connection(db: "default")
end
it "returns 200 when prevent_anons_from_downloading_files is false" do
get("/uploads/second/#{@upload_on_second_sha1}.#{@upload_on_second_extension}")
expect(response).to have_http_status(:ok)
end
context "when prevent_anons_from_downloading_files is enabled" do
before { SiteSetting.prevent_anons_from_downloading_files = true }
it "returns 404 because current_user is evaluated for target site (anon on target)" do
get("/uploads/second/#{@upload_on_second_sha1}.#{@upload_on_second_extension}")
expect(response).to have_http_status(:not_found)
end
end
end
context "when requesting an upload from a different site as anonymous (anon on target site)" do
before do
RailsMultisite::ConnectionManagement.with_connection("second") do
second_user =
Fabricate(
:user,
username: "s2a_#{SecureRandom.hex(3)}",
email: "s2a_#{SecureRandom.hex(4)}@example.com",
)
upload =
UploadCreator.new(file_from_fixtures("logo.jpg"), "logo.jpg").create_for(second_user.id)
@upload_on_second_sha1 = upload.sha1
@upload_on_second_extension = upload.extension
end
RailsMultisite::ConnectionManagement.establish_connection(db: "default")
end
context "when prevent_anons_from_downloading_files is enabled" do
before { SiteSetting.prevent_anons_from_downloading_files = true }
it "returns 404 because current_user is nil on target site" do
get("/uploads/second/#{@upload_on_second_sha1}.#{@upload_on_second_extension}")
expect(response).to have_http_status(:not_found)
end
end
end
end
end