2019-12-26 22:10:19 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec . describe API :: Groups do
2019-12-21 20:55:43 +05:30
include GroupAPIHelpers
2017-08-17 22:00:37 +05:30
include UploadHelpers
2014-09-02 18:07:02 +05:30
2020-05-24 23:13:21 +05:30
let_it_be ( :user1 ) { create ( :user , can_create_group : false ) }
let_it_be ( :user2 ) { create ( :user ) }
let_it_be ( :user3 ) { create ( :user ) }
let_it_be ( :admin ) { create ( :admin ) }
2021-10-27 15:23:28 +05:30
let_it_be ( :group1 ) { create ( :group , path : 'some_path' , avatar : File . open ( uploaded_image_temp_path ) ) }
2020-05-24 23:13:21 +05:30
let_it_be ( :group2 ) { create ( :group , :private ) }
let_it_be ( :project1 ) { create ( :project , namespace : group1 ) }
let_it_be ( :project2 ) { create ( :project , namespace : group2 ) }
let_it_be ( :project3 ) { create ( :project , namespace : group1 , path : 'test' , visibility_level : Gitlab :: VisibilityLevel :: PRIVATE ) }
2020-07-28 23:09:34 +05:30
let_it_be ( :archived_project ) { create ( :project , namespace : group1 , archived : true ) }
2014-09-02 18:07:02 +05:30
2021-09-30 23:02:18 +05:30
before_all do
2014-09-02 18:07:02 +05:30
group1 . add_owner ( user1 )
group2 . add_owner ( user2 )
end
2020-04-08 14:13:33 +05:30
shared_examples 'group avatar upload' do
context 'when valid' do
let ( :file_path ) { 'spec/fixtures/banana_sample.gif' }
it 'returns avatar url in response' do
make_upload_request
group_id = json_response [ 'id' ]
expect ( json_response [ 'avatar_url' ] ) . to eq ( 'http://localhost/uploads/' \
'-/system/group/avatar/' \
" #{ group_id } /banana_sample.gif " )
end
end
context 'when invalid' do
shared_examples 'invalid file upload request' do
it 'returns 400' do
make_upload_request
expect ( response ) . to have_gitlab_http_status ( :bad_request )
expect ( response . message ) . to eq ( 'Bad Request' )
expect ( json_response [ 'message' ] . to_s ) . to match ( / #{ message } / )
end
end
context 'when file format is not supported' do
let ( :file_path ) { 'spec/fixtures/doc_sample.txt' }
let ( :message ) { 'file format is not supported. Please try one of the following supported formats: image/png, image/jpeg, image/gif, image/bmp, image/tiff, image/vnd.microsoft.icon' }
it_behaves_like 'invalid file upload request'
end
2021-03-11 19:13:27 +05:30
context 'when file is too large' do
2020-04-08 14:13:33 +05:30
let ( :file_path ) { 'spec/fixtures/big-image.png' }
let ( :message ) { 'is too big' }
it_behaves_like 'invalid file upload request'
end
end
end
2021-10-27 15:23:28 +05:30
shared_examples 'skips searching in full path' do
it 'does not find groups by full path' do
subgroup = create ( :group , parent : parent , path : " #{ parent . path } -subgroup " )
create ( :group , parent : parent , path : 'not_matching_path' )
get endpoint , params : { search : parent . path }
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( subgroup . id )
end
end
2014-09-02 18:07:02 +05:30
describe " GET /groups " do
context " when unauthenticated " do
2018-03-17 18:26:18 +05:30
it " returns public groups " do
2014-09-02 18:07:02 +05:30
get api ( " /groups " )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
2020-04-22 19:07:51 +05:30
expect ( json_response . first [ 'created_at' ] ) . to be_present
2018-03-17 18:26:18 +05:30
expect ( json_response )
. to satisfy_one { | group | group [ 'name' ] == group1 . name }
end
it 'avoids N+1 queries' do
# Establish baseline
get api ( " /groups " , admin )
control = ActiveRecord :: QueryRecorder . new do
get api ( " /groups " , admin )
end
create ( :group )
expect do
get api ( " /groups " , admin )
end . not_to exceed_query_limit ( control )
2014-09-02 18:07:02 +05:30
end
2020-05-24 23:13:21 +05:30
context 'when statistics are requested' do
it 'does not include statistics' do
get api ( " /groups " ) , params : { statistics : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include 'statistics'
end
end
2014-09-02 18:07:02 +05:30
end
context " when authenticated as user " do
2016-09-13 17:45:13 +05:30
it " normal user: returns an array of groups of user1 " do
2014-09-02 18:07:02 +05:30
get api ( " /groups " , user1 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2015-04-26 12:48:37 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
2017-08-17 22:00:37 +05:30
expect ( json_response )
. to satisfy_one { | group | group [ 'name' ] == group1 . name }
end
2019-12-04 20:38:33 +05:30
it " does not include runners_token information " do
get api ( " /groups " , user1 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first ) . not_to include ( 'runners_token' )
end
2017-08-17 22:00:37 +05:30
it " does not include statistics " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { statistics : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include 'statistics'
2014-09-02 18:07:02 +05:30
end
2020-04-22 19:07:51 +05:30
it " includes a created_at timestamp " do
get api ( " /groups " , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first [ 'created_at' ] ) . to be_present
end
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
context " when authenticated as admin " do
2016-09-13 17:45:13 +05:30
it " admin: returns an array of all groups " do
2014-09-02 18:07:02 +05:30
get api ( " /groups " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2015-04-26 12:48:37 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
2019-12-04 20:38:33 +05:30
it " does not include runners_token information " do
get api ( " /groups " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
expect ( json_response . first ) . not_to include ( 'runners_token' )
end
2017-08-17 22:00:37 +05:30
it " does not include statistics by default " do
get api ( " /groups " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include ( 'statistics' )
end
2020-04-22 19:07:51 +05:30
it " includes a created_at timestamp " do
get api ( " /groups " , admin )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first [ 'created_at' ] ) . to be_present
end
2017-08-17 22:00:37 +05:30
it " includes statistics if requested " do
attributes = {
2020-07-28 23:09:34 +05:30
storage_size : 2392 ,
2017-08-17 22:00:37 +05:30
repository_size : 123 ,
2019-09-04 21:01:54 +05:30
wiki_size : 456 ,
2017-08-17 22:00:37 +05:30
lfs_objects_size : 234 ,
2020-07-28 23:09:34 +05:30
build_artifacts_size : 345 ,
snippets_size : 1234
2017-08-17 22:00:37 +05:30
} . stringify_keys
exposed_attributes = attributes . dup
exposed_attributes [ 'job_artifacts_size' ] = exposed_attributes . delete ( 'build_artifacts_size' )
project1 . statistics . update! ( attributes )
2019-02-15 15:39:39 +05:30
get api ( " /groups " , admin ) , params : { statistics : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response )
. to satisfy_one { | group | group [ 'statistics' ] == exposed_attributes }
end
2014-09-02 18:07:02 +05:30
end
2016-11-03 12:29:30 +05:30
context " when using skip_groups in request " do
it " returns all groups excluding skipped groups " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , admin ) , params : { skip_groups : [ group2 . id ] }
2016-11-03 12:29:30 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2016-11-03 12:29:30 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
end
end
2017-08-17 22:00:37 +05:30
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
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { all_available : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups ) . to contain_exactly ( public_group . name , group1 . name )
end
end
2020-06-23 00:09:42 +05:30
context " when using top_level_only " do
let ( :top_level_group ) { create ( :group , name : 'top-level-group' ) }
let ( :subgroup ) { create ( :group , :nested , name : 'subgroup' ) }
let ( :response_groups ) { json_response . map { | group | group [ 'name' ] } }
before do
top_level_group . add_owner ( user1 )
subgroup . add_owner ( user1 )
end
it " doesn't return subgroups " do
get api ( " /groups " , user1 ) , params : { top_level_only : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups ) . to include ( top_level_group . name )
expect ( response_groups ) . not_to include ( subgroup . name )
end
end
2017-08-17 22:00:37 +05:30
context " when using sorting " do
2021-09-30 23:02:18 +05:30
let_it_be ( :group3 ) { create ( :group , name : " a #{ group1 . name } " , path : " z #{ group1 . path } " ) }
let_it_be ( :group4 ) { create ( :group , name : " same-name " , path : " y #{ group1 . path } " ) }
let_it_be ( :group5 ) { create ( :group , name : " same-name " ) }
2017-08-17 22:00:37 +05:30
let ( :response_groups ) { json_response . map { | group | group [ 'name' ] } }
2018-11-08 19:23:39 +05:30
let ( :response_groups_ids ) { json_response . map { | group | group [ 'id' ] } }
2017-08-17 22:00:37 +05:30
2021-09-30 23:02:18 +05:30
before_all do
2017-08-17 22:00:37 +05:30
group3 . add_owner ( user1 )
2018-11-08 19:23:39 +05:30
group4 . add_owner ( user1 )
group5 . add_owner ( user1 )
2017-08-17 22:00:37 +05:30
end
it " sorts by name ascending by default " do
get api ( " /groups " , user1 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
2018-11-08 19:23:39 +05:30
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( :name ) . pluck ( :name ) )
2017-08-17 22:00:37 +05:30
end
it " sorts in descending order when passed " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { sort : " desc " }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
2018-11-08 19:23:39 +05:30
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( name : :desc ) . pluck ( :name ) )
2017-08-17 22:00:37 +05:30
end
2018-11-08 19:23:39 +05:30
it " sorts by path in order_by param " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { order_by : " path " }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
2018-11-08 19:23:39 +05:30
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( :path ) . pluck ( :name ) )
end
it " sorts by id in the order_by param " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { order_by : " id " }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-08 19:23:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( :id ) . pluck ( :name ) )
end
it " sorts also by descending id with pagination fix " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { order_by : " id " , sort : " desc " }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-08 19:23:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( id : :desc ) . pluck ( :name ) )
end
it " sorts identical keys by id for good pagination " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { search : " same-name " , order_by : " name " }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-08 19:23:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups_ids ) . to eq ( Group . select { | group | group [ 'name' ] == 'same-name' } . map { | group | group [ 'id' ] } . sort )
end
it " sorts descending identical keys by id for good pagination " do
2019-02-15 15:39:39 +05:30
get api ( " /groups " , user1 ) , params : { search : " same-name " , order_by : " name " , sort : " desc " }
2018-11-08 19:23:39 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-08 19:23:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( response_groups_ids ) . to eq ( Group . select { | group | group [ 'name' ] == 'same-name' } . map { | group | group [ 'id' ] } . sort )
end
2021-09-30 23:02:18 +05:30
context 'when searching with similarity ordering' , :aggregate_failures do
let_it_be ( :group6 ) { create ( :group , name : 'same-name subgroup' , parent : group4 ) }
let_it_be ( :group7 ) { create ( :group , name : 'same-name parent' ) }
let ( :params ) { { order_by : 'similarity' , search : 'same-name' } }
before_all do
group6 . add_owner ( user1 )
group7 . add_owner ( user1 )
end
subject { get api ( '/groups' , user1 ) , params : params }
it 'sorts top level groups before subgroups with exact matches first' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 4 )
expect ( response_groups ) . to eq ( [ 'same-name' , 'same-name parent' , 'same-name subgroup' , 'same-name' ] )
end
context 'when `search` parameter is not given' do
let ( :params ) { { order_by : 'similarity' } }
it 'sorts items ordered by name' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 6 )
expect ( response_groups ) . to eq ( groups_visible_to_user ( user1 ) . order ( :name ) . pluck ( :name ) )
end
end
end
2018-11-08 19:23:39 +05:30
def groups_visible_to_user ( user )
Group . where ( id : user . authorized_groups . select ( :id ) . reorder ( nil ) )
2017-08-17 22:00:37 +05:30
end
end
context 'when using owned in the request' do
it 'returns an array of groups the user owns' do
2018-11-18 11:00:15 +05:30
group1 . add_maintainer ( user2 )
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
get api ( '/groups' , user2 ) , params : { owned : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
2018-03-17 18:26:18 +05:30
expect ( json_response . length ) . to eq ( 1 )
2017-08-17 22:00:37 +05:30
expect ( json_response . first [ 'name' ] ) . to eq ( group2 . name )
end
end
2018-11-18 11:00:15 +05:30
context 'when using min_access_level in the request' do
let! ( :group3 ) { create ( :group , :private ) }
let ( :response_groups ) { json_response . map { | group | group [ 'id' ] } }
before do
group1 . add_developer ( user2 )
2020-04-22 19:07:51 +05:30
group3 . add_maintainer ( user2 )
2018-11-18 11:00:15 +05:30
end
it 'returns an array of groups the user has at least master access' do
2019-02-15 15:39:39 +05:30
get api ( '/groups' , user2 ) , params : { min_access_level : 40 }
2018-11-18 11:00:15 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-18 11:00:15 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
2020-05-24 23:13:21 +05:30
expect ( response_groups ) . to contain_exactly ( group2 . id , group3 . id )
2018-11-18 11:00:15 +05:30
end
end
2021-10-27 15:23:28 +05:30
context 'when searching' do
let_it_be ( :subgroup1 ) { create ( :group , parent : group1 , path : 'some_path' ) }
let ( :response_groups ) { json_response . map { | group | group [ 'id' ] } }
subject { get api ( '/groups' , user1 ) , params : { search : group1 . path } }
it 'finds also groups with full path matching search param' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( response_groups ) . to match_array ( [ group1 . id , subgroup1 . id ] )
end
end
2014-09-02 18:07:02 +05:30
end
describe " GET /groups/:id " do
2018-03-17 18:26:18 +05:30
# Given a group, create one project for each visibility level
#
# group - Group to add projects to
# share_with - If provided, each project will be shared with this Group
#
# Returns a Hash of visibility_level => Project pairs
def add_projects_to_group ( group , share_with : nil )
projects = {
public : create ( :project , :public , namespace : group ) ,
internal : create ( :project , :internal , namespace : group ) ,
private : create ( :project , :private , namespace : group )
}
if share_with
create ( :project_group_link , project : projects [ :public ] , group : share_with )
create ( :project_group_link , project : projects [ :internal ] , group : share_with )
create ( :project_group_link , project : projects [ :private ] , group : share_with )
end
projects
end
2018-11-18 11:00:15 +05:30
def response_project_ids ( json_response , key )
json_response [ key ] . map do | project |
project [ 'id' ] . to_i
end
end
2018-03-17 18:26:18 +05:30
context 'when unauthenticated' do
it 'returns 404 for a private group' do
get api ( " /groups/ #{ group2 . id } " )
2018-11-18 11:00:15 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
it 'returns 200 for a public group' do
get api ( " /groups/ #{ group1 . id } " )
2018-11-18 11:00:15 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( json_response ) . not_to include ( 'runners_token' )
2020-04-22 19:07:51 +05:30
expect ( json_response ) . to include ( 'created_at' )
2018-03-17 18:26:18 +05:30
end
it 'returns only public projects in the group' do
public_group = create ( :group , :public )
projects = add_projects_to_group ( public_group )
get api ( " /groups/ #{ public_group . id } " )
2018-11-18 11:00:15 +05:30
expect ( response_project_ids ( json_response , 'projects' ) )
2018-03-17 18:26:18 +05:30
. to contain_exactly ( projects [ :public ] . id )
end
it 'returns only public projects shared with the group' do
public_group = create ( :group , :public )
projects = add_projects_to_group ( public_group , share_with : group1 )
get api ( " /groups/ #{ group1 . id } " )
2018-11-18 11:00:15 +05:30
expect ( response_project_ids ( json_response , 'shared_projects' ) )
2018-03-17 18:26:18 +05:30
. to contain_exactly ( projects [ :public ] . id )
end
end
2014-09-02 18:07:02 +05:30
context " when authenticated as user " do
2016-08-24 12:49:21 +05:30
it " returns one of user1's groups " do
2017-09-10 17:25:29 +05:30
project = create ( :project , namespace : group2 , path : 'Foo' )
2016-08-24 12:49:21 +05:30
create ( :project_group_link , project : project , group : group1 )
2020-06-23 00:09:42 +05:30
group = create ( :group )
link = create ( :group_group_link , shared_group : group1 , shared_with_group : group )
2016-08-24 12:49:21 +05:30
2014-09-02 18:07:02 +05:30
get api ( " /groups/ #{ group1 . id } " , user1 )
2016-08-24 12:49:21 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2016-08-24 12:49:21 +05:30
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 )
2017-08-17 22:00:37 +05:30
expect ( json_response [ 'visibility' ] ) . to eq ( Gitlab :: VisibilityLevel . string_level ( group1 . visibility_level ) )
2017-09-10 17:25:29 +05:30
expect ( json_response [ 'avatar_url' ] ) . to eq ( group1 . avatar_url ( only_path : false ) )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'share_with_group_lock' ] ) . to eq ( group1 . share_with_group_lock )
2021-09-30 23:02:18 +05:30
expect ( json_response [ 'prevent_sharing_groups_outside_hierarchy' ] ) . to eq ( group2 . namespace_settings . prevent_sharing_groups_outside_hierarchy )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'require_two_factor_authentication' ] ) . to eq ( group1 . require_two_factor_authentication )
expect ( json_response [ 'two_factor_grace_period' ] ) . to eq ( group1 . two_factor_grace_period )
expect ( json_response [ 'auto_devops_enabled' ] ) . to eq ( group1 . auto_devops_enabled )
expect ( json_response [ 'emails_disabled' ] ) . to eq ( group1 . emails_disabled )
2020-03-13 15:44:24 +05:30
expect ( json_response [ 'mentions_disabled' ] ) . to eq ( group1 . mentions_disabled )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'project_creation_level' ] ) . to eq ( 'maintainer' )
expect ( json_response [ 'subgroup_creation_level' ] ) . to eq ( 'maintainer' )
2016-08-24 12:49:21 +05:30
expect ( json_response [ 'web_url' ] ) . to eq ( group1 . web_url )
2017-08-17 22:00:37 +05:30
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 )
2020-04-22 19:07:51 +05:30
expect ( json_response [ 'created_at' ] ) . to be_present
2020-06-23 00:09:42 +05:30
expect ( json_response [ 'shared_with_groups' ] ) . to be_an Array
expect ( json_response [ 'shared_with_groups' ] . length ) . to eq ( 1 )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_id' ] ) . to eq ( group . id )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_name' ] ) . to eq ( group . name )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_full_path' ] ) . to eq ( group . full_path )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_access_level' ] ) . to eq ( link . group_access )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] ) . to have_key ( 'expires_at' )
2016-08-24 12:49:21 +05:30
expect ( json_response [ 'projects' ] ) . to be_an Array
2020-07-28 23:09:34 +05:30
expect ( json_response [ 'projects' ] . length ) . to eq ( 3 )
2016-08-24 12:49:21 +05:30
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 )
2014-09-02 18:07:02 +05:30
end
2018-11-18 11:00:15 +05:30
it " returns one of user1's groups without projects when with_projects option is set to false " do
project = create ( :project , namespace : group2 , path : 'Foo' )
create ( :project_group_link , project : project , group : group1 )
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } " , user1 ) , params : { with_projects : false }
2018-11-18 11:00:15 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-11-18 11:00:15 +05:30
expect ( json_response [ 'projects' ] ) . to be_nil
expect ( json_response [ 'shared_projects' ] ) . to be_nil
2019-12-04 20:38:33 +05:30
expect ( json_response ) . not_to include ( 'runners_token' )
end
it " doesn't return runners_token if the user is not the owner of the group " do
get api ( " /groups/ #{ group1 . id } " , user3 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( json_response ) . not_to include ( 'runners_token' )
end
it " returns runners_token if the user is the owner of the group " do
group1 . add_owner ( user3 )
get api ( " /groups/ #{ group1 . id } " , user3 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( json_response ) . to include ( 'runners_token' )
2018-11-18 11:00:15 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not return a non existing group " do
2021-09-04 01:27:46 +05:30
get api ( " /groups/ #{ non_existing_record_id } " , user1 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not return a group not attached to user1 " do
2014-09-02 18:07:02 +05:30
get api ( " /groups/ #{ group2 . id } " , user1 )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
it 'returns only public and internal projects in the group' do
public_group = create ( :group , :public )
projects = add_projects_to_group ( public_group )
get api ( " /groups/ #{ public_group . id } " , user2 )
2018-11-18 11:00:15 +05:30
expect ( response_project_ids ( json_response , 'projects' ) )
2018-03-17 18:26:18 +05:30
. to contain_exactly ( projects [ :public ] . id , projects [ :internal ] . id )
end
it 'returns only public and internal projects shared with the group' do
public_group = create ( :group , :public )
projects = add_projects_to_group ( public_group , share_with : group1 )
get api ( " /groups/ #{ group1 . id } " , user2 )
2018-11-18 11:00:15 +05:30
expect ( response_project_ids ( json_response , 'shared_projects' ) )
2018-03-17 18:26:18 +05:30
. to contain_exactly ( projects [ :public ] . id , projects [ :internal ] . id )
2014-09-02 18:07:02 +05:30
end
2019-03-02 22:35:43 +05:30
2020-06-23 00:09:42 +05:30
it 'avoids N+1 queries with project links' do
2019-03-02 22:35:43 +05:30
get api ( " /groups/ #{ group1 . id } " , admin )
control_count = ActiveRecord :: QueryRecorder . new do
get api ( " /groups/ #{ group1 . id } " , admin )
end . count
create ( :project , namespace : group1 )
expect do
get api ( " /groups/ #{ group1 . id } " , admin )
end . not_to exceed_query_limit ( control_count )
end
2020-06-23 00:09:42 +05:30
it 'avoids N+1 queries with shared group links' do
# setup at least 1 shared group, so that we record the queries that preload the nested associations too.
create ( :group_group_link , shared_group : group1 , shared_with_group : create ( :group ) )
control_count = ActiveRecord :: QueryRecorder . new do
get api ( " /groups/ #{ group1 . id } " , admin )
end . count
# setup "n" more shared groups
create ( :group_group_link , shared_group : group1 , shared_with_group : create ( :group ) )
create ( :group_group_link , shared_group : group1 , shared_with_group : create ( :group ) )
# test that no of queries for 1 shared group is same as for n shared groups
expect do
get api ( " /groups/ #{ group1 . id } " , admin )
end . not_to exceed_query_limit ( control_count )
end
2014-09-02 18:07:02 +05:30
end
context " when authenticated as admin " do
2016-09-13 17:45:13 +05:30
it " returns any existing group " do
2014-09-02 18:07:02 +05:30
get api ( " /groups/ #{ group2 . id } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2015-12-23 02:04:40 +05:30
expect ( json_response [ 'name' ] ) . to eq ( group2 . name )
2014-09-02 18:07:02 +05:30
end
2019-12-04 20:38:33 +05:30
it " returns information of the runners_token for the group " do
get api ( " /groups/ #{ group2 . id } " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-04 20:38:33 +05:30
expect ( json_response ) . to include ( 'runners_token' )
end
2016-09-13 17:45:13 +05:30
it " does not return a non existing group " do
2021-09-04 01:27:46 +05:30
get api ( " /groups/ #{ non_existing_record_id } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2015-04-26 12:48:37 +05:30
end
end
context 'when using group path in URL' do
2016-09-13 17:45:13 +05:30
it 'returns any existing group' do
2015-04-26 12:48:37 +05:30
get api ( " /groups/ #{ group1 . path } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2015-12-23 02:04:40 +05:30
expect ( json_response [ 'name' ] ) . to eq ( group1 . name )
2015-04-26 12:48:37 +05:30
end
2016-09-13 17:45:13 +05:30
it 'does not return a non existing group' do
2015-04-26 12:48:37 +05:30
get api ( '/groups/unknown' , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2015-04-26 12:48:37 +05:30
end
2016-09-13 17:45:13 +05:30
it 'does not return a group not attached to user1' do
2015-04-26 12:48:37 +05:30
get api ( " /groups/ #{ group2 . path } " , user1 )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2016-06-02 11:05:42 +05:30
end
end
2020-01-01 13:55:28 +05:30
context 'limiting the number of projects and shared_projects in the response' do
let ( :limit ) { 1 }
before do
stub_const ( " GroupProjectsFinder::DEFAULT_PROJECTS_LIMIT " , limit )
# creates 3 public projects
create_list ( :project , 3 , :public , namespace : group1 )
# creates 3 shared projects
public_group = create ( :group , :public )
projects_to_be_shared = create_list ( :project , 3 , :public , namespace : public_group )
projects_to_be_shared . each do | project |
create ( :project_group_link , project : project , group : group1 )
end
end
2021-09-04 01:27:46 +05:30
it 'limits projects and shared_projects' do
get api ( " /groups/ #{ group1 . id } " )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
expect ( json_response [ 'projects' ] . count ) . to eq ( limit )
expect ( json_response [ 'shared_projects' ] . count ) . to eq ( limit )
2020-01-01 13:55:28 +05:30
end
end
2016-06-02 11:05:42 +05:30
end
describe 'PUT /groups/:id' do
let ( :new_group_name ) { 'New Group' }
2021-03-11 19:13:27 +05:30
let ( :file_path ) { 'spec/fixtures/dk.png' }
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
it_behaves_like 'group avatar upload' do
def make_upload_request
group_param = {
avatar : fixture_file_upload ( file_path )
}
put api ( " /groups/ #{ group1 . id } " , user1 ) , params : group_param
end
end
2016-06-02 11:05:42 +05:30
context 'when authenticated as the group owner' do
it 'updates the group' do
2019-12-21 20:55:43 +05:30
put api ( " /groups/ #{ group1 . id } " , user1 ) , params : {
name : new_group_name ,
request_access_enabled : true ,
project_creation_level : " noone " ,
2020-04-08 14:13:33 +05:30
subgroup_creation_level : " maintainer " ,
2021-03-11 19:13:27 +05:30
default_branch_protection : :: Gitlab :: Access :: MAINTAINER_PROJECT_ACCESS ,
2021-09-30 23:02:18 +05:30
prevent_sharing_groups_outside_hierarchy : true ,
2021-03-11 19:13:27 +05:30
avatar : fixture_file_upload ( file_path )
2019-12-21 20:55:43 +05:30
}
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2016-06-02 11:05:42 +05:30
expect ( json_response [ 'name' ] ) . to eq ( new_group_name )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'description' ] ) . to eq ( '' )
expect ( json_response [ 'visibility' ] ) . to eq ( 'public' )
expect ( json_response [ 'share_with_group_lock' ] ) . to eq ( false )
expect ( json_response [ 'require_two_factor_authentication' ] ) . to eq ( false )
expect ( json_response [ 'two_factor_grace_period' ] ) . to eq ( 48 )
expect ( json_response [ 'auto_devops_enabled' ] ) . to eq ( nil )
expect ( json_response [ 'emails_disabled' ] ) . to eq ( nil )
2020-03-13 15:44:24 +05:30
expect ( json_response [ 'mentions_disabled' ] ) . to eq ( nil )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'project_creation_level' ] ) . to eq ( " noone " )
expect ( json_response [ 'subgroup_creation_level' ] ) . to eq ( " maintainer " )
2016-09-29 09:46:39 +05:30
expect ( json_response [ 'request_access_enabled' ] ) . to eq ( true )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'parent_id' ] ) . to eq ( nil )
2020-04-22 19:07:51 +05:30
expect ( json_response [ 'created_at' ] ) . to be_present
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'projects' ] ) . to be_an Array
2020-07-28 23:09:34 +05:30
expect ( json_response [ 'projects' ] . length ) . to eq ( 3 )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'shared_projects' ] ) . to be_an Array
expect ( json_response [ 'shared_projects' ] . length ) . to eq ( 0 )
2020-04-08 14:13:33 +05:30
expect ( json_response [ 'default_branch_protection' ] ) . to eq ( :: Gitlab :: Access :: MAINTAINER_PROJECT_ACCESS )
2021-03-11 19:13:27 +05:30
expect ( json_response [ 'avatar_url' ] ) . to end_with ( 'dk.png' )
2021-09-30 23:02:18 +05:30
expect ( json_response [ 'prevent_sharing_groups_outside_hierarchy' ] ) . to eq ( true )
2016-06-02 11:05:42 +05:30
end
2021-10-29 20:43:33 +05:30
it 'does not update visibility_level if it is restricted' do
stub_application_setting ( restricted_visibility_levels : [ Gitlab :: VisibilityLevel :: INTERNAL ] )
put api ( " /groups/ #{ group1 . id } " , user1 ) , params : { visibility : 'internal' }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
expect ( json_response [ 'message' ] [ 'visibility_level' ] ) . to include ( 'internal has been restricted by your GitLab administrator' )
end
2020-05-24 23:13:21 +05:30
context 'updating the `default_branch_protection` attribute' do
subject do
put api ( " /groups/ #{ group1 . id } " , user1 ) , params : { default_branch_protection : :: Gitlab :: Access :: PROTECTION_NONE }
end
context 'for users who have the ability to update default_branch_protection' do
it 'updates the attribute' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'default_branch_protection' ] ) . to eq ( Gitlab :: Access :: PROTECTION_NONE )
end
end
context 'for users who does not have the ability to update default_branch_protection`' do
it 'does not update the attribute' do
allow ( Ability ) . to receive ( :allowed? ) . and_call_original
allow ( Ability ) . to receive ( :allowed? ) . with ( user1 , :update_default_branch_protection , group1 ) { false }
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'default_branch_protection' ] ) . not_to eq ( Gitlab :: Access :: PROTECTION_NONE )
end
end
end
2020-03-28 13:19:24 +05:30
context 'malicious group name' do
subject { put api ( " /groups/ #{ group1 . id } " , user1 ) , params : { name : " <SCRIPT>alert('DOUBLE-ATTACK!')</SCRIPT> " } }
it 'returns bad request' do
subject
expect ( response ) . to have_gitlab_http_status ( :bad_request )
end
it 'does not update group name' do
expect { subject } . not_to change { group1 . reload . name }
end
end
2016-06-02 11:05:42 +05:30
it 'returns 404 for a non existing group' do
2021-09-04 01:27:46 +05:30
put api ( " /groups/ #{ non_existing_record_id } " , user1 ) , params : { name : new_group_name }
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2016-06-02 11:05:42 +05:30
end
2019-12-21 20:55:43 +05:30
context 'within a subgroup' do
let ( :group3 ) { create ( :group , visibility_level : Gitlab :: VisibilityLevel :: PUBLIC ) }
let! ( :subgroup ) { create ( :group , parent : group3 , visibility_level : Gitlab :: VisibilityLevel :: PUBLIC ) }
before do
group3 . add_owner ( user3 )
end
it 'does not change visibility when not requested' do
put api ( " /groups/ #{ group3 . id } " , user3 ) , params : { description : 'Bug #23083' }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'visibility' ] ) . to eq ( 'public' )
end
it 'prevents making private a group containing public subgroups' do
put api ( " /groups/ #{ group3 . id } " , user3 ) , params : { visibility : 'private' }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2019-12-21 20:55:43 +05:30
expect ( json_response [ 'message' ] [ 'visibility_level' ] ) . to contain_exactly ( 'private is not allowed since there are sub-groups with higher visibility.' )
end
2021-09-30 23:02:18 +05:30
it 'does not update prevent_sharing_groups_outside_hierarchy' do
put api ( " /groups/ #{ subgroup . id } " , user3 ) , params : { description : 'it works' , prevent_sharing_groups_outside_hierarchy : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response . keys ) . not_to include ( 'prevent_sharing_groups_outside_hierarchy' )
expect ( subgroup . reload . prevent_sharing_groups_outside_hierarchy ) . to eq ( false )
expect ( json_response [ 'description' ] ) . to eq ( 'it works' )
end
2019-12-21 20:55:43 +05:30
end
2016-06-02 11:05:42 +05:30
end
context 'when authenticated as the admin' do
it 'updates the group' do
2019-02-15 15:39:39 +05:30
put api ( " /groups/ #{ group1 . id } " , admin ) , params : { name : new_group_name }
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2016-06-02 11:05:42 +05:30
expect ( json_response [ 'name' ] ) . to eq ( new_group_name )
end
2021-10-29 20:43:33 +05:30
it 'ignores visibility level restrictions' do
stub_application_setting ( restricted_visibility_levels : [ Gitlab :: VisibilityLevel :: INTERNAL ] )
put api ( " /groups/ #{ group1 . id } " , admin ) , params : { visibility : 'internal' }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response [ 'visibility' ] ) . to eq ( 'internal' )
end
2016-06-02 11:05:42 +05:30
end
context 'when authenticated as an user that can see the group' do
it 'does not updates the group' do
2019-02-15 15:39:39 +05:30
put api ( " /groups/ #{ group1 . id } " , user2 ) , params : { name : new_group_name }
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2014-09-02 18:07:02 +05:30
end
end
2016-06-02 11:05:42 +05:30
context 'when authenticated as an user that cannot see the group' do
it 'returns 404 when trying to update the group' do
2019-02-15 15:39:39 +05:30
put api ( " /groups/ #{ group2 . id } " , user1 ) , params : { name : new_group_name }
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2016-06-02 11:05:42 +05:30
end
end
2014-09-02 18:07:02 +05:30
end
2015-12-23 02:04:40 +05:30
describe " GET /groups/:id/projects " do
context " when authenticated as user " do
2019-12-04 20:38:33 +05:30
context 'with min access level' do
it 'returns projects with min access level or higher' do
group_guest = create ( :user )
group1 . add_guest ( group_guest )
project4 = create ( :project , group : group1 )
project1 . add_guest ( group_guest )
project3 . add_reporter ( group_guest )
project4 . add_developer ( group_guest )
get api ( " /groups/ #{ group1 . id } /projects " , group_guest ) , params : { min_access_level : Gitlab :: Access :: REPORTER }
project_ids = json_response . map { | proj | proj [ 'id' ] }
expect ( project_ids ) . to match_array ( [ project3 . id , project4 . id ] )
end
end
2016-09-13 17:45:13 +05:30
it " returns the group's projects " do
2015-12-23 02:04:40 +05:30
get api ( " /groups/ #{ group1 . id } /projects " , user1 )
2016-06-16 23:09:34 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2020-07-28 23:09:34 +05:30
expect ( json_response . length ) . to eq ( 3 )
2017-08-17 22:00:37 +05:30
project_names = json_response . map { | proj | proj [ 'name' ] }
2020-07-28 23:09:34 +05:30
expect ( project_names ) . to match_array ( [ project1 . name , project3 . name , archived_project . name ] )
2017-08-17 22:00:37 +05:30
expect ( json_response . first [ 'visibility' ] ) . to be_present
end
2020-07-28 23:09:34 +05:30
context 'and using archived' do
it " returns the group's archived projects " do
get api ( " /groups/ #{ group1 . id } /projects?archived=true " , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( Project . public_or_visible_to_user ( user1 ) . where ( archived : true ) . size )
expect ( json_response . map { | project | project [ 'id' ] } ) . to include ( archived_project . id )
end
it " returns the group's non-archived projects " do
get api ( " /groups/ #{ group1 . id } /projects?archived=false " , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( Project . public_or_visible_to_user ( user1 ) . where ( archived : false ) . size )
expect ( json_response . map { | project | project [ 'id' ] } ) . not_to include ( archived_project . id )
end
it " returns all of the group's projects " do
get api ( " /groups/ #{ group1 . id } /projects " , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . map { | project | project [ 'id' ] } ) . to contain_exactly ( * Project . public_or_visible_to_user ( user1 ) . pluck ( :id ) )
end
end
2020-10-24 23:57:45 +05:30
context 'with similarity ordering' do
let_it_be ( :group_with_projects ) { create ( :group ) }
let_it_be ( :project_1 ) { create ( :project , name : 'Project' , path : 'project' , group : group_with_projects ) }
let_it_be ( :project_2 ) { create ( :project , name : 'Test Project' , path : 'test-project' , group : group_with_projects ) }
let_it_be ( :project_3 ) { create ( :project , name : 'Test' , path : 'test' , group : group_with_projects ) }
let ( :params ) { { order_by : 'similarity' , search : 'test' } }
subject { get api ( " /groups/ #{ group_with_projects . id } /projects " , user1 ) , params : params }
before do
group_with_projects . add_owner ( user1 )
end
it 'returns items based ordered by similarity' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 2 )
project_names = json_response . map { | proj | proj [ 'name' ] }
expect ( project_names ) . to eq ( [ 'Test' , 'Test Project' ] )
end
context 'when `search` parameter is not given' do
before do
params . delete ( :search )
end
it 'returns items ordered by name' do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 3 )
project_names = json_response . map { | proj | proj [ 'name' ] }
expect ( project_names ) . to eq ( [ 'Project' , 'Test' , 'Test Project' ] )
end
end
end
2017-08-17 22:00:37 +05:30
it " returns the group's projects with simple representation " do
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /projects " , user1 ) , params : { simple : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2020-07-28 23:09:34 +05:30
expect ( json_response . length ) . to eq ( 3 )
2017-08-17 22:00:37 +05:30
project_names = json_response . map { | proj | proj [ 'name' ] }
2020-07-28 23:09:34 +05:30
expect ( project_names ) . to match_array ( [ project1 . name , project3 . name , archived_project . name ] )
2017-08-17 22:00:37 +05:30
expect ( json_response . first [ 'visibility' ] ) . not_to be_present
end
2019-02-15 15:39:39 +05:30
it " filters the groups projects " do
2017-09-10 17:25:29 +05:30
public_project = create ( :project , :public , path : 'test1' , group : group1 )
2017-08-17 22:00:37 +05:30
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /projects " , user1 ) , params : { visibility : 'public' }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'name' ] ) . to eq ( public_project . name )
2015-12-23 02:04:40 +05:30
end
2019-02-15 15:39:39 +05:30
it " returns projects excluding shared " do
create ( :project_group_link , project : create ( :project ) , group : group1 )
create ( :project_group_link , project : create ( :project ) , group : group1 )
create ( :project_group_link , project : create ( :project ) , group : group1 )
get api ( " /groups/ #{ group1 . id } /projects " , user1 ) , params : { with_shared : false }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-02-15 15:39:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
2020-07-28 23:09:34 +05:30
expect ( json_response . length ) . to eq ( 3 )
2019-02-15 15:39:39 +05:30
end
2019-10-12 21:52:04 +05:30
it " returns projects including those in subgroups " do
2019-02-15 15:39:39 +05:30
subgroup = create ( :group , parent : group1 )
create ( :project , group : subgroup )
create ( :project , group : subgroup )
get api ( " /groups/ #{ group1 . id } /projects " , user1 ) , params : { include_subgroups : true }
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2019-02-15 15:39:39 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
2020-07-28 23:09:34 +05:30
expect ( json_response . length ) . to eq ( 5 )
2019-02-15 15:39:39 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not return a non existing group " do
2021-09-04 01:27:46 +05:30
get api ( " /groups/ #{ non_existing_record_id } /projects " , user1 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2015-12-23 02:04:40 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not return a group not attached to user1 " do
2015-12-23 02:04:40 +05:30
get api ( " /groups/ #{ group2 . id } /projects " , user1 )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2015-12-23 02:04:40 +05:30
end
2016-06-16 23:09:34 +05:30
2017-08-17 22:00:37 +05:30
it " only returns projects to which user has access " do
2018-03-17 18:26:18 +05:30
project3 . add_developer ( user3 )
2016-06-16 23:09:34 +05:30
get api ( " /groups/ #{ group1 . id } /projects " , user3 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2016-06-16 23:09:34 +05:30
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'name' ] ) . to eq ( project3 . name )
end
2017-08-17 22:00:37 +05:30
it 'only returns the projects owned by user' do
project2 . group . add_owner ( user3 )
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ project2 . group . id } /projects " , user3 ) , params : { owned : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
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 ]
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /projects " , user1 ) , params : { starred : true }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'name' ] ) . to eq ( project1 . name )
end
2015-12-23 02:04:40 +05:30
end
context " when authenticated as admin " do
2017-08-17 22:00:37 +05:30
it " returns any existing group " do
2015-12-23 02:04:40 +05:30
get api ( " /groups/ #{ group2 . id } /projects " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
2015-12-23 02:04:40 +05:30
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'name' ] ) . to eq ( project2 . name )
end
2017-08-17 22:00:37 +05:30
it " does not return a non existing group " do
2021-09-04 01:27:46 +05:30
get api ( " /groups/ #{ non_existing_record_id } /projects " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
it 'avoids N+1 queries' do
get api ( " /groups/ #{ group1 . id } /projects " , admin )
control_count = ActiveRecord :: QueryRecorder . new do
get api ( " /groups/ #{ group1 . id } /projects " , admin )
end . count
create ( :project , namespace : group1 )
expect do
get api ( " /groups/ #{ group1 . id } /projects " , admin )
end . not_to exceed_query_limit ( control_count )
2015-12-23 02:04:40 +05:30
end
end
context 'when using group path in URL' do
2017-08-17 22:00:37 +05:30
it 'returns any existing group' do
2015-12-23 02:04:40 +05:30
get api ( " /groups/ #{ group1 . path } /projects " , admin )
2016-06-16 23:09:34 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2017-08-17 22:00:37 +05:30
expect ( response ) . to include_pagination_headers
project_names = json_response . map { | proj | proj [ 'name' ] }
2020-07-28 23:09:34 +05:30
expect ( project_names ) . to match_array ( [ project1 . name , project3 . name , archived_project . name ] )
2015-12-23 02:04:40 +05:30
end
2016-09-13 17:45:13 +05:30
it 'does not return a non existing group' do
2015-12-23 02:04:40 +05:30
get api ( '/groups/unknown/projects' , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2015-12-23 02:04:40 +05:30
end
2016-09-13 17:45:13 +05:30
it 'does not return a group not attached to user1' do
2015-12-23 02:04:40 +05:30
get api ( " /groups/ #{ group2 . path } /projects " , user1 )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
end
end
2020-05-24 23:13:21 +05:30
describe " GET /groups/:id/projects/shared " do
let! ( :project4 ) do
create ( :project , namespace : group2 , path : 'test_project' , visibility_level : Gitlab :: VisibilityLevel :: PRIVATE )
end
2020-10-24 23:57:45 +05:30
2020-05-24 23:13:21 +05:30
let ( :path ) { " /groups/ #{ group1 . id } /projects/shared " }
before do
create ( :project_group_link , project : project2 , group : group1 )
create ( :project_group_link , project : project4 , group : group1 )
end
context 'when authenticated as user' do
it 'returns the shared projects in the group' do
get api ( path , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 2 )
project_ids = json_response . map { | project | project [ 'id' ] }
expect ( project_ids ) . to match_array ( [ project2 . id , project4 . id ] )
expect ( json_response . first [ 'visibility' ] ) . to be_present
end
it 'returns shared projects with min access level or higher' do
user = create ( :user )
project2 . add_guest ( user )
project4 . add_reporter ( user )
get api ( path , user ) , params : { min_access_level : Gitlab :: Access :: REPORTER }
expect ( json_response ) . to be_an ( Array )
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( project4 . id )
end
it 'returns the shared projects of the group with simple representation' do
get api ( path , user1 ) , params : { simple : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 2 )
project_ids = json_response . map { | project | project [ 'id' ] }
expect ( project_ids ) . to match_array ( [ project2 . id , project4 . id ] )
expect ( json_response . first [ 'visibility' ] ) . not_to be_present
end
it 'filters the shared projects in the group based on visibility' do
internal_project = create ( :project , :internal , namespace : create ( :group ) )
create ( :project_group_link , project : internal_project , group : group1 )
get api ( path , user1 ) , params : { visibility : 'internal' }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( internal_project . id )
end
it 'filters the shared projects in the group based on search params' do
get api ( path , user1 ) , params : { search : 'test_project' }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( project4 . id )
end
it 'does not return the projects owned by the group' do
get api ( path , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an ( Array )
project_ids = json_response . map { | project | project [ 'id' ] }
expect ( project_ids ) . not_to include ( project1 . id )
end
it 'returns 404 for a non-existing group' do
get api ( " /groups/0000/projects/shared " , user1 )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
it 'does not return a group not attached to the user' do
group = create ( :group , :private )
get api ( " /groups/ #{ group . id } /projects/shared " , user1 )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
it 'only returns shared projects to which user has access' do
project4 . add_developer ( user3 )
get api ( path , user3 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( project4 . id )
end
it 'only returns the projects starred by user' do
user1 . starred_projects = [ project2 ]
get api ( path , user1 ) , params : { starred : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( project2 . id )
end
end
context " when authenticated as admin " do
subject { get api ( path , admin ) }
it " returns shared projects of an existing group " do
subject
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 2 )
project_ids = json_response . map { | project | project [ 'id' ] }
expect ( project_ids ) . to match_array ( [ project2 . id , project4 . id ] )
end
context 'for a non-existent group' do
let ( :path ) { " /groups/000/projects/shared " }
it 'returns 404 for a non-existent group' do
subject
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
it 'avoids N+1 queries' do
control_count = ActiveRecord :: QueryRecorder . new do
subject
end . count
create ( :project_group_link , project : create ( :project ) , group : group1 )
expect do
subject
end . not_to exceed_query_limit ( control_count )
end
end
context 'when using group path in URL' do
let ( :path ) { " /groups/ #{ group1 . path } /projects/shared " }
it 'returns the right details' do
get api ( path , admin )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response . length ) . to eq ( 2 )
project_ids = json_response . map { | project | project [ 'id' ] }
expect ( project_ids ) . to match_array ( [ project2 . id , project4 . id ] )
end
it 'returns 404 for a non-existent group' do
get api ( '/groups/unknown/projects/shared' , admin )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
end
2019-10-12 21:52:04 +05:30
describe 'GET /groups/:id/subgroups' do
2018-03-17 18:26:18 +05:30
let! ( :subgroup1 ) { create ( :group , parent : group1 ) }
let! ( :subgroup2 ) { create ( :group , :private , parent : group1 ) }
let! ( :subgroup3 ) { create ( :group , :private , parent : group2 ) }
context 'when unauthenticated' do
it 'returns only public subgroups' do
get api ( " /groups/ #{ group1 . id } /subgroups " )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( subgroup1 . id )
expect ( json_response . first [ 'parent_id' ] ) . to eq ( group1 . id )
end
it 'returns 404 for a private group' do
get api ( " /groups/ #{ group2 . id } /subgroups " )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
2020-05-24 23:13:21 +05:30
context 'when statistics are requested' do
it 'does not include statistics' do
get api ( " /groups/ #{ group1 . id } /subgroups " ) , params : { statistics : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include 'statistics'
end
end
2018-03-17 18:26:18 +05:30
end
context 'when authenticated as user' do
context 'when user is not member of a public group' do
it 'returns no subgroups for the public group' do
get api ( " /groups/ #{ group1 . id } /subgroups " , user2 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 0 )
end
context 'when using all_available in request' do
it 'returns public subgroups' do
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /subgroups " , user2 ) , params : { all_available : true }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response [ 0 ] [ 'id' ] ) . to eq ( subgroup1 . id )
expect ( json_response [ 0 ] [ 'parent_id' ] ) . to eq ( group1 . id )
end
end
end
context 'when user is not member of a private group' do
it 'returns 404 for the private group' do
get api ( " /groups/ #{ group2 . id } /subgroups " , user1 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2018-03-17 18:26:18 +05:30
end
end
context 'when user is member of public group' do
before do
group1 . add_guest ( user2 )
end
it 'returns private subgroups' do
get api ( " /groups/ #{ group1 . id } /subgroups " , user2 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
private_subgroups = json_response . select { | group | group [ 'visibility' ] == 'private' }
expect ( private_subgroups . length ) . to eq ( 1 )
expect ( private_subgroups . first [ 'id' ] ) . to eq ( subgroup2 . id )
expect ( private_subgroups . first [ 'parent_id' ] ) . to eq ( group1 . id )
end
context 'when using statistics in request' do
it 'does not include statistics' do
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /subgroups " , user2 ) , params : { statistics : true }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include 'statistics'
end
end
end
context 'when user is member of private group' do
before do
group2 . add_guest ( user1 )
end
it 'returns subgroups' do
get api ( " /groups/ #{ group2 . id } /subgroups " , user1 )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
expect ( json_response . first [ 'id' ] ) . to eq ( subgroup3 . id )
expect ( json_response . first [ 'parent_id' ] ) . to eq ( group2 . id )
end
end
end
context 'when authenticated as admin' do
it 'returns private subgroups of a public group' do
get api ( " /groups/ #{ group1 . id } /subgroups " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
end
it 'returns subgroups of a private group' do
get api ( " /groups/ #{ group2 . id } /subgroups " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 1 )
end
it 'does not include statistics by default' do
get api ( " /groups/ #{ group1 . id } /subgroups " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include ( 'statistics' )
end
it 'includes statistics if requested' do
2019-02-15 15:39:39 +05:30
get api ( " /groups/ #{ group1 . id } /subgroups " , admin ) , params : { statistics : true }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :ok )
2018-03-17 18:26:18 +05:30
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . to include ( 'statistics' )
2015-12-23 02:04:40 +05:30
end
end
2021-10-27 15:23:28 +05:30
it_behaves_like 'skips searching in full path' do
let ( :parent ) { group1 }
let ( :endpoint ) { api ( " /groups/ #{ group1 . id } /subgroups " , user1 ) }
end
2015-12-23 02:04:40 +05:30
end
2021-01-03 14:25:43 +05:30
describe 'GET /groups/:id/descendant_groups' do
let_it_be ( :child_group1 ) { create ( :group , parent : group1 ) }
let_it_be ( :private_child_group1 ) { create ( :group , :private , parent : group1 ) }
let_it_be ( :sub_child_group1 ) { create ( :group , parent : child_group1 ) }
let_it_be ( :child_group2 ) { create ( :group , :private , parent : group2 ) }
let_it_be ( :sub_child_group2 ) { create ( :group , :private , parent : child_group2 ) }
2021-09-30 23:02:18 +05:30
2021-01-03 14:25:43 +05:30
let ( :response_groups ) { json_response . map { | group | group [ 'name' ] } }
context 'when unauthenticated' do
it 'returns only public descendants' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
expect ( response_groups ) . to contain_exactly ( child_group1 . name , sub_child_group1 . name )
end
it 'returns 404 for a private group' do
get api ( " /groups/ #{ group2 . id } /descendant_groups " )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when authenticated as user' do
context 'when user is not member of a public group' do
it 'returns no descendants for the public group' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , user2 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 0 )
end
context 'when using all_available in request' do
it 'returns public descendants' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , user2 ) , params : { all_available : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
expect ( response_groups ) . to contain_exactly ( child_group1 . name , sub_child_group1 . name )
end
end
end
context 'when user is not member of a private group' do
it 'returns 404 for the private group' do
get api ( " /groups/ #{ group2 . id } /descendant_groups " , user1 )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when user is member of public group' do
before do
group1 . add_guest ( user2 )
end
it 'returns private descendants' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , user2 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( response ) . to include_pagination_headers
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 3 )
expect ( response_groups ) . to contain_exactly ( child_group1 . name , sub_child_group1 . name , private_child_group1 . name )
end
context 'when using statistics in request' do
it 'does not include statistics' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , user2 ) , params : { statistics : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include 'statistics'
end
end
end
context 'when user is member of private group' do
before do
group2 . add_guest ( user1 )
end
it 'returns descendants' do
get api ( " /groups/ #{ group2 . id } /descendant_groups " , user1 )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
expect ( response_groups ) . to contain_exactly ( child_group2 . name , sub_child_group2 . name )
end
end
end
context 'when authenticated as admin' do
it 'returns private descendants of a public group' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , admin )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 3 )
end
it 'returns descendants of a private group' do
get api ( " /groups/ #{ group2 . id } /descendant_groups " , admin )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . length ) . to eq ( 2 )
end
it 'does not include statistics by default' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , admin )
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . not_to include ( 'statistics' )
end
it 'includes statistics if requested' do
get api ( " /groups/ #{ group1 . id } /descendant_groups " , admin ) , params : { statistics : true }
expect ( response ) . to have_gitlab_http_status ( :ok )
expect ( json_response ) . to be_an Array
expect ( json_response . first ) . to include ( 'statistics' )
end
end
2021-10-27 15:23:28 +05:30
it_behaves_like 'skips searching in full path' do
let ( :parent ) { group1 }
let ( :endpoint ) { api ( " /groups/ #{ group1 . id } /descendant_groups " , user1 ) }
end
2021-01-03 14:25:43 +05:30
end
2014-09-02 18:07:02 +05:30
describe " POST /groups " do
2020-04-08 14:13:33 +05:30
it_behaves_like 'group avatar upload' do
def make_upload_request
params = attributes_for_group_api ( request_access_enabled : false ) . tap do | attrs |
attrs [ :avatar ] = fixture_file_upload ( file_path )
end
post api ( " /groups " , user3 ) , params : params
end
end
2015-09-11 14:41:01 +05:30
context " when authenticated as user without group permissions " do
2016-09-13 17:45:13 +05:30
it " does not create group " do
2019-12-21 20:55:43 +05:30
group = attributes_for_group_api
post api ( " /groups " , user1 ) , params : group
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2018-03-17 18:26:18 +05:30
end
2019-10-12 21:52:04 +05:30
context 'as owner' do
2018-03-17 18:26:18 +05:30
before do
group2 . add_owner ( user1 )
end
it 'can create subgroups' do
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user1 ) , params : { parent_id : group2 . id , name : 'foo' , path : 'foo' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-03-17 18:26:18 +05:30
end
end
2019-10-12 21:52:04 +05:30
context 'as maintainer' do
2018-03-17 18:26:18 +05:30
before do
2018-11-18 11:00:15 +05:30
group2 . add_maintainer ( user1 )
2018-03-17 18:26:18 +05:30
end
2019-10-12 21:52:04 +05:30
it 'can create subgroups' do
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user1 ) , params : { parent_id : group2 . id , name : 'foo' , path : 'foo' }
2018-03-17 18:26:18 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2018-03-17 18:26:18 +05:30
end
2014-09-02 18:07:02 +05:30
end
end
2015-09-11 14:41:01 +05:30
context " when authenticated as user with group permissions " do
2016-09-13 17:45:13 +05:30
it " creates group " do
2019-12-21 20:55:43 +05:30
group = attributes_for_group_api request_access_enabled : false
2016-09-29 09:46:39 +05:30
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user3 ) , params : group
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2016-09-29 09:46:39 +05:30
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 ] )
2018-03-17 18:26:18 +05:30
expect ( json_response [ " visibility " ] ) . to eq ( Gitlab :: VisibilityLevel . string_level ( Gitlab :: CurrentSettings . current_application_settings . default_group_visibility ) )
2014-09-02 18:07:02 +05:30
end
2019-10-12 21:52:04 +05:30
it " creates a nested group " do
2017-08-17 22:00:37 +05:30
parent = create ( :group )
parent . add_owner ( user3 )
2019-12-21 20:55:43 +05:30
group = attributes_for_group_api parent_id : parent . id
2017-08-17 22:00:37 +05:30
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user3 ) , params : group
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-08-17 22:00:37 +05:30
expect ( json_response [ " full_path " ] ) . to eq ( " #{ parent . path } / #{ group [ :path ] } " )
expect ( json_response [ " parent_id " ] ) . to eq ( parent . id )
end
2020-03-28 13:19:24 +05:30
context 'malicious group name' do
subject { post api ( " /groups " , user3 ) , params : group_params }
let ( :group_params ) { attributes_for_group_api name : " <SCRIPT>alert('ATTACKED!')</SCRIPT> " , path : " unique-url " }
it 'returns bad request' do
subject
expect ( response ) . to have_gitlab_http_status ( :bad_request )
end
it { expect { subject } . not_to change { Group . count } }
end
2020-05-24 23:13:21 +05:30
context 'when creating a group with `default_branch_protection` attribute' do
let ( :params ) { attributes_for_group_api default_branch_protection : Gitlab :: Access :: PROTECTION_NONE }
subject { post api ( " /groups " , user3 ) , params : params }
context 'for users who have the ability to create a group with `default_branch_protection`' do
it 'creates group with the specified branch protection level' do
subject
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( json_response [ 'default_branch_protection' ] ) . to eq ( Gitlab :: Access :: PROTECTION_NONE )
end
end
context 'for users who do not have the ability to create a group with `default_branch_protection`' do
it 'does not create the group with the specified branch protection level' do
allow ( Ability ) . to receive ( :allowed? ) . and_call_original
allow ( Ability ) . to receive ( :allowed? ) . with ( user3 , :create_group_with_default_branch_protection ) { false }
subject
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( json_response [ 'default_branch_protection' ] ) . not_to eq ( Gitlab :: Access :: PROTECTION_NONE )
end
end
end
2016-09-13 17:45:13 +05:30
it " does not create group, duplicate " do
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user3 ) , params : { name : 'Duplicate Test' , path : group2 . path }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2015-04-26 12:48:37 +05:30
expect ( response . message ) . to eq ( " Bad Request " )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " returns 400 bad request error if name not given " do
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user3 ) , params : { path : group2 . path }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " returns 400 bad request error if path not given " do
2019-02-15 15:39:39 +05:30
post api ( " /groups " , user3 ) , params : { name : 'test' }
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :bad_request )
2014-09-02 18:07:02 +05:30
end
end
end
describe " DELETE /groups/:id " do
context " when authenticated as user " do
2016-09-13 17:45:13 +05:30
it " removes group " do
2018-11-08 19:23:39 +05:30
Sidekiq :: Testing . fake! do
expect { delete api ( " /groups/ #{ group1 . id } " , user1 ) } . to change ( GroupDestroyWorker . jobs , :size ) . by ( 1 )
end
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :accepted )
2018-03-17 18:26:18 +05:30
end
it_behaves_like '412 response' do
let ( :request ) { api ( " /groups/ #{ group1 . id } " , user1 ) }
2018-11-08 19:23:39 +05:30
let ( :success_status ) { 202 }
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not remove a group if not an owner " do
2015-09-11 14:41:01 +05:30
user4 = create ( :user )
2018-11-18 11:00:15 +05:30
group1 . add_maintainer ( user4 )
2017-08-17 22:00:37 +05:30
2014-09-02 18:07:02 +05:30
delete api ( " /groups/ #{ group1 . id } " , user3 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not remove a non existing group " do
2021-09-04 01:27:46 +05:30
delete api ( " /groups/ #{ non_existing_record_id } " , user1 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not remove a group not attached to user1 " do
2014-09-02 18:07:02 +05:30
delete api ( " /groups/ #{ group2 . id } " , user1 )
2016-06-02 11:05:42 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2014-09-02 18:07:02 +05:30
end
end
context " when authenticated as admin " do
2016-09-13 17:45:13 +05:30
it " removes any existing group " do
2014-09-02 18:07:02 +05:30
delete api ( " /groups/ #{ group2 . id } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :accepted )
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
it " does not remove a non existing group " do
2021-09-04 01:27:46 +05:30
delete api ( " /groups/ #{ non_existing_record_id } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2014-09-02 18:07:02 +05:30
end
end
end
describe " POST /groups/:id/projects/:project_id " do
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project ) }
let ( :project_path ) { CGI . escape ( project . full_path ) }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
before do
2020-01-01 13:55:28 +05:30
allow_next_instance_of ( Projects :: TransferService ) do | instance |
allow ( instance ) . to receive ( :execute ) . and_return ( true )
end
2014-09-02 18:07:02 +05:30
end
context " when authenticated as user " do
2016-09-13 17:45:13 +05:30
it " does not transfer project to group " do
2014-09-02 18:07:02 +05:30
post api ( " /groups/ #{ group1 . id } /projects/ #{ project . id } " , user2 )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :forbidden )
2014-09-02 18:07:02 +05:30
end
end
context " when authenticated as admin " do
2016-09-13 17:45:13 +05:30
it " transfers project to group " do
2014-09-02 18:07:02 +05:30
post api ( " /groups/ #{ group1 . id } /projects/ #{ project . id } " , admin )
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when using project path in URL' do
context 'with a valid project path' do
it " transfers project to group " do
post api ( " /groups/ #{ group1 . id } /projects/ #{ project_path } " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-08-17 22:00:37 +05:30
end
end
context 'with a non-existent project path' do
it " does not transfer project to group " do
post api ( " /groups/ #{ group1 . id } /projects/nogroup%2Fnoproject " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2017-08-17 22:00:37 +05:30
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 api ( " /groups/ #{ group1 . path } /projects/ #{ project_path } " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :created )
2017-08-17 22:00:37 +05:30
end
end
context 'with a non-existent group path' do
it " does not transfer project to group " do
post api ( " /groups/noexist/projects/ #{ project_path } " , admin )
2020-04-08 14:13:33 +05:30
expect ( response ) . to have_gitlab_http_status ( :not_found )
2017-08-17 22:00:37 +05:30
end
end
end
2014-09-02 18:07:02 +05:30
end
end
2018-03-17 18:26:18 +05:30
it_behaves_like 'custom attributes endpoints' , 'groups' do
let ( :attributable ) { group1 }
let ( :other_attributable ) { group2 }
let ( :user ) { user1 }
before do
group2 . add_owner ( user1 )
end
end
2020-06-23 00:09:42 +05:30
describe " POST /groups/:id/share " do
shared_examples 'shares group with group' do
it " shares group with group " do
expires_at = 10 . days . from_now . to_date
expect do
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_id : shared_with_group . id , group_access : Gitlab :: Access :: DEVELOPER , expires_at : expires_at }
end . to change { group . shared_with_group_links . count } . by ( 1 )
expect ( response ) . to have_gitlab_http_status ( :created )
expect ( json_response [ 'shared_with_groups' ] ) . to be_an Array
expect ( json_response [ 'shared_with_groups' ] . length ) . to eq ( 1 )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_id' ] ) . to eq ( shared_with_group . id )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_name' ] ) . to eq ( shared_with_group . name )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_full_path' ] ) . to eq ( shared_with_group . full_path )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'group_access_level' ] ) . to eq ( Gitlab :: Access :: DEVELOPER )
expect ( json_response [ 'shared_with_groups' ] [ 0 ] [ 'expires_at' ] ) . to eq ( expires_at . to_s )
end
it " returns a 400 error when group id is not given " do
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_access : Gitlab :: Access :: DEVELOPER }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
end
it " returns a 400 error when access level is not given " do
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_id : shared_with_group . id }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
end
it 'returns a 404 error when group does not exist' do
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_id : non_existing_record_id , group_access : Gitlab :: Access :: DEVELOPER }
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
it " returns a 400 error when wrong params passed " do
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_id : shared_with_group . id , group_access : non_existing_record_access_level }
expect ( response ) . to have_gitlab_http_status ( :bad_request )
expect ( json_response [ 'error' ] ) . to eq 'group_access does not have a valid value'
end
it " returns a 409 error when link is not saved " do
allow ( :: Groups :: GroupLinks :: CreateService ) . to receive_message_chain ( :new , :execute )
. and_return ( { status : :error , http_status : 409 , message : 'error' } )
post api ( " /groups/ #{ group . id } /share " , user ) , params : { group_id : shared_with_group . id , group_access : Gitlab :: Access :: DEVELOPER }
expect ( response ) . to have_gitlab_http_status ( :conflict )
end
end
context 'when authenticated as owner' do
let ( :owner_group ) { create ( :group ) }
let ( :owner_user ) { create ( :user ) }
before do
owner_group . add_owner ( owner_user )
end
it_behaves_like 'shares group with group' do
let ( :user ) { owner_user }
let ( :group ) { owner_group }
let ( :shared_with_group ) { create ( :group ) }
end
end
context 'when the user is not the owner of the group' do
let ( :group ) { create ( :group ) }
let ( :user4 ) { create ( :user ) }
let ( :expires_at ) { 10 . days . from_now . to_date }
before do
group1 . add_maintainer ( user4 )
end
it 'does not create group share' do
post api ( " /groups/ #{ group1 . id } /share " , user4 ) , params : { group_id : group . id , group_access : Gitlab :: Access :: DEVELOPER , expires_at : expires_at }
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when authenticated as admin' do
it_behaves_like 'shares group with group' do
let ( :user ) { admin }
let ( :group ) { create ( :group ) }
let ( :shared_with_group ) { create ( :group ) }
end
end
end
describe 'DELETE /groups/:id/share/:group_id' do
shared_examples 'deletes group share' do
it 'deletes a group share' do
expect do
delete api ( " /groups/ #{ shared_group . id } /share/ #{ shared_with_group . id } " , user )
expect ( response ) . to have_gitlab_http_status ( :no_content )
expect ( shared_group . shared_with_group_links ) . to be_empty
end . to change { shared_group . shared_with_group_links . count } . by ( - 1 )
end
it 'requires the group id to be an integer' do
delete api ( " /groups/ #{ shared_group . id } /share/foo " , user )
expect ( response ) . to have_gitlab_http_status ( :bad_request )
end
it 'returns a 404 error when group link does not exist' do
delete api ( " /groups/ #{ shared_group . id } /share/ #{ non_existing_record_id } " , user )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
it 'returns a 404 error when group does not exist' do
delete api ( " /groups/123/share/ #{ non_existing_record_id } " , user )
expect ( response ) . to have_gitlab_http_status ( :not_found )
end
end
context 'when authenticated as owner' do
let ( :group_a ) { create ( :group ) }
before do
create ( :group_group_link , shared_group : group1 , shared_with_group : group_a )
end
it_behaves_like 'deletes group share' do
let ( :user ) { user1 }
let ( :shared_group ) { group1 }
let ( :shared_with_group ) { group_a }
end
end
context 'when the user is not the owner of the group' do
let ( :group_a ) { create ( :group ) }
let ( :user4 ) { create ( :user ) }
before do
group1 . add_maintainer ( user4 )
create ( :group_group_link , shared_group : group1 , shared_with_group : group_a )
end
it 'does not remove group share' do
expect do
delete api ( " /groups/ #{ group1 . id } /share/ #{ group_a . id } " , user4 )
expect ( response ) . to have_gitlab_http_status ( :no_content )
end . not_to change { group1 . shared_with_group_links }
end
end
context 'when authenticated as admin' do
let ( :group_b ) { create ( :group ) }
before do
create ( :group_group_link , shared_group : group2 , shared_with_group : group_b )
end
it_behaves_like 'deletes group share' do
let ( :user ) { admin }
let ( :shared_group ) { group2 }
let ( :shared_with_group ) { group_b }
end
end
end
2014-09-02 18:07:02 +05:30
end