Expose Snippet VisibilityLevel as String
This commit is contained in:
parent
ed8f13c745
commit
209856166e
|
|
@ -5,15 +5,15 @@
|
|||
### Snippet visibility level
|
||||
|
||||
Snippets in GitLab can be either private, internal, or public.
|
||||
You can set it with the `visibility_level` field in the snippet.
|
||||
You can set it with the `visibility` field in the snippet.
|
||||
|
||||
Constants for snippet visibility levels are:
|
||||
|
||||
| Visibility | Visibility level | Description |
|
||||
| ---------- | ---------------- | ----------- |
|
||||
| Private | `0` | The snippet is visible only to the snippet creator |
|
||||
| Internal | `10` | The snippet is visible for any logged in user |
|
||||
| Public | `20` | The snippet can be accessed without any authentication |
|
||||
| Visibility | Description |
|
||||
| ---------- | ----------- |
|
||||
| `private` | The snippet is visible only to the snippet creator |
|
||||
| `internal` | The snippet is visible for any logged in user |
|
||||
| `public` | The snippet can be accessed without any authentication |
|
||||
|
||||
## List snippets
|
||||
|
||||
|
|
@ -78,11 +78,11 @@ Parameters:
|
|||
| `title` | String | yes | The title of a snippet |
|
||||
| `file_name` | String | yes | The name of a snippet file |
|
||||
| `content` | String | yes | The content of a snippet |
|
||||
| `visibility_level` | Integer | yes | The snippet's visibility |
|
||||
| `visibility` | String | yes | The snippet's visibility |
|
||||
|
||||
|
||||
``` bash
|
||||
curl --request POST --data '{"title": "This is a snippet", "content": "Hello world", "file_name": "test.txt", "visibility_level": 10 }' --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets
|
||||
curl --request POST --data '{"title": "This is a snippet", "content": "Hello world", "file_name": "test.txt", "visibility": "internal" }' --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
|
@ -123,7 +123,7 @@ Parameters:
|
|||
| `title` | String | no | The title of a snippet |
|
||||
| `file_name` | String | no | The name of a snippet file |
|
||||
| `content` | String | no | The content of a snippet |
|
||||
| `visibility_level` | Integer | no | The snippet's visibility |
|
||||
| `visibility` | String | no | The snippet's visibility |
|
||||
|
||||
|
||||
``` bash
|
||||
|
|
@ -154,7 +154,7 @@ Example response:
|
|||
|
||||
## Delete snippet
|
||||
|
||||
Deletes an existing snippet.
|
||||
Deletes an existing snippet.
|
||||
|
||||
```
|
||||
DELETE /snippets/:id
|
||||
|
|
@ -229,4 +229,3 @@ Example response:
|
|||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ module API
|
|||
mount ::API::V3::Repositories
|
||||
mount ::API::V3::Runners
|
||||
mount ::API::V3::Services
|
||||
mount ::API::V3::Snippets
|
||||
mount ::API::V3::Subscriptions
|
||||
mount ::API::V3::SystemHooks
|
||||
mount ::API::V3::Tags
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ module API
|
|||
requires :title, type: String, desc: 'The title of a snippet'
|
||||
requires :file_name, type: String, desc: 'The name of a snippet file'
|
||||
requires :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
default: Gitlab::VisibilityLevel::INTERNAL,
|
||||
desc: 'The visibility level of the snippet'
|
||||
optional :visibility, type: String,
|
||||
values: Gitlab::VisibilityLevel.string_values,
|
||||
default: 'internal',
|
||||
desc: 'The visibility of the snippet'
|
||||
end
|
||||
post do
|
||||
attrs = declared_params(include_missing: false).merge(request: request, api: true)
|
||||
attrs = map_visibility_level(declared_params(include_missing: false)).merge(request: request, api: true)
|
||||
snippet = CreateSnippetService.new(nil, current_user, attrs).execute
|
||||
|
||||
render_spam_error! if snippet.spam?
|
||||
|
|
@ -85,17 +85,17 @@ module API
|
|||
optional :title, type: String, desc: 'The title of a snippet'
|
||||
optional :file_name, type: String, desc: 'The name of a snippet file'
|
||||
optional :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
desc: 'The visibility level of the snippet'
|
||||
at_least_one_of :title, :file_name, :content, :visibility_level
|
||||
optional :visibility, type: String,
|
||||
values: Gitlab::VisibilityLevel.string_values,
|
||||
desc: 'The visibility of the snippet'
|
||||
at_least_one_of :title, :file_name, :content, :visibility
|
||||
end
|
||||
put ':id' do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
authorize! :update_personal_snippet, snippet
|
||||
|
||||
attrs = declared_params(include_missing: false).merge(request: request, api: true)
|
||||
attrs = map_visibility_level(declared_params(include_missing: false).merge(request: request, api: true))
|
||||
|
||||
UpdateSnippetService.new(nil, current_user, snippet, attrs).execute
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
module API
|
||||
module V3
|
||||
class Snippets < Grape::API
|
||||
include PaginationParams
|
||||
|
||||
before { authenticate! }
|
||||
|
||||
resource :snippets do
|
||||
helpers do
|
||||
def snippets_for_current_user
|
||||
SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user)
|
||||
end
|
||||
|
||||
def public_snippets
|
||||
SnippetsFinder.new.execute(current_user, filter: :public)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Get a snippets list for authenticated user' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
use :pagination
|
||||
end
|
||||
get do
|
||||
present paginate(snippets_for_current_user), with: ::API::Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'List all public snippets current_user has access to' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
use :pagination
|
||||
end
|
||||
get 'public' do
|
||||
present paginate(public_snippets), with: ::API::Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'Get a single snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
get ':id' do
|
||||
snippet = snippets_for_current_user.find(params[:id])
|
||||
present snippet, with: ::API::Entities::PersonalSnippet
|
||||
end
|
||||
|
||||
desc 'Create new snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :title, type: String, desc: 'The title of a snippet'
|
||||
requires :file_name, type: String, desc: 'The name of a snippet file'
|
||||
requires :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
default: Gitlab::VisibilityLevel::INTERNAL,
|
||||
desc: 'The visibility level of the snippet'
|
||||
end
|
||||
post do
|
||||
attrs = declared_params(include_missing: false).merge(request: request, api: true)
|
||||
snippet = CreateSnippetService.new(nil, current_user, attrs).execute
|
||||
|
||||
if snippet.persisted?
|
||||
present snippet, with: ::API::Entities::PersonalSnippet
|
||||
else
|
||||
render_validation_error!(snippet)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Update an existing snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
optional :title, type: String, desc: 'The title of a snippet'
|
||||
optional :file_name, type: String, desc: 'The name of a snippet file'
|
||||
optional :content, type: String, desc: 'The content of a snippet'
|
||||
optional :visibility_level, type: Integer,
|
||||
values: Gitlab::VisibilityLevel.values,
|
||||
desc: 'The visibility level of the snippet'
|
||||
at_least_one_of :title, :file_name, :content, :visibility_level
|
||||
end
|
||||
put ':id' do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
authorize! :update_personal_snippet, snippet
|
||||
|
||||
attrs = declared_params(include_missing: false)
|
||||
|
||||
UpdateSnippetService.new(nil, current_user, snippet, attrs).execute
|
||||
if snippet.persisted?
|
||||
present snippet, with: ::API::Entities::PersonalSnippet
|
||||
else
|
||||
render_validation_error!(snippet)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Remove snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
success ::API::Entities::PersonalSnippet
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
delete ':id' do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
authorize! :destroy_personal_snippet, snippet
|
||||
snippet.destroy
|
||||
no_content!
|
||||
end
|
||||
|
||||
desc 'Get a raw snippet' do
|
||||
detail 'This feature was introduced in GitLab 8.15.'
|
||||
end
|
||||
params do
|
||||
requires :id, type: Integer, desc: 'The ID of a snippet'
|
||||
end
|
||||
get ":id/raw" do
|
||||
snippet = snippets_for_current_user.find_by(id: params.delete(:id))
|
||||
return not_found!('Snippet') unless snippet
|
||||
|
||||
env['api.format'] = :txt
|
||||
content_type 'text/plain'
|
||||
present snippet.content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -87,7 +87,7 @@ describe API::Snippets, api: true do
|
|||
title: 'Test Title',
|
||||
file_name: 'test.rb',
|
||||
content: 'puts "hello world"',
|
||||
visibility_level: Snippet::PUBLIC
|
||||
visibility: 'public'
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -120,14 +120,14 @@ describe API::Snippets, api: true do
|
|||
|
||||
context 'when the snippet is private' do
|
||||
it 'creates the snippet' do
|
||||
expect { create_snippet(visibility_level: Snippet::PRIVATE) }.
|
||||
expect { create_snippet(visibility: 'private') }.
|
||||
to change { Snippet.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the snippet is public' do
|
||||
it 'rejects the shippet' do
|
||||
expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
|
||||
expect { create_snippet(visibility: 'public') }.
|
||||
not_to change { Snippet.count }
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
|
|
@ -135,7 +135,7 @@ describe API::Snippets, api: true do
|
|||
end
|
||||
|
||||
it 'creates a spam log' do
|
||||
expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
|
||||
expect { create_snippet(visibility: 'public') }.
|
||||
to change { SpamLog.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
|
@ -218,12 +218,12 @@ describe API::Snippets, api: true do
|
|||
let(:visibility_level) { Snippet::PRIVATE }
|
||||
|
||||
it 'rejects the snippet' do
|
||||
expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
|
||||
expect { update_snippet(title: 'Foo', visibility: 'public') }.
|
||||
not_to change { snippet.reload.title }
|
||||
end
|
||||
|
||||
it 'creates a spam log' do
|
||||
expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }.
|
||||
expect { update_snippet(title: 'Foo', visibility: 'public') }.
|
||||
to change { SpamLog.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe API::V3::Snippets, api: true do
|
||||
include ApiHelpers
|
||||
let!(:user) { create(:user) }
|
||||
|
||||
describe 'GET /snippets/' do
|
||||
it 'returns snippets available' do
|
||||
public_snippet = create(:personal_snippet, :public, author: user)
|
||||
private_snippet = create(:personal_snippet, :private, author: user)
|
||||
internal_snippet = create(:personal_snippet, :internal, author: user)
|
||||
|
||||
get v3_api("/snippets/", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
internal_snippet.id,
|
||||
private_snippet.id)
|
||||
expect(json_response.last).to have_key('web_url')
|
||||
expect(json_response.last).to have_key('raw_url')
|
||||
end
|
||||
|
||||
it 'hides private snippets from regular user' do
|
||||
create(:personal_snippet, :private)
|
||||
|
||||
get v3_api("/snippets/", user)
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/public' do
|
||||
let!(:other_user) { create(:user) }
|
||||
let!(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
let!(:private_snippet) { create(:personal_snippet, :private, author: user) }
|
||||
let!(:internal_snippet) { create(:personal_snippet, :internal, author: user) }
|
||||
let!(:public_snippet_other) { create(:personal_snippet, :public, author: other_user) }
|
||||
let!(:private_snippet_other) { create(:personal_snippet, :private, author: other_user) }
|
||||
let!(:internal_snippet_other) { create(:personal_snippet, :internal, author: other_user) }
|
||||
|
||||
it 'returns all snippets with public visibility from all users' do
|
||||
get v3_api("/snippets/public", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
public_snippet_other.id)
|
||||
expect(json_response.map{ |snippet| snippet['web_url']} ).to include(
|
||||
"http://localhost/snippets/#{public_snippet.id}",
|
||||
"http://localhost/snippets/#{public_snippet_other.id}")
|
||||
expect(json_response.map{ |snippet| snippet['raw_url']} ).to include(
|
||||
"http://localhost/snippets/#{public_snippet.id}/raw",
|
||||
"http://localhost/snippets/#{public_snippet_other.id}/raw")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /snippets/:id/raw' do
|
||||
let(:snippet) { create(:personal_snippet, author: user) }
|
||||
|
||||
it 'returns raw text' do
|
||||
get v3_api("/snippets/#{snippet.id}/raw", user)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type).to eq 'text/plain'
|
||||
expect(response.body).to eq(snippet.content)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
delete v3_api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /snippets/' do
|
||||
let(:params) do
|
||||
{
|
||||
title: 'Test Title',
|
||||
file_name: 'test.rb',
|
||||
content: 'puts "hello world"',
|
||||
visibility_level: Snippet::PUBLIC
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a new snippet' do
|
||||
expect do
|
||||
post v3_api("/snippets/", user), params
|
||||
end.to change { PersonalSnippet.count }.by(1)
|
||||
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['title']).to eq(params[:title])
|
||||
expect(json_response['file_name']).to eq(params[:file_name])
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
params.delete(:title)
|
||||
|
||||
post v3_api("/snippets/", user), params
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
|
||||
context 'when the snippet is spam' do
|
||||
def create_snippet(snippet_params = {})
|
||||
post v3_api('/snippets', user), params.merge(snippet_params)
|
||||
end
|
||||
|
||||
before do
|
||||
allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
|
||||
end
|
||||
|
||||
context 'when the snippet is private' do
|
||||
it 'creates the snippet' do
|
||||
expect { create_snippet(visibility_level: Snippet::PRIVATE) }.
|
||||
to change { Snippet.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the snippet is public' do
|
||||
it 'rejects the shippet' do
|
||||
expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
|
||||
not_to change { Snippet.count }
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
|
||||
it 'creates a spam log' do
|
||||
expect { create_snippet(visibility_level: Snippet::PUBLIC) }.
|
||||
to change { SpamLog.count }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /snippets/:id' do
|
||||
let(:other_user) { create(:user) }
|
||||
let(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
it 'updates snippet' do
|
||||
new_content = 'New content'
|
||||
|
||||
put v3_api("/snippets/#{public_snippet.id}", user), content: new_content
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
public_snippet.reload
|
||||
expect(public_snippet.content).to eq(new_content)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
put v3_api("/snippets/1234", user), title: 'foo'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
it "returns 404 for another user's snippet" do
|
||||
put v3_api("/snippets/#{public_snippet.id}", other_user), title: 'fubar'
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
|
||||
it 'returns 400 for missing parameters' do
|
||||
put v3_api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(400)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /snippets/:id' do
|
||||
let!(:public_snippet) { create(:personal_snippet, :public, author: user) }
|
||||
it 'deletes snippet' do
|
||||
expect do
|
||||
delete v3_api("/snippets/#{public_snippet.id}", user)
|
||||
|
||||
expect(response).to have_http_status(204)
|
||||
end.to change { PersonalSnippet.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'returns 404 for invalid snippet id' do
|
||||
delete v3_api("/snippets/1234", user)
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
expect(json_response['message']).to eq('404 Snippet Not Found')
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue