Add support for batch download operation
This commit is contained in:
parent
56476f1847
commit
888821f9ff
|
@ -26,7 +26,7 @@ module Gitlab
|
|||
|
||||
def render_download_object_response(oid)
|
||||
render_response_to_download do
|
||||
if check_download_sendfile_header? && check_download_accept_header?
|
||||
if check_download_sendfile_header?
|
||||
render_lfs_sendfile(oid)
|
||||
else
|
||||
render_not_found
|
||||
|
@ -34,20 +34,15 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def render_lfs_api_auth
|
||||
render_response_to_push do
|
||||
request_body = JSON.parse(@request.body.read)
|
||||
return render_not_found if request_body.empty? || request_body['objects'].empty?
|
||||
|
||||
response = build_response(request_body['objects'])
|
||||
[
|
||||
200,
|
||||
{
|
||||
"Content-Type" => "application/json; charset=utf-8",
|
||||
"Cache-Control" => "private",
|
||||
},
|
||||
[JSON.dump(response)]
|
||||
]
|
||||
def render_batch_operation_response
|
||||
request_body = JSON.parse(@request.body.read)
|
||||
case request_body["operation"]
|
||||
when "download"
|
||||
render_batch_download(request_body)
|
||||
when "upload"
|
||||
render_batch_upload(request_body)
|
||||
else
|
||||
render_forbidden
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -142,6 +137,38 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def render_batch_upload(body)
|
||||
return render_not_found if body.empty? || body['objects'].nil?
|
||||
|
||||
render_response_to_push do
|
||||
response = build_upload_batch_response(body['objects'])
|
||||
[
|
||||
200,
|
||||
{
|
||||
"Content-Type" => "application/json; charset=utf-8",
|
||||
"Cache-Control" => "private",
|
||||
},
|
||||
[JSON.dump(response)]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def render_batch_download(body)
|
||||
return render_not_found if body.empty? || body['objects'].nil?
|
||||
|
||||
render_response_to_download do
|
||||
response = build_download_batch_response(body['objects'])
|
||||
[
|
||||
200,
|
||||
{
|
||||
"Content-Type" => "application/json; charset=utf-8",
|
||||
"Cache-Control" => "private",
|
||||
},
|
||||
[JSON.dump(response)]
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def render_lfs_download_hypermedia(oid)
|
||||
return render_not_found unless oid.present?
|
||||
|
||||
|
@ -266,10 +293,16 @@ module Gitlab
|
|||
@project.lfs_objects.where(oid: objects_oids).pluck(:oid).to_set
|
||||
end
|
||||
|
||||
def build_response(objects)
|
||||
def build_upload_batch_response(objects)
|
||||
selected_objects = select_existing_objects(objects)
|
||||
|
||||
upload_hypermedia(objects, selected_objects)
|
||||
upload_hypermedia_links(objects, selected_objects)
|
||||
end
|
||||
|
||||
def build_download_batch_response(objects)
|
||||
selected_objects = select_existing_objects(objects)
|
||||
|
||||
download_hypermedia_links(objects, selected_objects)
|
||||
end
|
||||
|
||||
def download_hypermedia(oid)
|
||||
|
@ -279,7 +312,6 @@ module Gitlab
|
|||
{
|
||||
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{oid}",
|
||||
'header' => {
|
||||
'Accept' => "application/vnd.git-lfs+json; charset=utf-8",
|
||||
'Authorization' => @env['HTTP_AUTHORIZATION']
|
||||
}.compact
|
||||
}
|
||||
|
@ -287,21 +319,40 @@ module Gitlab
|
|||
}
|
||||
end
|
||||
|
||||
def upload_hypermedia(all_objects, existing_objects)
|
||||
def download_hypermedia_links(all_objects, existing_objects)
|
||||
all_objects.each do |object|
|
||||
object['_links'] = hypermedia_links(object) unless existing_objects.include?(object['oid'])
|
||||
# generate links only for existing objects
|
||||
next unless existing_objects.include?(object['oid'])
|
||||
|
||||
object['_links'] = {
|
||||
'download' => {
|
||||
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}",
|
||||
'header' => {
|
||||
'Authorization' => @env['HTTP_AUTHORIZATION']
|
||||
}.compact
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
{ 'objects' => all_objects }
|
||||
end
|
||||
|
||||
def hypermedia_links(object)
|
||||
{
|
||||
"upload" => {
|
||||
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}",
|
||||
'header' => { 'Authorization' => @env['HTTP_AUTHORIZATION'] }
|
||||
}.compact
|
||||
}
|
||||
def upload_hypermedia_links(all_objects, existing_objects)
|
||||
all_objects.each do |object|
|
||||
# generate links only for non-existing objects
|
||||
next if existing_objects.include?(object['oid'])
|
||||
|
||||
object['_links'] = {
|
||||
'upload' => {
|
||||
'href' => "#{@origin_project.http_url_to_repo}/gitlab-lfs/objects/#{object['oid']}/#{object['size']}",
|
||||
'header' => {
|
||||
'Authorization' => @env['HTTP_AUTHORIZATION']
|
||||
}.compact
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
{ 'objects' => all_objects }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,7 +48,7 @@ module Gitlab
|
|||
|
||||
# Check for Batch API
|
||||
if post_path[0].ends_with?("/info/lfs/objects/batch")
|
||||
lfs.render_lfs_api_auth
|
||||
lfs.render_batch_operation_response
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -66,7 +66,7 @@ describe Gitlab::Lfs::Router 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, "Accept" => "application/vnd.git-lfs+json; charset=utf-8")
|
||||
expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -107,7 +107,7 @@ describe Gitlab::Lfs::Router do
|
|||
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("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
|
||||
expect(json_response['_links']['download']['header']).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -117,7 +117,7 @@ describe Gitlab::Lfs::Router do
|
|||
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("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
|
||||
expect(json_response['_links']['download']['header']).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -191,7 +191,7 @@ describe Gitlab::Lfs::Router do
|
|||
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("Accept" => "application/vnd.git-lfs+json; charset=utf-8")
|
||||
expect(json_response['_links']['download']['header']).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -219,7 +219,7 @@ describe Gitlab::Lfs::Router do
|
|||
|
||||
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("Accept" => "application/vnd.git-lfs+json; charset=utf-8", "Authorization" => @auth)
|
||||
expect(json_response['_links']['download']['header']).to eq("Authorization" => @auth)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -250,7 +250,8 @@ describe Gitlab::Lfs::Router do
|
|||
body = { 'objects' => [{
|
||||
'oid' => sample_oid,
|
||||
'size' => sample_size
|
||||
}]
|
||||
}],
|
||||
'operation' => 'upload'
|
||||
}.to_json
|
||||
env['rack.input'] = StringIO.new(body)
|
||||
end
|
||||
|
@ -286,7 +287,8 @@ describe Gitlab::Lfs::Router do
|
|||
'objects' => [{
|
||||
'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
|
||||
'size' => 1575078
|
||||
}]
|
||||
}],
|
||||
'operation' => 'upload'
|
||||
}.to_json
|
||||
env['rack.input'] = StringIO.new(body)
|
||||
end
|
||||
|
@ -315,7 +317,8 @@ describe Gitlab::Lfs::Router do
|
|||
{ 'oid' => sample_oid,
|
||||
'size' => sample_size
|
||||
}
|
||||
]
|
||||
],
|
||||
'operation' => 'upload'
|
||||
}.to_json
|
||||
env['rack.input'] = StringIO.new(body)
|
||||
public_project.lfs_objects << lfs_object
|
||||
|
@ -351,6 +354,12 @@ describe Gitlab::Lfs::Router do
|
|||
end
|
||||
|
||||
context 'when user is not authenticated' do
|
||||
before do
|
||||
env['rack.input'] = StringIO.new(
|
||||
{ 'objects' => [], 'operation' => 'upload' }.to_json
|
||||
)
|
||||
end
|
||||
|
||||
context 'when user has push access' do
|
||||
before do
|
||||
project.team << [user, :master]
|
||||
|
|
Loading…
Reference in New Issue