Skip to content
Snippets Groups Projects
Commit f45cbc87 authored by Toon Claes's avatar Toon Claes
Browse files

Expose Group VisibilityLevel as String

Instead of exposing the VisibilityLevel as Integer, expose it as
String `visibility`.
parent b2c2dfe5
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -27,7 +27,7 @@ GET /groups
"name": "Foobar Group",
"path": "foo-bar",
"description": "An interesting group",
"visibility_level": 20,
"visibility": "public",
"lfs_enabled": true,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
Loading
Loading
@@ -72,9 +72,8 @@ Example response:
"description": "foo",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 10,
"visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
"http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
Loading
Loading
@@ -134,7 +133,7 @@ Example response:
"name": "Twitter",
"path": "twitter",
"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
"visibility_level": 20,
"visibility": "public",
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/twitter",
"request_access_enabled": false,
Loading
Loading
@@ -147,9 +146,8 @@ Example response:
"description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
"default_branch": "master",
"tag_list": [],
"public": true,
"archived": false,
"visibility_level": 20,
"visibility": "public",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
"http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git",
"web_url": "https://gitlab.example.com/twitter/typeahead-js",
Loading
Loading
@@ -186,9 +184,8 @@ Example response:
"description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 10,
"visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
"http_url_to_repo": "https://gitlab.example.com/twitter/flight.git",
"web_url": "https://gitlab.example.com/twitter/flight",
Loading
Loading
@@ -227,9 +224,8 @@ Example response:
"description": "Velit eveniet provident fugiat saepe eligendi autem.",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 0,
"visibility": "private",
"ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
"http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "https://gitlab.example.com/h5bp/html5-boilerplate",
Loading
Loading
@@ -288,7 +284,7 @@ Parameters:
- `name` (required) - The name of the group
- `path` (required) - The path of the group
- `description` (optional) - The group's description
- `visibility_level` (optional) - The group's visibility. 0 for private, 10 for internal, 20 for public.
- `visibility` (optional) - The group's visibility. Can be `private`, `internal`, or `public`.
- `lfs_enabled` (optional) - Enable/disable Large File Storage (LFS) for the projects in this group
- `request_access_enabled` (optional) - Allow users to request member access.
- `parent_id` (optional) - The parent group id for creating nested group.
Loading
Loading
@@ -320,7 +316,7 @@ PUT /groups/:id
| `name` | string | no | The name of the group |
| `path` | string | no | The path of the group |
| `description` | string | no | The description of the group |
| `visibility_level` | integer | no | The visibility level of the group. 0 for private, 10 for internal, 20 for public. |
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
 
Loading
Loading
@@ -337,7 +333,7 @@ Example response:
"name": "Experimental",
"path": "h5bp",
"description": "foo",
"visibility_level": 10,
"visibility": "internal",
"avatar_url": null,
"web_url": "http://gitlab.example.com/groups/h5bp",
"request_access_enabled": false,
Loading
Loading
@@ -352,7 +348,7 @@ Example response:
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 10,
"visibility": "internal",
"ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
"http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
"web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
Loading
Loading
Loading
Loading
@@ -132,7 +132,8 @@ module API
end
 
class Group < Grape::Entity
expose :id, :name, :path, :description, :visibility_level
expose :id, :name, :path, :description
expose(:visibility) { |group, _options| Gitlab::VisibilityLevel.string_level(group.visibility_level) }
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url
expose :web_url
Loading
Loading
Loading
Loading
@@ -7,7 +7,7 @@ module API
helpers do
params :optional_params do
optional :description, type: String, desc: 'The description of the group'
optional :visibility_level, type: Integer, desc: 'The visibility level of the group'
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the group'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
end
Loading
Loading
@@ -92,7 +92,7 @@ module API
optional :name, type: String, desc: 'The name of the group'
optional :path, type: String, desc: 'The path of the group'
use :optional_params
at_least_one_of :name, :path, :description, :visibility_level,
at_least_one_of :name, :path, :description, :visibility,
:lfs_enabled, :request_access_enabled
end
put ':id' do
Loading
Loading
@@ -126,7 +126,7 @@ module API
end
params do
optional :archived, type: Boolean, default: false, desc: 'Limit by archived status'
optional :visibility, type: String, values: %w[public internal private],
optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values,
desc: 'Limit by visibility'
optional :search, type: String, desc: 'Return list of authorized projects matching the search criteria'
optional :order_by, type: String, values: %w[id name path created_at updated_at last_activity_at],
Loading
Loading
Loading
Loading
@@ -125,6 +125,30 @@ module API
Gitlab::UrlBuilder.build(merge_request)
end
end
class Group < Grape::Entity
expose :id, :name, :path, :description, :visibility_level
expose :lfs_enabled?, as: :lfs_enabled
expose :avatar_url
expose :web_url
expose :request_access_enabled
expose :full_name, :full_path
expose :parent_id
expose :statistics, if: :statistics do
with_options format_with: -> (value) { value.to_i } do
expose :storage_size
expose :repository_size
expose :lfs_objects_size
expose :build_artifacts_size
end
end
end
class GroupDetail < Group
expose :projects, using: Entities::Project
expose :shared_projects, using: Entities::Project
end
end
end
end
Loading
Loading
@@ -6,13 +6,20 @@ module API
before { authenticate! }
 
helpers do
params :optional_params do
optional :description, type: String, desc: 'The description of the group'
optional :visibility_level, type: Integer, desc: 'The visibility level of the group'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
end
params :statistics_params do
optional :statistics, type: Boolean, default: false, desc: 'Include project statistics'
end
 
def present_groups(groups, options = {})
options = options.reverse_merge(
with: ::API::Entities::Group,
with: Entities::Group,
current_user: current_user,
)
 
Loading
Loading
@@ -22,8 +29,36 @@ module API
end
 
