Commit dbc0be1b authored by Marin Jankovski's avatar Marin Jankovski

Error 501 when client is using deprecated API.

parent b8d8292b
...@@ -10,20 +10,6 @@ module Gitlab ...@@ -10,20 +10,6 @@ module Gitlab
@request = request @request = request
end end
# Return a response for a download request
# Can be a response to:
# Request from a user to get the file
# Request from gitlab-workhorse which file to serve to the user
def render_download_hypermedia_response(oid)
render_response_to_download do
if check_download_accept_header?
render_lfs_download_hypermedia(oid)
else
render_not_found
end
end
end
def render_download_object_response(oid) def render_download_object_response(oid)
render_response_to_download do render_response_to_download do
if check_download_sendfile_header? if check_download_sendfile_header?
...@@ -66,13 +52,24 @@ module Gitlab ...@@ -66,13 +52,24 @@ module Gitlab
end end
end end
def render_unsupported_deprecated_api
[
501,
{ "Content-Type" => "application/json; charset=utf-8" },
[JSON.dump({
'message' => 'Server supports batch API only, please update your Git LFS client to version 0.6.0 and up.',
'documentation_url' => "#{Gitlab.config.gitlab.url}/help",
})]
]
end
private private
def render_not_enabled def render_not_enabled
[ [
501, 501,
{ {
"Content-Type" => "application/vnd.git-lfs+json", "Content-Type" => "application/json; charset=utf-8",
}, },
[JSON.dump({ [JSON.dump({
'message' => 'Git LFS is not enabled on this GitLab server, contact your admin.', 'message' => 'Git LFS is not enabled on this GitLab server, contact your admin.',
...@@ -169,21 +166,6 @@ module Gitlab ...@@ -169,21 +166,6 @@ module Gitlab
end end
end end
def render_lfs_download_hypermedia(oid)
return render_not_found unless oid.present?
lfs_object = object_for_download(oid)
if lfs_object
[
200,
{ "Content-Type" => "application/vnd.git-lfs+json" },
[JSON.dump(download_hypermedia(oid))]
]
else
render_not_found
end
end
def render_lfs_upload_ok(oid, size, tmp_file) def render_lfs_upload_ok(oid, size, tmp_file)
if store_file(oid, size, tmp_file) if store_file(oid, size, tmp_file)
[ [
...@@ -226,10 +208,6 @@ module Gitlab ...@@ -226,10 +208,6 @@ module Gitlab
@env['HTTP_X_SENDFILE_TYPE'].to_s == "X-Sendfile" @env['HTTP_X_SENDFILE_TYPE'].to_s == "X-Sendfile"
end end
def check_download_accept_header?
@env['HTTP_ACCEPT'].to_s == "application/vnd.git-lfs+json; charset=utf-8"
end
def user_can_fetch? def user_can_fetch?
# Check user access against the project they used to initiate the pull # Check user access against the project they used to initiate the pull
@user.can?(:download_code, @origin_project) @user.can?(:download_code, @origin_project)
...@@ -305,20 +283,6 @@ module Gitlab ...@@ -305,20 +283,6 @@ module Gitlab
download_hypermedia_links(objects, selected_objects) download_hypermedia_links(objects, selected_objects)
end end
def download_hypermedia(oid)
{
'_links' => {
'download' =>
{
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{oid}",
'header' => {
'Authorization' => @env['HTTP_AUTHORIZATION']
}.compact
}
}
}
end
def download_hypermedia_links(all_objects, existing_objects) def download_hypermedia_links(all_objects, existing_objects)
all_objects.each do |object| all_objects.each do |object|
if existing_objects.include?(object['oid']) if existing_objects.include?(object['oid'])
......
...@@ -34,7 +34,7 @@ module Gitlab ...@@ -34,7 +34,7 @@ module Gitlab
case path_match[1] case path_match[1]
when "info/lfs" when "info/lfs"
lfs.render_download_hypermedia_response(oid) lfs.render_unsupported_deprecated_api
when "gitlab-lfs" when "gitlab-lfs"
lfs.render_download_object_response(oid) lfs.render_download_object_response(oid)
else else
...@@ -49,6 +49,8 @@ module Gitlab ...@@ -49,6 +49,8 @@ module Gitlab
# Check for Batch API # Check for Batch API
if post_path[0].ends_with?("/info/lfs/objects/batch") if post_path[0].ends_with?("/info/lfs/objects/batch")
lfs.render_batch_operation_response lfs.render_batch_operation_response
elsif post_path[0].ends_with?("/info/lfs/objects")
lfs.render_unsupported_deprecated_api
else else
nil nil
end end
......
...@@ -26,113 +26,52 @@ describe Gitlab::Lfs::Router do ...@@ -26,113 +26,52 @@ describe Gitlab::Lfs::Router do
let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" } let(:sample_oid) { "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80" }
let(:sample_size) { 499013 } let(:sample_size) { 499013 }
let(:respond_with_deprecated) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Server supports batch API only, please update your Git LFS client to version 0.6.0 and up.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
let(:respond_with_disabled) {[ 501, { "Content-Type"=>"application/json; charset=utf-8" }, ["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]]}
describe 'when lfs is disabled' do describe 'when lfs is disabled' do
before do before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(false) allow(Gitlab.config.lfs).to receive(:enabled).and_return(false)
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}" env['REQUEST_METHOD'] = 'POST'
body = {
'objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078
},
{ 'oid' => sample_oid,
'size' => sample_size
}
],
'operation' => 'upload'
}.to_json
env['rack.input'] = StringIO.new(body)
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/batch"
end end
it 'responds with 501' do it 'responds with 501' do
respond_with_disabled = [ 501,
{ "Content-Type"=>"application/vnd.git-lfs+json" },
["{\"message\":\"Git LFS is not enabled on this GitLab server, contact your admin.\",\"documentation_url\":\"#{Gitlab.config.gitlab.url}/help\"}"]
]
expect(lfs_router_auth.try_call).to match_array(respond_with_disabled) expect(lfs_router_auth.try_call).to match_array(respond_with_disabled)
end end
end end
describe 'when fetching lfs object' do describe 'when fetching lfs object using deprecated API' do
before do before do
enable_lfs enable_lfs
env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}" env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}"
end end
describe 'when user is authenticated' do it 'responds with 501' do
context 'and user has project download access' do expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated)
before do
@auth = authorize(user)
env["HTTP_AUTHORIZATION"] = @auth
project.lfs_objects << lfs_object
project.team << [user, :master]
end
it "responds with status 200" do
expect(lfs_router_auth.try_call.first).to eq(200)
end
it "responds with download hypermedia" do
json_response = ActiveSupport::JSON.decode(lfs_router_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
end
end
context 'and user does not have project access' do
it "responds with status 403" do
expect(lfs_router_auth.try_call.first).to eq(403)
end
end
end
describe 'when user is unauthenticated' do
context 'and user does not have download access' do
it "responds with status 401" do
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
context 'and user has download access' do
before do
project.team << [user, :master]
end
it "responds with status 401" do
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end end
end end
describe 'and project is public' do describe 'when fetching lfs object' do
context 'and project has access to the lfs object' do
before do before do
public_project.lfs_objects << lfs_object enable_lfs
end env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}"
context 'and user is authenticated' do
it "responds with status 200 and sends download hypermedia" do
expect(lfs_router_public_auth.try_call.first).to eq(200)
json_response = ActiveSupport::JSON.decode(lfs_router_public_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
expect(json_response['_links']['download']['header']).to eq({})
end
end
context 'and user is unauthenticated' do
it "responds with status 200 and sends download hypermedia" do
expect(lfs_router_public_noauth.try_call.first).to eq(200)
json_response = ActiveSupport::JSON.decode(lfs_router_public_noauth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{public_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
expect(json_response['_links']['download']['header']).to eq({})
end
end
end
context 'and project does not have access to the lfs object' do
it "responds with status 404" do
expect(lfs_router_public_auth.try_call.first).to eq(404)
end
end
end end
describe 'and request comes from gitlab-workhorse' do describe 'and request comes from gitlab-workhorse' do
before do
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}"
end
context 'without user being authorized' do context 'without user being authorized' do
it "responds with status 401" do it "responds with status 401" do
expect(lfs_router_noauth.try_call.first).to eq(401) expect(lfs_router_noauth.try_call.first).to eq(401)
...@@ -173,68 +112,17 @@ describe Gitlab::Lfs::Router do ...@@ -173,68 +112,17 @@ describe Gitlab::Lfs::Router do
end end
end end
end end
describe 'from a forked public project' do
before do
env['HTTP_ACCEPT'] = "application/vnd.git-lfs+json; charset=utf-8"
env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/#{sample_oid}"
end
context "when fetching a lfs object" do
context "and user has project download access" do
before do
public_project.lfs_objects << lfs_object
end
it "can download the lfs object" do
expect(lfs_router_forked_auth.try_call.first).to eq(200)
json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}")
expect(json_response['_links']['download']['header']).to eq({})
end
end
context "and user is not authenticated but project is public" do
before do
public_project.lfs_objects << lfs_object
end
it "can download the lfs object" do
expect(lfs_router_forked_auth.try_call.first).to eq(200)
end
end end
context "and user has project download access" do describe 'when handling lfs request using deprecated API' do
before do before do
env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897" enable_lfs
@auth = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) env['REQUEST_METHOD'] = 'POST'
env["HTTP_AUTHORIZATION"] = @auth env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/info/lfs/objects"
lfs_object_two = create(:lfs_object, :with_file, oid: "91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897", size: 1575078)
public_project.lfs_objects << lfs_object_two
end
it "can get a lfs object that is not in the forked project" do
expect(lfs_router_forked_auth.try_call.first).to eq(200)
json_response = ActiveSupport::JSON.decode(lfs_router_forked_auth.try_call.last.first)
expect(json_response['_links']['download']['href']).to eq("#{Gitlab.config.gitlab.url}/#{forked_project.path_with_namespace}.git/gitlab-lfs/objects/91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897")
expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
end
end
context "and user has project download access" do
before do
env["PATH_INFO"] = "#{forked_project.repository.path_with_namespace}.git/info/lfs/objects/267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b"
lfs_object_three = create(:lfs_object, :with_file, oid: "267c8b1d876743971e3a9978405818ff5ca731c4c870b06507619cd9b1847b6b", size: 127192524)
project.lfs_objects << lfs_object_three
end end
it "cannot get a lfs object that is not in the project" do it 'responds with 501' do
expect(lfs_router_forked_auth.try_call.first).to eq(404) expect(lfs_router_auth.try_call).to match_array(respond_with_deprecated)
end
end
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment