Commit a95c85ad authored by Steve Abrams's avatar Steve Abrams

Add event tracking to Maven API

Add snowplow event tracking to Maven API
to track push and pull of packages
parent d6e31b67
...@@ -27,7 +27,7 @@ module API ...@@ -27,7 +27,7 @@ module API
if %w(md5 sha1).include?(format) if %w(md5 sha1).include?(format)
[name, format] [name, format]
else else
[file_name, nil] [file_name, format]
end end
end end
...@@ -46,6 +46,10 @@ module API ...@@ -46,6 +46,10 @@ module API
project_path = path.rpartition('/').first project_path = path.rpartition('/').first
Project.find_by_full_path(project_path) Project.find_by_full_path(project_path)
end end
def jar_file?(format)
format == 'jar'
end
end end
desc 'Download the maven package file at instance level' do desc 'Download the maven package file at instance level' do
...@@ -79,7 +83,9 @@ module API ...@@ -79,7 +83,9 @@ module API
package_file.file_md5 package_file.file_md5
when 'sha1' when 'sha1'
package_file.file_sha1 package_file.file_sha1
when nil else
track_event('pull_package') if jar_file?(format)
present_carrierwave_file!(package_file.file) present_carrierwave_file!(package_file.file)
end end
end end
...@@ -117,7 +123,9 @@ module API ...@@ -117,7 +123,9 @@ module API
package_file.file_md5 package_file.file_md5
when 'sha1' when 'sha1'
package_file.file_sha1 package_file.file_sha1
when nil else
track_event('pull_package') if jar_file?(format)
present_carrierwave_file!(package_file.file) present_carrierwave_file!(package_file.file)
end end
end end
...@@ -155,12 +163,14 @@ module API ...@@ -155,12 +163,14 @@ module API
package_file.file_md5 package_file.file_md5
when 'sha1' when 'sha1'
package_file.file_sha1 package_file.file_sha1
when nil else
track_event('pull_package') if jar_file?(format)
present_carrierwave_file!(package_file.file) present_carrierwave_file!(package_file.file)
end end
end end
desc 'Upload the maven package file' do desc 'Workhorse authorize the maven package file upload' do
detail 'This feature was introduced in GitLab 11.3' detail 'This feature was introduced in GitLab 11.3'
end end
params do params do
...@@ -215,7 +225,11 @@ module API ...@@ -215,7 +225,11 @@ module API
.new(package, file_name).execute! .new(package, file_name).execute!
verify_package_file(package_file, uploaded_file) verify_package_file(package_file, uploaded_file)
when nil when 'md5'
nil
else
track_event('push_package') if jar_file?(format)
file_params = { file_params = {
file: uploaded_file, file: uploaded_file,
size: params['file.size'], size: params['file.size'],
......
...@@ -5,6 +5,10 @@ describe API::MavenPackages do ...@@ -5,6 +5,10 @@ describe API::MavenPackages do
let(:group) { create(:group) } let(:group) { create(:group) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :public, namespace: group) } let(:project) { create(:project, :public, namespace: group) }
let(:package) { create(:maven_package, project: project) }
let(:maven_metadatum) { package.maven_metadatum }
let(:package_file) { package.package_files.where('file_name like ?', '%.xml').first }
let(:jar_file) { package.package_files.where('file_name like ?', '%.jar').first }
let(:personal_access_token) { create(:personal_access_token, user: user) } let(:personal_access_token) { create(:personal_access_token, user: user) }
let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') } let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } } let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } }
...@@ -17,25 +21,35 @@ describe API::MavenPackages do ...@@ -17,25 +21,35 @@ describe API::MavenPackages do
stub_licensed_features(packages: true) stub_licensed_features(packages: true)
end end
shared_examples 'tracking the file download event' do
context 'with jar file' do
let(:package_file) { jar_file }
it_behaves_like 'a gitlab tracking event', described_class.name, 'pull_package'
end
end
describe 'GET /api/v4/packages/maven/*path/:file_name' do describe 'GET /api/v4/packages/maven/*path/:file_name' do
let(:package) { create(:maven_package, project: project, name: project.full_path) } let(:package) { create(:maven_package, project: project, name: project.full_path) }
let(:maven_metadatum) { package.maven_metadatum }
let(:package_file_xml) { package.package_files.find_by(file_type: 'xml') }
context 'a public project' do context 'a public project' do
subject { download_file(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file_xml.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.content_type.to_s).to eq('text/plain')
expect(response.body).to eq(package_file_xml.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -45,21 +59,25 @@ describe API::MavenPackages do ...@@ -45,21 +59,25 @@ describe API::MavenPackages do
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end end
subject { download_file_with_token(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
end end
it 'denies download when no private token' do it 'denies download when no private token' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'allows download with job token' do it 'allows download with job token' do
download_file(package_file_xml.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -67,12 +85,16 @@ describe API::MavenPackages do ...@@ -67,12 +85,16 @@ describe API::MavenPackages do
end end
context 'private project' do context 'private project' do
subject { download_file_with_token(package_file.file_name) }
before do before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end end
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -81,19 +103,19 @@ describe API::MavenPackages do ...@@ -81,19 +103,19 @@ describe API::MavenPackages do
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
project.add_guest(user) project.add_guest(user)
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'denies download when no private token' do it 'denies download when no private token' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'allows download with job token' do it 'allows download with job token' do
download_file(package_file_xml.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -103,7 +125,7 @@ describe API::MavenPackages do ...@@ -103,7 +125,7 @@ describe API::MavenPackages do
it 'rejects request if feature is not in the license' do it 'rejects request if feature is not in the license' do
stub_licensed_features(packages: false) stub_licensed_features(packages: false)
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
...@@ -112,7 +134,7 @@ describe API::MavenPackages do ...@@ -112,7 +134,7 @@ describe API::MavenPackages do
let(:package) { create(:maven_package, project: project) } let(:package) { create(:maven_package, project: project) }
it 'rejects request' do it 'rejects request' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
...@@ -128,29 +150,29 @@ describe API::MavenPackages do ...@@ -128,29 +150,29 @@ describe API::MavenPackages do
end end
describe 'GET /api/v4/groups/:id/-/packages/maven/*path/:file_name' do describe 'GET /api/v4/groups/:id/-/packages/maven/*path/:file_name' do
let(:package) { create(:maven_package, project: project) }
let(:maven_metadatum) { package.maven_metadatum }
let(:package_file_xml) { package.package_files.find_by(file_type: 'xml') }
before do before do
project.team.truncate project.team.truncate
group.add_developer(user) group.add_developer(user)
end end
context 'a public project' do context 'a public project' do
subject { download_file(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file_xml.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.content_type.to_s).to eq('text/plain')
expect(response.body).to eq(package_file_xml.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -160,21 +182,25 @@ describe API::MavenPackages do ...@@ -160,21 +182,25 @@ describe API::MavenPackages do
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL) project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end end
subject { download_file_with_token(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
end end
it 'denies download when no private token' do it 'denies download when no private token' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(404)
end end
it 'allows download with job token' do it 'allows download with job token' do
download_file(package_file_xml.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -186,8 +212,12 @@ describe API::MavenPackages do ...@@ -186,8 +212,12 @@ describe API::MavenPackages do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end end
subject { download_file_with_token(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -196,19 +226,19 @@ describe API::MavenPackages do ...@@ -196,19 +226,19 @@ describe API::MavenPackages do
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
group.add_guest(user) group.add_guest(user)
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'denies download when no private token' do it 'denies download when no private token' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(404)
end end
it 'allows download with job token' do it 'allows download with job token' do
download_file(package_file_xml.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -218,7 +248,7 @@ describe API::MavenPackages do ...@@ -218,7 +248,7 @@ describe API::MavenPackages do
it 'rejects request if feature is not in the license' do it 'rejects request if feature is not in the license' do
stub_licensed_features(packages: false) stub_licensed_features(packages: false)
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
...@@ -233,24 +263,24 @@ describe API::MavenPackages do ...@@ -233,24 +263,24 @@ describe API::MavenPackages do
end end
describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do describe 'GET /api/v4/projects/:id/packages/maven/*path/:file_name' do
let(:package) { create(:maven_package, project: project) }
let(:maven_metadatum) { package.maven_metadatum }
let(:package_file_xml) { package.package_files.find_by(file_type: 'xml') }
context 'a public project' do context 'a public project' do
subject { download_file(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file_xml.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.content_type.to_s).to eq('text/plain')
expect(response.body).to eq(package_file_xml.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -259,8 +289,12 @@ describe API::MavenPackages do ...@@ -259,8 +289,12 @@ describe API::MavenPackages do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end end
subject { download_file_with_token(package_file.file_name) }
it_behaves_like 'tracking the file download event'
it 'returns the file' do it 'returns the file' do
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -269,19 +303,19 @@ describe API::MavenPackages do ...@@ -269,19 +303,19 @@ describe API::MavenPackages do
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
project.add_guest(user) project.add_guest(user)
download_file_with_token(package_file_xml.file_name) subject
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
it 'denies download when no private token' do it 'denies download when no private token' do
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(404) expect(response).to have_gitlab_http_status(404)
end end
it 'allows download with job token' do it 'allows download with job token' do
download_file(package_file_xml.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.content_type.to_s).to eq('application/octet-stream')
...@@ -291,7 +325,7 @@ describe API::MavenPackages do ...@@ -291,7 +325,7 @@ describe API::MavenPackages do
it 'rejects request if feature is not in the license' do it 'rejects request if feature is not in the license' do
stub_licensed_features(packages: false) stub_licensed_features(packages: false)
download_file(package_file_xml.file_name) download_file(package_file.file_name)
expect(response).to have_gitlab_http_status(403) expect(response).to have_gitlab_http_status(403)
end end
...@@ -361,7 +395,7 @@ describe API::MavenPackages do ...@@ -361,7 +395,7 @@ describe API::MavenPackages do
end end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name' do describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name' do
let(:file_upload) { fixture_file_upload('ee/spec/fixtures/maven/maven-metadata.xml') } let(:file_upload) { fixture_file_upload('ee/spec/fixtures/maven/my-app-1.0-20180724.124855-1.jar') }
before do before do
# by configuring this path we allow to pass temp file from any path # by configuring this path we allow to pass temp file from any path
...@@ -404,6 +438,14 @@ describe API::MavenPackages do ...@@ -404,6 +438,14 @@ describe API::MavenPackages do
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
context 'event tracking' do
let(:package_file) { jar_file }
subject { upload_file_with_token(params) }
it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package'
end
it 'creates package and stores package file' do it 'creates package and stores package file' do
expect { upload_file_with_token(params) }.to change { project.packages.count }.by(1) expect { upload_file_with_token(params) }.to change { project.packages.count }.by(1)
.and change { Packages::MavenMetadatum.count }.by(1) .and change { Packages::MavenMetadatum.count }.by(1)
...@@ -433,7 +475,7 @@ describe API::MavenPackages do ...@@ -433,7 +475,7 @@ describe API::MavenPackages do
end end
def upload_file(params = {}, request_headers = headers) def upload_file(params = {}, request_headers = headers)
put api("/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/maven-metadata.xml"), params: params, headers: request_headers put api("/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/my-app-1.0-20180724.124855-1.jar"), params: params, headers: request_headers
end end
def upload_file_with_token(params = {}, request_headers = headers_with_token) def upload_file_with_token(params = {}, request_headers = headers_with_token)
......
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