resource :groups do
desc 'Get a groups list' do
success Entities::Group
end
params do
use :statistics_params
optional :skip_groups, type: Array[Integer], desc: 'Array of group ids to exclude from list'
optional :all_available, type: Boolean, desc: 'Show all group that you have access to'
optional :search, type: String, desc: 'Search for a specific group'
optional :order_by, type: String, values: %w[name path], default: 'name', desc: 'Order by name or path'
optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
use :pagination
end
get do
groups = if current_user.admin
Group.all
elsif params[:all_available]
GroupsFinder.new.execute(current_user)
else
current_user.groups
end
groups = groups.search(params[:search]) if params[:search].present?
groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
groups = groups.reorder(params[:order_by] => params[:sort])
present_groups groups, statistics: params[:statistics] && current_user.is_admin?
end
desc 'Get list of owned groups for authenticated user' do
success ::API::Entities::Group
success Entities::Group
end
params do
use :pagination
Loading
Loading
@@ -32,6 +67,114 @@ module API
get '/owned' do
present_groups current_user.owned_groups, statistics: params[:statistics]
end
desc 'Create a group. Available only for users who can create groups.' do
success Entities::Group
end
params do
requires :name, type: String, desc: 'The name of the group'
requires :path, type: String, desc: 'The path of the group'
optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group'
use :optional_params
end
post do
authorize! :create_group
group = ::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute
if group.persisted?
present group, with: Entities::Group, current_user: current_user
else
render_api_error!("Failed to save group #{group.errors.messages}", 400)
end
end
end
params do
requires :id, type: String, desc: 'The ID of a group'
end
resource :groups do
desc 'Update a group. Available only for users who can administrate groups.' do
success Entities::Group
end
params do
optional :name, type: String, desc: 'The name of the group'
optional :path, type: String, desc: 'The path of the group'
use :optional_params
at_least_one_of :name, :path, :description, :visibility_level,
:lfs_enabled, :request_access_enabled
end
put ':id' do
group = find_group!(params[:id])
authorize! :admin_group, group
if ::Groups::UpdateService.new(group, current_user, declared_params(include_missing: false)).execute
present group, with: Entities::GroupDetail, current_user: current_user
else
render_validation_error!(group)
end
end
desc 'Get a single group, with containing projects.' do
success Entities::GroupDetail
end
get ":id" do
group = find_group!(params[:id])
present group, with: Entities::GroupDetail, current_user: current_user
end
desc 'Remove a group.'
delete ":id" do
group = find_group!(params[:id])
authorize! :admin_group, group
present ::Groups::DestroyService.new(group, current_user).execute, with: Entities::GroupDetail, current_user: current_user
end
desc 'Get a list of projects in this group.' do
success Entities::Project
end
params do
optional :archived, type: Boolean, default: false, desc: 'Limit by archived status'
optional :visibility, type: String, values: %w[public internal private],
desc: 'Limit by visibility'
optional :search, type: String, desc: 'Return list of authorized projects matching the search criteria'
optional :order_by, type: String, values: %w[id name path created_at updated_at last_activity_at],
default: 'created_at', desc: 'Return projects ordered by field'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return projects sorted in ascending and descending order'
optional :simple, type: Boolean, default: false,
desc: 'Return only the ID, URL, name, and path of each project'
optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
optional :starred, type: Boolean, default: false, desc: 'Limit by starred status'
use :pagination
end
get ":id/projects" do
group = find_group!(params[:id])
projects = GroupProjectsFinder.new(group).execute(current_user)
projects = filter_projects(projects)
entity = params[:simple] ? ::API::Entities::BasicProjectDetails : Entities::Project
present paginate(projects), with: entity, current_user: current_user
end
desc 'Transfer a project to the group namespace. Available only for admin.' do
success Entities::GroupDetail
end
params do
requires :project_id, type: String, desc: 'The ID or path of the project'
end
post ":id/projects/:project_id" do
authenticated_as_admin!
group = find_group!(params[:id])
project = find_project!(params[:project_id])
result = ::Projects::TransferService.new(project, current_user).execute(group)
if result
present group, with: Entities::GroupDetail, current_user: current_user
else
render_api_error!("Failed to transfer project #{project.errors.messages}", 400)
end
end
end
end
end
Loading
Loading
Loading
Loading
@@ -176,7 +176,7 @@ describe API::Groups, api: true do
expect(json_response['name']).to eq(group1.name)
expect(json_response['path']).to eq(group1.path)
expect(json_response['description']).to eq(group1.description)
expect(json_response['visibility_level']).to eq(group1.visibility_level)
expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
expect(json_response['avatar_url']).to eq(group1.avatar_url)
expect(json_response['web_url']).to eq(group1.web_url)
expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
Loading
Loading
@@ -295,7 +295,7 @@ describe API::Groups, api: true do
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
expect(json_response.first['visibility_level']).to be_present
expect(json_response.first['visibility']).to be_present
end
 
it "returns the group's projects with simple representation" do
Loading
Loading
@@ -306,7 +306,7 @@ describe API::Groups, api: true do
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
expect(json_response.first['visibility_level']).not_to be_present
expect(json_response.first['visibility']).not_to be_present
end
 
it 'filters the groups projects' do
Loading
Loading
Loading
Loading
@@ -4,14 +4,144 @@ describe API::V3::Groups, api: true do
include ApiHelpers
include UploadHelpers
 
let(:user1) { create(:user, can_create_group: false) }
let(:user2) { create(:user) }
let(:user3) { create(:user) }
let(:admin) { create(:admin) }
let!(:group1) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
let!(:group2) { create(:group, :private) }
let!(:project1) { create(:empty_project, namespace: group1) }
let!(:project2) { create(:empty_project, namespace: group2) }
let!(:project3) { create(:empty_project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
 
before do
group1.add_owner(user1)
group2.add_owner(user2)
end
 
describe "GET /groups" do
context "when unauthenticated" do
it "returns authentication error" do
get v3_api("/groups")
expect(response).to have_http_status(401)
end
end
context "when authenticated as user" do
it "normal user: returns an array of groups of user1" do
get v3_api("/groups", user1)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
expect(json_response)
.to satisfy_one { |group| group['name'] == group1.name }
end
it "does not include statistics" do
get v3_api("/groups", user1), statistics: true
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.first).not_to include 'statistics'
end
end
context "when authenticated as admin" do
it "admin: returns an array of all groups" do
get v3_api("/groups", admin)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.length).to eq(2)
end
it "does not include statistics by default" do
get v3_api("/groups", admin)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.first).not_to include('statistics')
end
it "includes statistics if requested" do
attributes = {
storage_size: 702,
repository_size: 123,
lfs_objects_size: 234,
build_artifacts_size: 345,
}.stringify_keys
project1.statistics.update!(attributes)
get v3_api("/groups", admin), statistics: true
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response)
.to satisfy_one { |group| group['statistics'] == attributes }
end
end
context "when using skip_groups in request" do
it "returns all groups excluding skipped groups" do
get v3_api("/groups", admin), skip_groups: [group2.id]
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
end
end
context "when using all_available in request" do
let(:response_groups) { json_response.map { |group| group['name'] } }
it "returns all groups you have access to" do
public_group = create :group, :public
get v3_api("/groups", user1), all_available: true
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(response_groups).to contain_exactly(public_group.name, group1.name)
end
end
context "when using sorting" do
let(:group3) { create(:group, name: "a#{group1.name}", path: "z#{group1.path}") }
let(:response_groups) { json_response.map { |group| group['name'] } }
before do
group3.add_owner(user1)
end
it "sorts by name ascending by default" do
get v3_api("/groups", user1)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(response_groups).to eq([group3.name, group1.name])
end
it "sorts in descending order when passed" do
get v3_api("/groups", user1), sort: "desc"
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(response_groups).to eq([group1.name, group3.name])
end
it "sorts by the order_by param" do
get v3_api("/groups", user1), order_by: "path"
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(response_groups).to eq([group1.name, group3.name])
end
end
end
describe 'GET /groups/owned' do
context 'when unauthenticated' do
it 'returns authentication error' do
Loading
Loading
@@ -32,4 +162,404 @@ describe API::V3::Groups, api: true do
end
end
end
describe "GET /groups/:id" do
context "when authenticated as user" do
it "returns one of user1's groups" do
project = create(:empty_project, namespace: group2, path: 'Foo')
create(:project_group_link, project: project, group: group1)
get v3_api("/groups/#{group1.id}", user1)
expect(response).to have_http_status(200)
expect(json_response['id']).to eq(group1.id)
expect(json_response['name']).to eq(group1.name)
expect(json_response['path']).to eq(group1.path)
expect(json_response['description']).to eq(group1.description)
expect(json_response['visibility_level']).to eq(group1.visibility_level)
expect(json_response['avatar_url']).to eq(group1.avatar_url)
expect(json_response['web_url']).to eq(group1.web_url)
expect(json_response['request_access_enabled']).to eq(group1.request_access_enabled)
expect(json_response['full_name']).to eq(group1.full_name)
expect(json_response['full_path']).to eq(group1.full_path)
expect(json_response['parent_id']).to eq(group1.parent_id)
expect(json_response['projects']).to be_an Array
expect(json_response['projects'].length).to eq(2)
expect(json_response['shared_projects']).to be_an Array
expect(json_response['shared_projects'].length).to eq(1)
expect(json_response['shared_projects'][0]['id']).to eq(project.id)
end
it "does not return a non existing group" do
get v3_api("/groups/1328", user1)
expect(response).to have_http_status(404)
end
it "does not return a group not attached to user1" do
get v3_api("/groups/#{group2.id}", user1)
expect(response).to have_http_status(404)
end
end
context "when authenticated as admin" do
it "returns any existing group" do
get v3_api("/groups/#{group2.id}", admin)
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(group2.name)
end
it "does not return a non existing group" do
get v3_api("/groups/1328", admin)
expect(response).to have_http_status(404)
end
end
context 'when using group path in URL' do
it 'returns any existing group' do
get v3_api("/groups/#{group1.path}", admin)
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(group1.name)
end
it 'does not return a non existing group' do
get v3_api('/groups/unknown', admin)
expect(response).to have_http_status(404)
end
it 'does not return a group not attached to user1' do
get v3_api("/groups/#{group2.path}", user1)
expect(response).to have_http_status(404)
end
end
end
describe 'PUT /groups/:id' do
let(:new_group_name) { 'New Group'}
context 'when authenticated as the group owner' do
it 'updates the group' do
put v3_api("/groups/#{group1.id}", user1), name: new_group_name, request_access_enabled: true
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(new_group_name)
expect(json_response['request_access_enabled']).to eq(true)
end
it 'returns 404 for a non existing group' do
put v3_api('/groups/1328', user1), name: new_group_name
expect(response).to have_http_status(404)
end
end
context 'when authenticated as the admin' do
it 'updates the group' do
put v3_api("/groups/#{group1.id}", admin), name: new_group_name
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(new_group_name)
end
end
context 'when authenticated as an user that can see the group' do
it 'does not updates the group' do
put v3_api("/groups/#{group1.id}", user2), name: new_group_name
expect(response).to have_http_status(403)
end
end
context 'when authenticated as an user that cannot see the group' do
it 'returns 404 when trying to update the group' do
put v3_api("/groups/#{group2.id}", user1), name: new_group_name
expect(response).to have_http_status(404)
end
end
end
describe "GET /groups/:id/projects" do
context "when authenticated as user" do
it "returns the group's projects" do
get v3_api("/groups/#{group1.id}/projects", user1)
expect(response).to have_http_status(200)
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
expect(json_response.first['visibility_level']).to be_present
end
it "returns the group's projects with simple representation" do
get v3_api("/groups/#{group1.id}/projects", user1), simple: true
expect(response).to have_http_status(200)
expect(json_response.length).to eq(2)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
expect(json_response.first['visibility_level']).not_to be_present
end
it 'filters the groups projects' do
public_project = create(:empty_project, :public, path: 'test1', group: group1)
get v3_api("/groups/#{group1.id}/projects", user1), visibility: 'public'
expect(response).to have_http_status(200)
expect(json_response).to be_an(Array)
expect(json_response.length).to eq(1)
expect(json_response.first['name']).to eq(public_project.name)
end
it "does not return a non existing group" do
get v3_api("/groups/1328/projects", user1)
expect(response).to have_http_status(404)
end
it "does not return a group not attached to user1" do
get v3_api("/groups/#{group2.id}/projects", user1)
expect(response).to have_http_status(404)
end
it "only returns projects to which user has access" do
project3.team << [user3, :developer]
get v3_api("/groups/#{group1.id}/projects", user3)
expect(response).to have_http_status(200)
expect(json_response.length).to eq(1)
expect(json_response.first['name']).to eq(project3.name)
end
it 'only returns the projects owned by user' do
project2.group.add_owner(user3)
get v3_api("/groups/#{project2.group.id}/projects", user3), owned: true
expect(response).to have_http_status(200)
expect(json_response.length).to eq(1)
expect(json_response.first['name']).to eq(project2.name)
end
it 'only returns the projects starred by user' do
user1.starred_projects = [project1]
get v3_api("/groups/#{group1.id}/projects", user1), starred: true
expect(response).to have_http_status(200)
expect(json_response.length).to eq(1)
expect(json_response.first['name']).to eq(project1.name)
end
end
context "when authenticated as admin" do
it "returns any existing group" do
get v3_api("/groups/#{group2.id}/projects", admin)
expect(response).to have_http_status(200)
expect(json_response.length).to eq(1)
expect(json_response.first['name']).to eq(project2.name)
end
it "does not return a non existing group" do
get v3_api("/groups/1328/projects", admin)
expect(response).to have_http_status(404)
end
end
context 'when using group path in URL' do
it 'returns any existing group' do
get v3_api("/groups/#{group1.path}/projects", admin)
expect(response).to have_http_status(200)
project_names = json_response.map { |proj| proj['name'] }
expect(project_names).to match_array([project1.name, project3.name])
end
it 'does not return a non existing group' do
get v3_api('/groups/unknown/projects', admin)
expect(response).to have_http_status(404)
end
it 'does not return a group not attached to user1' do
get v3_api("/groups/#{group2.path}/projects", user1)
expect(response).to have_http_status(404)
end
end
end
describe "POST /groups" do
context "when authenticated as user without group permissions" do
it "does not create group" do
post v3_api("/groups", user1), attributes_for(:group)
expect(response).to have_http_status(403)
end
end
context "when authenticated as user with group permissions" do
it "creates group" do
group = attributes_for(:group, { request_access_enabled: false })
post v3_api("/groups", user3), group
expect(response).to have_http_status(201)
expect(json_response["name"]).to eq(group[:name])
expect(json_response["path"]).to eq(group[:path])
expect(json_response["request_access_enabled"]).to eq(group[:request_access_enabled])
end
it "creates a nested group" do
parent = create(:group)
parent.add_owner(user3)
group = attributes_for(:group, { parent_id: parent.id })
post v3_api("/groups", user3), group
expect(response).to have_http_status(201)
expect(json_response["full_path"]).to eq("#{parent.path}/#{group[:path]}")
expect(json_response["parent_id"]).to eq(parent.id)
end
it "does not create group, duplicate" do
post v3_api("/groups", user3), { name: 'Duplicate Test', path: group2.path }
expect(response).to have_http_status(400)
expect(response.message).to eq("Bad Request")
end
it "returns 400 bad request error if name not given" do
post v3_api("/groups", user3), { path: group2.path }
expect(response).to have_http_status(400)
end
it "returns 400 bad request error if path not given" do
post v3_api("/groups", user3), { name: 'test' }
expect(response).to have_http_status(400)
end
end
end
describe "DELETE /groups/:id" do
context "when authenticated as user" do
it "removes group" do
delete v3_api("/groups/#{group1.id}", user1)
expect(response).to have_http_status(200)
end
it "does not remove a group if not an owner" do
user4 = create(:user)
group1.add_master(user4)
delete v3_api("/groups/#{group1.id}", user3)
expect(response).to have_http_status(403)
end
it "does not remove a non existing group" do
delete v3_api("/groups/1328", user1)
expect(response).to have_http_status(404)
end
it "does not remove a group not attached to user1" do
delete v3_api("/groups/#{group2.id}", user1)
expect(response).to have_http_status(404)
end
end
context "when authenticated as admin" do
it "removes any existing group" do
delete v3_api("/groups/#{group2.id}", admin)
expect(response).to have_http_status(200)
end
it "does not remove a non existing group" do
delete v3_api("/groups/1328", admin)
expect(response).to have_http_status(404)
end
end
end
describe "POST /groups/:id/projects/:project_id" do
let(:project) { create(:empty_project) }
let(:project_path) { "#{project.namespace.path}%2F#{project.path}" }
before(:each) do
allow_any_instance_of(Projects::TransferService).
to receive(:execute).and_return(true)
end
context "when authenticated as user" do
it "does not transfer project to group" do
post v3_api("/groups/#{group1.id}/projects/#{project.id}", user2)
expect(response).to have_http_status(403)
end
end
context "when authenticated as admin" do
it "transfers project to group" do
post v3_api("/groups/#{group1.id}/projects/#{project.id}", admin)
expect(response).to have_http_status(201)
end
context 'when using project path in URL' do
context 'with a valid project path' do
it "transfers project to group" do
post v3_api("/groups/#{group1.id}/projects/#{project_path}", admin)
expect(response).to have_http_status(201)
end
end
context 'with a non-existent project path' do
it "does not transfer project to group" do
post v3_api("/groups/#{group1.id}/projects/nogroup%2Fnoproject", admin)
expect(response).to have_http_status(404)
end
end
end
context 'when using a group path in URL' do
context 'with a valid group path' do
it "transfers project to group" do
post v3_api("/groups/#{group1.path}/projects/#{project_path}", admin)
expect(response).to have_http_status(201)
end
end
context 'with a non-existent group path' do
it "does not transfer project to group" do
post v3_api("/groups/noexist/projects/#{project_path}", admin)
expect(response).to have_http_status(404)
end
end
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment