Commit e27ebba5 authored by Sean McGivern's avatar Sean McGivern

Merge branch '4269-public-repositories-and-files-api-ee' into 'master'

[EE] Allow unauthenticated access to Repositories & Repository Files API GET endpoints

See merge request !985
parents 1333a40a f0b933ec
---
title: Allow public access to some Project API endpoints
title: Allow unauthenticated access to some Project API GET endpoints
merge_request: 7843
author:
---
title: Allow unauthenticated access to Repositories Files API GET endpoints
merge_request:
author:
---
title: Allow unauthenticated access to Repositories API GET endpoints
merge_request: 8148
author:
......@@ -2,7 +2,8 @@
## List repository tree
Get a list of repository files and directories in a project.
Get a list of repository files and directories in a project. This endpoint can
be accessed without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/tree
......@@ -71,7 +72,8 @@ Parameters:
## Raw file content
Get the raw file contents for a file by commit SHA and path.
Get the raw file contents for a file by commit SHA and path. This endpoint can
be accessed without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/blobs/:sha
......@@ -85,7 +87,8 @@ Parameters:
## Raw blob content
Get the raw file contents for a blob by blob SHA.
Get the raw file contents for a blob by blob SHA. This endpoint can be accessed
without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/raw_blobs/:sha
......@@ -98,7 +101,8 @@ Parameters:
## Get file archive
Get an archive of the repository
Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/archive
......@@ -111,6 +115,9 @@ Parameters:
## Compare branches, tags or commits
This endpoint can be accessed without authentication if the repository is
publicly accessible.
```
GET /projects/:id/repository/compare
```
......@@ -163,7 +170,8 @@ Response:
## Contributors
Get repository contributors list
Get repository contributors list. This endpoint can be accessed without
authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/contributors
......
......@@ -6,7 +6,9 @@
## Get file from repository
Allows you to receive information about file in repository like name, size, content. Note that file content is Base64 encoded.
Allows you to receive information about file in repository like name, size,
content. Note that file content is Base64 encoded. This endpoint can be accessed
without authentication if the repository is publicly accessible.
```
GET /projects/:id/repository/files
......
module API
# Projects API
class Files < Grape::API
before { authenticate! }
helpers do
def commit_params(attrs)
{
......
......@@ -2,7 +2,6 @@ require 'mime/types'
module API
class Repositories < Grape::API
before { authenticate! }
before { authorize! :download_code, user_project }
params do
......@@ -79,8 +78,6 @@ module API
optional :format, type: String, desc: 'The archive format'
end
get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do
authorize! :download_code, user_project
begin
send_git_archive user_project.repository, ref: params[:sha], format: params[:format]
rescue
......@@ -96,7 +93,6 @@ module API
requires :to, type: String, desc: 'The commit, branch name, or tag name to stop comparison'
end
get ':id/repository/compare' do
authorize! :download_code, user_project
compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to])
present compare, with: Entities::Compare
end
......@@ -105,8 +101,6 @@ module API
success Entities::Contributor
end
get ':id/repository/contributors' do
authorize! :download_code, user_project
begin
present user_project.repository.contributors,
with: Entities::Contributor
......
......@@ -4,7 +4,14 @@ describe API::Files, api: true do
include ApiHelpers
let(:user) { create(:user) }
let!(:project) { create(:project, namespace: user.namespace ) }
let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
let(:file_path) { 'files/ruby/popen.rb' }
let(:params) do
{
file_path: file_path,
ref: 'master'
}
end
let(:author_email) { FFaker::Internet.email }
# I have to remove periods from the end of the name
......@@ -24,36 +31,72 @@ describe API::Files, api: true do
before { project.team << [user, :developer] }
describe "GET /projects/:id/repository/files" do
it "returns file info" do
params = {
file_path: file_path,
ref: 'master',
}
let(:route) { "/projects/#{project.id}/repository/files" }
get api("/projects/#{project.id}/repository/files", user), params
shared_examples_for 'repository files' do
it "returns file info" do
get api(route, current_user), params
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
expect(json_response['file_name']).to eq('popen.rb')
expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
end
expect(response).to have_http_status(200)
expect(json_response['file_path']).to eq(file_path)
expect(json_response['file_name']).to eq('popen.rb')
expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
end
it "returns a 400 bad request if no params given" do
get api("/projects/#{project.id}/repository/files", user)
context 'when no params are given' do
it_behaves_like '400 response' do
let(:request) { get api(route, current_user) }
end
end
expect(response).to have_http_status(400)
context 'when file_path does not exist' do
let(:params) do
{
file_path: 'app/models/application.rb',
ref: 'master',
}
end
it_behaves_like '404 response' do
let(:request) { get api(route, current_user), params }
let(:message) { '404 File Not Found' }
end
end
context 'when repository is disabled' do
include_context 'disabled repository'
it_behaves_like '403 response' do
let(:request) { get api(route, current_user), params }
end
end
end
it "returns a 404 if such file does not exist" do
params = {
file_path: 'app/models/application.rb',
ref: 'master',
}
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository files' do
let(:project) { create(:project, :public) }
let(:current_user) { nil }
end
end
get api("/projects/#{project.id}/repository/files", user), params
context 'when unauthenticated', 'and project is private' do
it_behaves_like '404 response' do
let(:request) { get api(route), params }
let(:message) { '404 Project Not Found' }
end
end
context 'when authenticated', 'as a developer' do
it_behaves_like 'repository files' do
let(:current_user) { user }
end
end
expect(response).to have_http_status(404)
context 'when authenticated', 'as a guest' do
it_behaves_like '403 response' do
let(:request) { get api(route, guest), params }
end
end
end
......
This diff is collapsed.
shared_context 'disabled repository' do
before do
project.project_feature.update_attributes!(
repository_access_level: ProjectFeature::DISABLED,
merge_requests_access_level: ProjectFeature::DISABLED,
builds_access_level: ProjectFeature::DISABLED
)
expect(project.feature_available?(:repository, current_user)).to be false
end
end
# Specs for status checking.
#
# Requires an API request:
# let(:request) { get api("/projects/#{project.id}/repository/branches", user) }
shared_examples_for '400 response' do
before do
# Fires the request
request
end
it 'returns 400' do
expect(response).to have_http_status(400)
end
end
shared_examples_for '403 response' do
before do
# Fires the request
request
end
it 'returns 403' do
expect(response).to have_http_status(403)
end
end
shared_examples_for '404 response' do
let(:message) { nil }
before do
# Fires the request
request
end
it 'returns 404' do
expect(response).to have_http_status(404)
expect(json_response).to be_an Object
if message.present?
expect(json_response['message']).to eq(message)
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