Commit 6bc22d95 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Add test coverage to LFS fetching

parent 2f545a15
module Gitlab module Gitlab
module Lfs module Lfs
class Router class Router
attr_reader :project, :user, :ci, :request
def initialize(project, user, ci, request) def initialize(project, user, ci, request)
@project = project @project = project
@user = user @user = user
......
...@@ -83,6 +83,7 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -83,6 +83,7 @@ describe Gitlab::Lfs::Router, lib: true do
context 'with required headers' do context 'with required headers' do
before do before do
project.lfs_objects << lfs_object
env['HTTP_X_SENDFILE_TYPE'] = "X-Sendfile" env['HTTP_X_SENDFILE_TYPE'] = "X-Sendfile"
end end
...@@ -94,7 +95,6 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -94,7 +95,6 @@ describe Gitlab::Lfs::Router, lib: true do
context 'when user has project access' do context 'when user has project access' do
before do before do
project.lfs_objects << lfs_object
project.team << [user, :master] project.team << [user, :master]
end end
...@@ -148,143 +148,145 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -148,143 +148,145 @@ describe Gitlab::Lfs::Router, lib: true do
end end
describe 'download' do describe 'download' do
describe 'when user is authenticated' do before do
before do body = { 'operation' => 'download',
body = { 'operation' => 'download', 'objects' => [
'objects' => [ { 'oid' => sample_oid,
{ 'oid' => sample_oid, 'size' => sample_size
'size' => sample_size }]
}] }.to_json
}.to_json env['rack.input'] = StringIO.new(body)
env['rack.input'] = StringIO.new(body) end
end
describe 'when user has download access' do shared_examples 'an authorized requests' do
context 'when downloading an lfs object that is assigned to our project' do
before do before do
@auth = authorize(user) project.lfs_objects << lfs_object
env["HTTP_AUTHORIZATION"] = @auth
project.team << [user, :reporter]
end end
context 'when downloading an lfs object that is assigned to our project' do it 'responds with status 200 and href to download' do
before do response = router.try_call
project.lfs_objects << lfs_object expect(response.first).to eq(200)
end response_body = ActiveSupport::JSON.decode(response.last.first)
it 'responds with status 200 and href to download' do
response = lfs_router_auth.try_call
expect(response.first).to eq(200)
response_body = ActiveSupport::JSON.decode(response.last.first)
expect(response_body).to eq('objects' => [ expect(response_body).to eq('objects' => [
{ 'oid' => sample_oid, { 'oid' => sample_oid,
'size' => sample_size, 'size' => sample_size,
'actions' => { 'actions' => {
'download' => { 'download' => {
'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}",
'header' => { 'Authorization' => @auth } 'header' => { 'Authorization' => auth }
}
} }
}]) }
end }])
end end
end
context 'when downloading an lfs object that is assigned to other project' do context 'when downloading an lfs object that is assigned to other project' do
before do before do
public_project.lfs_objects << lfs_object public_project.lfs_objects << lfs_object
end end
it 'responds with status 200 and error message' do it 'responds with status 200 and error message' do
response = lfs_router_auth.try_call response = router.try_call
expect(response.first).to eq(200) expect(response.first).to eq(200)
response_body = ActiveSupport::JSON.decode(response.last.first) response_body = ActiveSupport::JSON.decode(response.last.first)
expect(response_body).to eq('objects' => [ expect(response_body).to eq('objects' => [
{ 'oid' => sample_oid, { 'oid' => sample_oid,
'size' => sample_size, 'size' => sample_size,
'error' => { 'error' => {
'code' => 404, 'code' => 404,
'message' => "Object does not exist on the server or you don't have permissions to access it", 'message' => "Object does not exist on the server or you don't have permissions to access it",
} }
}]) }])
end
end end
end
context 'when downloading a lfs object that does not exist' do context 'when downloading a lfs object that does not exist' do
before do before do
body = { 'operation' => 'download', body = { 'operation' => 'download',
'objects' => [ 'objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078 'size' => 1575078
}] }]
}.to_json }.to_json
env['rack.input'] = StringIO.new(body) env['rack.input'] = StringIO.new(body)
end end
it "responds with status 200 and error message" do it "responds with status 200 and error message" do
response = lfs_router_auth.try_call response = router.try_call
expect(response.first).to eq(200) expect(response.first).to eq(200)
response_body = ActiveSupport::JSON.decode(response.last.first) response_body = ActiveSupport::JSON.decode(response.last.first)
expect(response_body).to eq('objects' => [ expect(response_body).to eq('objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078, 'size' => 1575078,
'error' => { 'error' => {
'code' => 404, 'code' => 404,
'message' => "Object does not exist on the server or you don't have permissions to access it", 'message' => "Object does not exist on the server or you don't have permissions to access it",
} }
}]) }])
end
end end
end
context 'when downloading one new and one existing lfs object' do context 'when downloading one new and one existing lfs object' do
before do before do
body = { 'operation' => 'download', body = { 'operation' => 'download',
'objects' => [ 'objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078 'size' => 1575078
}, },
{ 'oid' => sample_oid, { 'oid' => sample_oid,
'size' => sample_size 'size' => sample_size
} }
] ]
}.to_json }.to_json
env['rack.input'] = StringIO.new(body) env['rack.input'] = StringIO.new(body)
project.lfs_objects << lfs_object project.lfs_objects << lfs_object
end end
it "responds with status 200 with upload hypermedia link for the new object" do it "responds with status 200 with upload hypermedia link for the new object" do
response = lfs_router_auth.try_call response = router.try_call
expect(response.first).to eq(200) expect(response.first).to eq(200)
response_body = ActiveSupport::JSON.decode(response.last.first) response_body = ActiveSupport::JSON.decode(response.last.first)
expect(response_body).to eq('objects' => [ expect(response_body).to eq('objects' => [
{ 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897', { 'oid' => '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897',
'size' => 1575078, 'size' => 1575078,
'error' => { 'error' => {
'code' => 404, 'code' => 404,
'message' => "Object does not exist on the server or you don't have permissions to access it", 'message' => "Object does not exist on the server or you don't have permissions to access it",
} }
}, },
{ 'oid' => sample_oid, { 'oid' => sample_oid,
'size' => sample_size, 'size' => sample_size,
'actions' => { 'actions' => {
'download' => { 'download' => {
'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}", 'href' => "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}",
'header' => { 'Authorization' => @auth } 'header' => { 'Authorization' => auth }
}
} }
}]) }
end }])
end end
end end
end
context 'when user is authenticated' do
let(:auth) { authorize(user) }
before do
env["HTTP_AUTHORIZATION"] = auth
project.team << [user, role]
end
it_behaves_like 'an authorized requests' do
let(:role) { :reporter }
let(:router) { lfs_router_auth }
end
context 'when user does is not member of the project' do context 'when user does is not member of the project' do
before do let(:role) { :guest }
@auth = authorize(user)
env["HTTP_AUTHORIZATION"] = @auth
project.team << [user, :guest]
end
it 'responds with 403' do it 'responds with 403' do
expect(lfs_router_auth.try_call.first).to eq(403) expect(lfs_router_auth.try_call.first).to eq(403)
...@@ -292,11 +294,7 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -292,11 +294,7 @@ describe Gitlab::Lfs::Router, lib: true do
end end
context 'when user does not have download access' do context 'when user does not have download access' do
before do let(:role) { :guest }
@auth = authorize(user)
env["HTTP_AUTHORIZATION"] = @auth
project.team << [user, :guest]
end
it 'responds with 403' do it 'responds with 403' do
expect(lfs_router_auth.try_call.first).to eq(403) expect(lfs_router_auth.try_call.first).to eq(403)
...@@ -304,18 +302,19 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -304,18 +302,19 @@ describe Gitlab::Lfs::Router, lib: true do
end end
end end
context 'when user is not authenticated' do context 'when CI is authorized' do
let(:auth) { 'gitlab-ci-token:password' }
before do before do
body = { 'operation' => 'download', env["HTTP_AUTHORIZATION"] = auth
'objects' => [ end
{ 'oid' => sample_oid,
'size' => sample_size
}],
}.to_json it_behaves_like 'an authorized requests' do
env['rack.input'] = StringIO.new(body) let(:router) { lfs_router_ci_auth }
end end
end
context 'when user is not authenticated' do
describe 'is accessing public project' do describe 'is accessing public project' do
before do before do
public_project.lfs_objects << lfs_object public_project.lfs_objects << lfs_object
...@@ -352,17 +351,17 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -352,17 +351,17 @@ describe Gitlab::Lfs::Router, lib: true do
end end
describe 'upload' do describe 'upload' do
describe 'when user is authenticated' do before do
before do body = { 'operation' => 'upload',
body = { 'operation' => 'upload', 'objects' => [
'objects' => [ { 'oid' => sample_oid,
{ 'oid' => sample_oid, 'size' => sample_size
'size' => sample_size }]
}] }.to_json
}.to_json env['rack.input'] = StringIO.new(body)
env['rack.input'] = StringIO.new(body) end
end
describe 'when request is authenticated' do
describe 'when user has project push access' do describe 'when user has project push access' do
before do before do
@auth = authorize(user) @auth = authorize(user)
...@@ -454,15 +453,15 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -454,15 +453,15 @@ describe Gitlab::Lfs::Router, lib: true do
expect(lfs_router_auth.try_call.first).to eq(403) expect(lfs_router_auth.try_call.first).to eq(403)
end end
end end
end
context 'when user is not authenticated' do context 'when CI is authorized' do
before do it 'responds with 401' do
env['rack.input'] = StringIO.new( expect(lfs_router_ci_auth.try_call.first).to eq(401)
{ 'objects' => [], 'operation' => 'upload' }.to_json end
)
end end
end
context 'when user is not authenticated' do
context 'when user has push access' do context 'when user has push access' do
before do before do
project.team << [user, :master] project.team << [user, :master]
...@@ -479,6 +478,18 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -479,6 +478,18 @@ describe Gitlab::Lfs::Router, lib: true do
end end
end end
end end
context 'when CI is authorized' do
let(:auth) { 'gitlab-ci-token:password' }
before do
env["HTTP_AUTHORIZATION"] = auth
end
it "responds with status 403" do
expect(lfs_router_public_ci_auth.try_call.first).to eq(401)
end
end
end end
describe 'unsupported' do describe 'unsupported' do
...@@ -504,13 +515,68 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -504,13 +515,68 @@ describe Gitlab::Lfs::Router, lib: true do
env['REQUEST_METHOD'] = 'PUT' env['REQUEST_METHOD'] = 'PUT'
end end
describe 'to one project' do shared_examples 'unauthorized' do
describe 'when user has push access to the project' do context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(router.project)
end
it 'responds with status 401' do
expect(router.try_call.first).to eq(401)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do
before do
headers_for_upload_finalize(router.project)
end
it 'responds with status 401' do
expect(router.try_call.first).to eq(401)
end
end
context 'and request is sent with a malformed headers' do
before do before do
project.team << [user, :master] env["PATH_INFO"] = "#{router.project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}"
env["HTTP_X_GITLAB_LFS_TMP"] = "cat /etc/passwd"
end end
describe 'when user is authenticated' do it 'does not recognize it as a valid lfs command' do
expect(router.try_call).to eq(nil)
end
end
end
shared_examples 'forbidden' do
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(router.project)
end
it 'responds with 403' do
expect(router.try_call.first).to eq(403)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do
before do
headers_for_upload_finalize(router.project)
end
it 'responds with 403' do
expect(router.try_call.first).to eq(403)
end
end
end
describe 'to one project' do
describe 'when user is authenticated' do
describe 'when user has push access to the project' do
before do
project.team << [user, :developer]
end
context 'and request is sent by gitlab-workhorse to authorize the request' do context 'and request is sent by gitlab-workhorse to authorize the request' do
before do before do
header_for_upload_authorize(project) header_for_upload_authorize(project)
...@@ -538,100 +604,35 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -538,100 +604,35 @@ describe Gitlab::Lfs::Router, lib: true do
end end
end end
describe 'when user is unauthenticated' do describe 'and user does not have push access' do
let(:lfs_router_noauth) { new_lfs_router(project) } let(:router) { lfs_router_auth }
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(project)
end
it 'responds with status 401' do
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do
before do
headers_for_upload_finalize(project)
end
it 'responds with status 401' do
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
context 'and request is sent with a malformed headers' do it_behaves_like 'forbidden'
before do
env["PATH_INFO"] = "#{project.repository.path_with_namespace}.git/gitlab-lfs/objects/#{sample_oid}/#{sample_size}"
env["HTTP_X_GITLAB_LFS_TMP"] = "cat /etc/passwd"
end
it 'does not recognize it as a valid lfs command' do
expect(lfs_router_noauth.try_call).to eq(nil)
end
end
end end
end end
describe 'and user does not have push access' do context 'when CI is authenticated' do
describe 'when user is authenticated' do let(:router) { lfs_router_ci_auth }
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(project)
end
it 'responds with 403' do
expect(lfs_router_auth.try_call.first).to eq(403)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do it_behaves_like 'unauthorized'
before do end
headers_for_upload_finalize(project)
end
it 'responds with 403' do
expect(lfs_router_auth.try_call.first).to eq(403)
end
end
end
describe 'when user is unauthenticated' do
let(:lfs_router_noauth) { new_lfs_router(project) }
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(project)
end
it 'responds with 401' do
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do context 'for unauthenticated' do
before do let(:router) { new_lfs_router(project) }
headers_for_upload_finalize(project)
end
it 'responds with 401' do it_behaves_like 'unauthorized'
expect(lfs_router_noauth.try_call.first).to eq(401)
end
end
end
end end
end end
describe "to a forked project" do describe 'to a forked project' do
let(:forked_project) { fork_project(public_project, user) } let(:forked_project) { fork_project(public_project, user) }
describe 'when user has push access to the project' do describe 'when user is authenticated' do
before do describe 'when user has push access to the project' do
forked_project.team << [user_two, :master] before do
end forked_project.team << [user_two, :developer]
end
describe 'when user is authenticated' do
context 'and request is sent by gitlab-workhorse to authorize the request' do context 'and request is sent by gitlab-workhorse to authorize the request' do
before do before do
header_for_upload_authorize(forked_project) header_for_upload_authorize(forked_project)
...@@ -659,73 +660,23 @@ describe Gitlab::Lfs::Router, lib: true do ...@@ -659,73 +660,23 @@ describe Gitlab::Lfs::Router, lib: true do
end end
end end
describe 'when user is unauthenticated' do describe 'and user does not have push access' do
context 'and request is sent by gitlab-workhorse to authorize the request' do let(:router) { lfs_router_forked_auth }
before do
header_for_upload_authorize(forked_project)
end
it 'responds with status 401' do
expect(lfs_router_forked_noauth.try_call.first).to eq(401)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do
before do
headers_for_upload_finalize(forked_project)
end
it 'responds with status 401' do it_behaves_like 'forbidden'
expect(lfs_router_forked_noauth.try_call.first).to eq(401)
end
end
end end
end end
describe 'and user does not have push access' do context 'when CI is authenticated' do
describe 'when user is authenticated' do let(:router) { lfs_router_forked_ci_auth }
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
header_for_upload_authorize(forked_project)
end
it 'responds with 403' do
expect(lfs_router_forked_auth.try_call.first).to eq(403)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do
before do
headers_for_upload_finalize(forked_project)
end
it 'responds with 403' do
expect(lfs_router_forked_auth.try_call.first).to eq(403)
end
end
end
describe 'when user is unauthenticated' do it_behaves_like 'unauthorized'
context 'and request is sent by gitlab-workhorse to authorize the request' do end
before do
header_for_upload_authorize(forked_project)
end
it 'responds with 401' do
expect(lfs_router_forked_noauth.try_call.first).to eq(401)
end
end
context 'and request is sent by gitlab-workhorse to finalize the upload' do context 'for unauthenticated' do
before do let(:router) { lfs_router_forked_noauth }
headers_for_upload_finalize(forked_project)
end
it 'responds with 401' do it_behaves_like 'unauthorized'
expect(lfs_router_forked_noauth.try_call.first).to eq(401)
end
end
end
end end
describe 'and second project not related to fork or a source project' do describe 'and second project not related to fork or a source project' do
......
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