debian-mirror-gitlab/spec/controllers/projects/raw_controller_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

297 lines
9.4 KiB
Ruby
Raw Normal View History

2019-07-31 22:56:46 +05:30
# frozen_string_literal: true
2015-09-25 12:07:36 +05:30
require 'spec_helper'
2023-04-23 21:23:45 +05:30
RSpec.describe Projects::RawController, feature_category: :source_code_management do
2019-10-12 21:52:04 +05:30
include RepoHelpers
2021-02-22 17:27:13 +05:30
let_it_be(:project) { create(:project, :public, :repository) }
2021-04-29 21:17:54 +05:30
2020-04-22 19:07:51 +05:30
let(:inline) { nil }
2022-03-02 08:16:31 +05:30
let(:params) { {} }
2018-11-20 20:47:30 +05:30
describe 'GET #show' do
2021-02-22 17:27:13 +05:30
def get_show
2023-05-27 22:25:52 +05:30
get :show, params: {
namespace_id: project.namespace, project_id: project, id: file_path, inline: inline
}.merge(params)
2018-11-20 20:47:30 +05:30
end
2015-09-25 12:07:36 +05:30
2021-02-22 17:27:13 +05:30
subject { get_show }
2023-04-23 21:23:45 +05:30
shared_examples 'limited number of Gitaly request' do
it 'makes a limited number of Gitaly request', :request_store, :clean_gitlab_redis_cache do
2021-02-22 17:27:13 +05:30
# Warm up to populate repository cache
get_show
RequestStore.clear!
2023-04-23 21:23:45 +05:30
expect { get_show }.to change { Gitlab::GitalyClient.get_request_count }.by(2)
2021-02-22 17:27:13 +05:30
end
end
2015-09-25 12:07:36 +05:30
context 'regular filename' do
2022-03-02 08:16:31 +05:30
let(:file_path) { 'master/CONTRIBUTING.md' }
2015-09-25 12:07:36 +05:30
2019-01-03 12:48:30 +05:30
it 'delivers ASCII file' do
2021-10-27 15:23:28 +05:30
allow(Gitlab::Workhorse).to receive(:send_git_blob).and_call_original
2019-01-03 12:48:30 +05:30
subject
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-01-03 12:48:30 +05:30
expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
2020-04-22 19:07:51 +05:30
expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq 'true'
2019-01-03 12:48:30 +05:30
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
2021-10-27 15:23:28 +05:30
expect(Gitlab::Workhorse).to have_received(:send_git_blob) do |repository, blob|
expected_blob = project.repository.blob_at('master', 'CONTRIBUTING.md')
expect(repository).to eq(project.repository)
expect(blob.id).to eq(expected_blob.id)
expect(blob).to be_truncated
end
2015-09-25 12:07:36 +05:30
end
2020-04-22 19:07:51 +05:30
it_behaves_like 'project cache control headers'
it_behaves_like 'content disposition headers'
2023-04-23 21:23:45 +05:30
include_examples 'limited number of Gitaly request'
2015-09-25 12:07:36 +05:30
end
context 'image header' do
2022-03-02 08:16:31 +05:30
let(:file_path) { 'master/files/images/6049019_460s.jpg' }
2015-09-25 12:07:36 +05:30
2019-02-15 15:39:39 +05:30
it 'leaves image content disposition' do
2019-01-03 12:48:30 +05:30
subject
2015-09-25 12:07:36 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-02-15 15:39:39 +05:30
expect(response.header[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
2019-01-03 12:48:30 +05:30
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
2015-09-25 12:07:36 +05:30
end
2020-04-22 19:07:51 +05:30
it_behaves_like 'project cache control headers'
it_behaves_like 'content disposition headers'
2023-04-23 21:23:45 +05:30
include_examples 'limited number of Gitaly request'
2015-09-25 12:07:36 +05:30
end
2015-12-23 02:04:40 +05:30
2020-04-22 19:07:51 +05:30
context 'with LFS files' do
2018-11-20 20:47:30 +05:30
let(:filename) { 'lfs_object.iso' }
2022-03-02 08:16:31 +05:30
let(:file_path) { "be93687/files/lfs/#{filename}" }
2020-04-22 19:07:51 +05:30
it_behaves_like 'a controller that can serve LFS files'
it_behaves_like 'project cache control headers'
2023-04-23 21:23:45 +05:30
include_examples 'limited number of Gitaly request'
2015-12-23 02:04:40 +05:30
end
2019-10-12 21:52:04 +05:30
2022-03-02 08:16:31 +05:30
context 'when the endpoint receives requests above the limit' do
2019-10-12 21:52:04 +05:30
let(:file_path) { 'master/README.md' }
2022-03-02 08:16:31 +05:30
let(:path_without_ref) { 'README.md' }
2019-10-12 21:52:04 +05:30
before do
2022-03-02 08:16:31 +05:30
allow(::Gitlab::ApplicationRateLimiter).to(
receive(:throttled?).with(:raw_blob, scope: [project, path_without_ref]).and_return(true)
)
2019-10-12 21:52:04 +05:30
end
2022-03-02 08:16:31 +05:30
it 'prevents from accessing the raw file' do
expect { get_show }.not_to change { Gitlab::GitalyClient.get_request_count }
2019-10-12 21:52:04 +05:30
2020-03-13 15:44:24 +05:30
expect(response.body).to eq(_('You cannot access the raw file. Please wait a minute.'))
expect(response).to have_gitlab_http_status(:too_many_requests)
2019-10-12 21:52:04 +05:30
end
2020-01-01 13:55:28 +05:30
context 'when receiving an external storage request' do
let(:token) { 'letmein' }
before do
stub_application_setting(
static_objects_external_storage_url: 'https://cdn.gitlab.com',
static_objects_external_storage_auth_token: token
)
end
it 'does not prevent from accessing the raw file' do
2022-03-02 08:16:31 +05:30
expect(::Gitlab::ApplicationRateLimiter).not_to receive(:throttled?)
2019-10-12 21:52:04 +05:30
2022-03-02 08:16:31 +05:30
request.headers['X-Gitlab-External-Storage-Token'] = token
get_show
2019-10-12 21:52:04 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2019-10-12 21:52:04 +05:30
end
end
end
2020-01-01 13:55:28 +05:30
context 'as a sessionless user' do
let_it_be(:project) { create(:project, :private, :repository) }
let_it_be(:user) { create(:user, static_object_token: 'very-secure-token') }
let_it_be(:file_path) { 'master/README.md' }
2022-01-12 12:59:36 +05:30
let(:token) { user.static_object_token }
2020-01-01 13:55:28 +05:30
before do
project.add_developer(user)
end
context 'when no token is provided' do
it 'redirects to sign in page' do
2022-03-02 08:16:31 +05:30
get_show
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:found)
2020-01-01 13:55:28 +05:30
expect(response.location).to end_with('/users/sign_in')
end
end
context 'when a token param is present' do
context 'when token is correct' do
2022-03-02 08:16:31 +05:30
let(:params) { { token: token } }
2020-01-01 13:55:28 +05:30
it 'calls the action normally' do
2022-03-02 08:16:31 +05:30
get_show
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2020-01-01 13:55:28 +05:30
end
2022-01-12 12:59:36 +05:30
context 'when user with expired password' do
let_it_be(:user) { create(:user, password_expires_at: 2.minutes.ago) }
it 'redirects to sign in page' do
2022-03-02 08:16:31 +05:30
get_show
2022-01-12 12:59:36 +05:30
expect(response).to have_gitlab_http_status(:found)
expect(response.location).to end_with('/users/sign_in')
end
end
context 'when password expiration is not applicable' do
context 'when ldap user' do
let_it_be(:user) { create(:omniauth_user, provider: 'ldap', password_expires_at: 2.minutes.ago) }
it 'calls the action normally' do
2022-03-02 08:16:31 +05:30
get_show
2022-01-12 12:59:36 +05:30
expect(response).to have_gitlab_http_status(:ok)
end
end
end
2020-01-01 13:55:28 +05:30
end
context 'when token is incorrect' do
2022-03-02 08:16:31 +05:30
let(:params) { { token: 'foobar' } }
2022-01-12 12:59:36 +05:30
2020-01-01 13:55:28 +05:30
it 'redirects to sign in page' do
2022-03-02 08:16:31 +05:30
get_show
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:found)
2020-01-01 13:55:28 +05:30
expect(response.location).to end_with('/users/sign_in')
end
end
end
context 'when a token header is present' do
2022-03-02 08:16:31 +05:30
before do
2022-01-12 12:59:36 +05:30
request.headers['X-Gitlab-Static-Object-Token'] = token
end
2020-01-01 13:55:28 +05:30
context 'when token is correct' do
it 'calls the action normally' do
2022-03-02 08:16:31 +05:30
get_show
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:ok)
2020-01-01 13:55:28 +05:30
end
2022-01-12 12:59:36 +05:30
context 'when user with expired password' do
let_it_be(:user) { create(:user, password_expires_at: 2.minutes.ago) }
it 'redirects to sign in page' do
2022-03-02 08:16:31 +05:30
get_show
2022-01-12 12:59:36 +05:30
expect(response).to have_gitlab_http_status(:found)
expect(response.location).to end_with('/users/sign_in')
end
end
context 'when password expiration is not applicable' do
context 'when ldap user' do
let_it_be(:user) { create(:omniauth_user, provider: 'ldap', password_expires_at: 2.minutes.ago) }
it 'calls the action normally' do
2022-03-02 08:16:31 +05:30
get_show
2022-01-12 12:59:36 +05:30
expect(response).to have_gitlab_http_status(:ok)
end
end
end
2020-01-01 13:55:28 +05:30
end
context 'when token is incorrect' do
2022-01-12 12:59:36 +05:30
let(:token) { 'foobar' }
2020-01-01 13:55:28 +05:30
it 'redirects to sign in page' do
2022-03-02 08:16:31 +05:30
get_show
2020-01-01 13:55:28 +05:30
2020-03-13 15:44:24 +05:30
expect(response).to have_gitlab_http_status(:found)
2020-01-01 13:55:28 +05:30
expect(response.location).to end_with('/users/sign_in')
end
end
end
end
2021-01-08 16:13:35 +05:30
describe 'caching' do
2023-04-23 21:23:45 +05:30
let(:ref) { project.default_branch }
2021-01-08 16:13:35 +05:30
def request_file
2023-04-23 21:23:45 +05:30
get(:show, params: { namespace_id: project.namespace, project_id: project, id: "#{ref}/README.md" })
2021-01-08 16:13:35 +05:30
end
2021-01-29 00:20:46 +05:30
it 'sets appropriate caching headers' do
sign_in create(:user)
request_file
2022-11-25 23:54:43 +05:30
expect(response.headers['ETag']).to eq("\"bdd5aa537c1e1f6d1b66de4bac8a6132\"")
2021-01-29 00:20:46 +05:30
expect(response.cache_control[:no_store]).to be_nil
2022-11-25 23:54:43 +05:30
expect(response.header['Cache-Control']).to eq(
'max-age=60, public, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60'
)
2021-01-29 00:20:46 +05:30
end
2023-04-23 21:23:45 +05:30
context 'when a blob access by permalink' do
let(:ref) { project.commit.id }
it 'sets appropriate caching headers with longer max-age' do
sign_in create(:user)
request_file
expect(response.headers['ETag']).to eq("\"bdd5aa537c1e1f6d1b66de4bac8a6132\"")
expect(response.cache_control[:no_store]).to be_nil
expect(response.header['Cache-Control']).to eq(
'max-age=3600, public, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60'
)
end
end
2021-01-08 16:13:35 +05:30
context 'when a public project has private repo' do
let(:project) { create(:project, :public, :repository, :repository_private) }
let(:user) { create(:user, maintainer_projects: [project]) }
it 'does not set public caching header' do
sign_in user
request_file
2022-11-25 23:54:43 +05:30
expect(response.header['Cache-Control']).to eq(
'max-age=60, private, must-revalidate, stale-while-revalidate=60, stale-if-error=300, s-maxage=60'
)
2021-01-29 00:20:46 +05:30
end
end
context 'when If-None-Match header is set' do
it 'returns a 304 status' do
request_file
request.headers['If-None-Match'] = response.headers['ETag']
request_file
expect(response).to have_gitlab_http_status(:not_modified)
2021-01-08 16:13:35 +05:30
end
end
end
2019-10-12 21:52:04 +05:30
end
2015-09-25 12:07:36 +05:30
end