gitlab-org--gitlab-foss/spec/lib/api/helpers_spec.rb
Stan Hu 41b51c0656 Encode Content-Disposition filenames
Users downloading non-ASCII attachments would see garbled characters.
When used with object storage, AWS S3 would return an InvalidArgument
error: Header value cannot be represented using ISO-8859-1.

Per RFC 5987 and RFC 6266, Content-Disposition should be encoded
properly. This commit takes the Rails 6 implementation of
ActiveSuppport::Http::ContentDisposition
(https://github.com/rails/rails/pull/33829) and ports it here.

Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/47673
2019-02-04 23:12:44 -08:00

187 lines
4.9 KiB
Ruby

require 'spec_helper'
describe API::Helpers do
subject { Class.new.include(described_class).new }
describe '#find_project' do
let(:project) { create(:project) }
shared_examples 'project finder' do
context 'when project exists' do
it 'returns requested project' do
expect(subject.find_project(existing_id)).to eq(project)
end
it 'returns nil' do
expect(subject.find_project(non_existing_id)).to be_nil
end
end
end
context 'when ID is used as an argument' do
let(:existing_id) { project.id }
let(:non_existing_id) { (Project.maximum(:id) || 0) + 1 }
it_behaves_like 'project finder'
end
context 'when PATH is used as an argument' do
let(:existing_id) { project.full_path }
let(:non_existing_id) { 'something/else' }
it_behaves_like 'project finder'
context 'with an invalid PATH' do
let(:non_existing_id) { 'undefined' } # path without slash
it_behaves_like 'project finder'
it 'does not hit the database' do
expect(Project).not_to receive(:find_by_full_path)
subject.find_project(non_existing_id)
end
end
end
end
describe '#find_namespace' do
let(:namespace) { create(:namespace) }
shared_examples 'namespace finder' do
context 'when namespace exists' do
it 'returns requested namespace' do
expect(subject.find_namespace(existing_id)).to eq(namespace)
end
end
context "when namespace doesn't exists" do
it 'returns nil' do
expect(subject.find_namespace(non_existing_id)).to be_nil
end
end
end
context 'when ID is used as an argument' do
let(:existing_id) { namespace.id }
let(:non_existing_id) { 9999 }
it_behaves_like 'namespace finder'
end
context 'when PATH is used as an argument' do
let(:existing_id) { namespace.path }
let(:non_existing_id) { 'non-existing-path' }
it_behaves_like 'namespace finder'
end
end
shared_examples 'user namespace finder' do
let(:user1) { create(:user) }
before do
allow(subject).to receive(:current_user).and_return(user1)
allow(subject).to receive(:header).and_return(nil)
allow(subject).to receive(:not_found!).and_raise('404 Namespace not found')
end
context 'when namespace is group' do
let(:namespace) { create(:group) }
context 'when user has access to group' do
before do
namespace.add_guest(user1)
namespace.save!
end
it 'returns requested namespace' do
expect(namespace_finder).to eq(namespace)
end
end
context "when user doesn't have access to group" do
it 'raises not found error' do
expect { namespace_finder }.to raise_error(RuntimeError, '404 Namespace not found')
end
end
end
context "when namespace is user's personal namespace" do
let(:namespace) { create(:namespace) }
context 'when user owns the namespace' do
before do
namespace.owner = user1
namespace.save!
end
it 'returns requested namespace' do
expect(namespace_finder).to eq(namespace)
end
end
context "when user doesn't own the namespace" do
it 'raises not found error' do
expect { namespace_finder }.to raise_error(RuntimeError, '404 Namespace not found')
end
end
end
end
describe '#find_namespace!' do
let(:namespace_finder) do
subject.find_namespace!(namespace.id)
end
it_behaves_like 'user namespace finder'
end
describe '#user_namespace' do
let(:namespace_finder) do
subject.user_namespace
end
before do
allow(subject).to receive(:params).and_return({ id: namespace.id })
end
it_behaves_like 'user namespace finder'
end
describe '#send_git_blob' do
let(:repository) { double }
let(:blob) { double(name: 'foobar') }
let(:send_git_blob) do
subject.send(:send_git_blob, repository, blob)
end
before do
allow(subject).to receive(:env).and_return({})
allow(subject).to receive(:content_type)
allow(subject).to receive(:header).and_return({})
allow(Gitlab::Workhorse).to receive(:send_git_blob)
end
it 'sets Gitlab::Workhorse::DETECT_HEADER header' do
expect(send_git_blob[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
context 'content disposition' do
context 'when blob name is null' do
let(:blob) { double(name: nil) }
it 'returns only the disposition' do
expect(send_git_blob['Content-Disposition']).to eq 'inline'
end
end
context 'when blob name is not null' do
it 'returns disposition with the blob name' do
expect(send_git_blob['Content-Disposition']).to eq %q(inline; filename="foobar"; filename*=UTF-8''foobar)
end
end
end
end
end