2018-09-29 22:34:47 +00:00
# frozen_string_literal: true
2013-05-14 12:33:31 +00:00
module API
2020-04-27 18:09:41 +00:00
class Groups < Grape :: API :: Instance
2016-12-04 17:11:19 +00:00
include PaginationParams
2017-12-22 15:54:55 +00:00
include Helpers :: CustomAttributes
2016-12-12 08:55:29 +00:00
2017-08-23 12:01:11 +00:00
before { authenticate_non_get! }
2013-01-08 21:05:00 +00:00
2019-05-27 12:37:53 +00:00
helpers Helpers :: GroupsHelpers
2019-05-20 17:02:06 +00:00
helpers do
2016-11-22 16:58:10 +00:00
params :statistics_params do
optional :statistics , type : Boolean , default : false , desc : 'Include project statistics'
end
2017-11-09 16:07:04 +00:00
params :group_list_params do
2016-11-22 16:58:10 +00:00
use :statistics_params
2020-04-27 18:09:41 +00:00
optional :skip_groups , type : Array [ Integer ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToIntegerArray . coerce , desc : 'Array of group ids to exclude from list'
2016-11-07 15:54:39 +00:00
optional :all_available , type : Boolean , desc : 'Show all group that you have access to'
optional :search , type : String , desc : 'Search for a specific group'
2017-02-24 08:25:53 +00:00
optional :owned , type : Boolean , default : false , desc : 'Limit by owned by authenticated user'
2018-06-08 18:37:19 +00:00
optional :order_by , type : String , values : %w[ name path id ] , default : 'name' , desc : 'Order by name, path or id'
2016-11-17 12:41:48 +00:00
optional :sort , type : String , values : %w[ asc desc ] , default : 'asc' , desc : 'Sort by asc (ascending) or desc (descending)'
2018-07-08 19:41:55 +00:00
optional :min_access_level , type : Integer , values : Gitlab :: Access . all_values , desc : 'Minimum access level of authenticated user'
2016-12-04 17:11:19 +00:00
use :pagination
2016-11-07 15:54:39 +00:00
end
2017-11-09 16:07:04 +00:00
2018-08-27 15:31:01 +00:00
# rubocop: disable CodeReuse/ActiveRecord
2018-05-01 09:24:21 +00:00
def find_groups ( params , parent_id = nil )
2018-07-08 19:41:55 +00:00
find_params = params . slice ( :all_available , :custom_attributes , :owned , :min_access_level )
2018-05-01 09:24:21 +00:00
find_params [ :parent ] = find_group! ( parent_id ) if parent_id
find_params [ :all_available ] =
2019-12-17 09:07:48 +00:00
find_params . fetch ( :all_available , current_user & . can_read_all_resources? )
2017-09-18 15:07:38 +00:00
2017-08-24 10:33:06 +00:00
groups = GroupsFinder . new ( current_user , find_params ) . execute
2016-11-07 15:54:39 +00:00
groups = groups . search ( params [ :search ] ) if params [ :search ] . present?
groups = groups . where . not ( id : params [ :skip_groups ] ) if params [ :skip_groups ] . present?
2018-06-15 10:16:21 +00:00
order_options = { params [ :order_by ] = > params [ :sort ] }
order_options [ " id " ] || = " asc "
groups = groups . reorder ( order_options )
2016-11-17 12:41:48 +00:00
2017-11-09 16:07:04 +00:00
groups
end
2018-08-27 15:31:01 +00:00
# rubocop: enable CodeReuse/ActiveRecord
2017-11-09 16:07:04 +00:00
2019-02-25 14:01:34 +00:00
def create_group
# This is a separate method so that EE can extend its behaviour, without
# having to modify this code directly.
:: Groups :: CreateService
. new ( current_user , declared_params ( include_missing : false ) )
. execute
end
2019-02-25 14:17:17 +00:00
def update_group ( group )
# This is a separate method so that EE can extend its behaviour, without
# having to modify this code directly.
:: Groups :: UpdateService
. new ( group , current_user , declared_params ( include_missing : false ) )
. execute
end
2017-11-24 12:20:52 +00:00
def find_group_projects ( params )
group = find_group! ( params [ :id ] )
2018-10-26 06:02:20 +00:00
options = {
2018-10-26 06:34:31 +00:00
only_owned : ! params [ :with_shared ] ,
2018-10-26 06:02:20 +00:00
include_subgroups : params [ :include_subgroups ]
}
projects = GroupProjectsFinder . new (
group : group ,
current_user : current_user ,
params : project_finder_params ,
options : options
) . execute
2018-07-02 08:04:43 +00:00
projects = projects . with_issues_available_for_user ( current_user ) if params [ :with_issues_enabled ]
projects = projects . with_merge_requests_enabled if params [ :with_merge_requests_enabled ]
2019-09-04 16:33:02 +00:00
projects = projects . visible_to_user_and_access_level ( current_user , params [ :min_access_level ] ) if params [ :min_access_level ]
2017-11-24 12:20:52 +00:00
projects = reorder_projects ( projects )
2017-11-27 11:24:33 +00:00
paginate ( projects )
2017-11-24 12:20:52 +00:00
end
2017-11-09 16:07:04 +00:00
def present_groups ( params , groups )
options = {
with : Entities :: Group ,
current_user : current_user ,
statistics : params [ :statistics ] && current_user . admin?
}
groups = groups . with_statistics if options [ :statistics ]
2017-12-22 15:54:55 +00:00
groups , options = with_custom_attributes ( groups , options )
2017-11-09 16:07:04 +00:00
present paginate ( groups ) , options
end
2020-01-24 12:09:01 +00:00
def delete_group ( group )
Gitlab :: QueryLimiting . whitelist ( 'https://gitlab.com/gitlab-org/gitlab-foss/issues/46285' )
destroy_conditionally! ( group ) do | group |
:: Groups :: DestroyService . new ( group , current_user ) . async_execute
end
accepted!
end
2017-11-09 16:07:04 +00:00
end
resource :groups do
include CustomAttributesEndpoints
desc 'Get a groups list' do
success Entities :: Group
end
params do
use :group_list_params
2017-12-22 15:54:55 +00:00
use :with_custom_attributes
2017-11-09 16:07:04 +00:00
end
get do
2018-05-01 09:24:21 +00:00
groups = find_groups ( declared_params ( include_missing : false ) , params [ :id ] )
2017-11-09 16:07:04 +00:00
present_groups params , groups
2013-02-01 14:00:12 +00:00
end
2016-11-07 15:54:39 +00:00
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'
2019-07-24 09:20:54 +00:00
optional :parent_id , type : Integer , desc : 'The parent group id for creating nested group'
2017-05-03 12:49:37 +00:00
2016-11-07 15:54:39 +00:00
use :optional_params
end
2013-02-01 14:00:12 +00:00
post do
2017-09-07 18:35:45 +00:00
parent_group = find_group! ( params [ :parent_id ] ) if params [ :parent_id ] . present?
if parent_group
authorize! :create_subgroup , parent_group
else
authorize! :create_group
end
2013-02-27 11:34:45 +00:00
2019-02-25 14:01:34 +00:00
group = create_group
2013-02-01 14:00:12 +00:00
2016-11-07 15:54:39 +00:00
if group . persisted?
2017-06-06 13:42:45 +00:00
present group , with : Entities :: GroupDetail , current_user : current_user
2013-02-01 14:00:12 +00:00
else
2016-11-07 15:54:39 +00:00
render_api_error! ( " Failed to save group #{ group . errors . messages } " , 400 )
2013-02-01 14:00:12 +00:00
end
end
2016-11-07 15:54:39 +00:00
end
2013-02-01 14:00:12 +00:00
2016-11-07 15:54:39 +00:00
params do
requires :id , type : String , desc : 'The ID of a group'
end
2018-11-08 12:18:17 +00:00
resource :groups , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
2016-11-07 15:54:39 +00:00
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
2019-05-20 17:02:06 +00:00
use :optional_update_params_ee
2016-11-07 15:54:39 +00:00
end
2016-04-07 08:12:49 +00:00
put ':id' do
2016-11-24 15:58:32 +00:00
group = find_group! ( params [ :id ] )
2016-04-07 08:12:49 +00:00
authorize! :admin_group , group
2019-02-25 14:17:17 +00:00
if update_group ( group )
2016-11-29 19:21:39 +00:00
present group , with : Entities :: GroupDetail , current_user : current_user
2016-04-12 17:08:35 +00:00
else
render_validation_error! ( group )
2016-04-07 08:12:49 +00:00
end
end
2016-11-07 15:54:39 +00:00
desc 'Get a single group, with containing projects.' do
success Entities :: GroupDetail
end
2017-12-22 15:54:55 +00:00
params do
use :with_custom_attributes
2018-07-09 12:24:29 +00:00
optional :with_projects , type : Boolean , default : true , desc : 'Omit project details'
2017-12-22 15:54:55 +00:00
end
2013-02-01 14:00:12 +00:00
get " :id " do
2016-11-24 15:58:32 +00:00
group = find_group! ( params [ :id ] )
2017-12-22 15:54:55 +00:00
options = {
2018-07-09 12:24:29 +00:00
with : params [ :with_projects ] ? Entities :: GroupDetail : Entities :: Group ,
2019-09-17 12:06:48 +00:00
current_user : current_user ,
user_can_admin_group : can? ( current_user , :admin_group , group )
2017-12-22 15:54:55 +00:00
}
group , options = with_custom_attributes ( group , options )
present group , options
2013-02-01 14:00:12 +00:00
end
2012-11-14 20:37:52 +00:00
2016-11-07 15:54:39 +00:00
desc 'Remove a group.'
2013-10-07 10:10:01 +00:00
delete " :id " do
2016-11-24 15:58:32 +00:00
group = find_group! ( params [ :id ] )
2015-04-10 12:39:10 +00:00
authorize! :admin_group , group
2017-07-20 13:33:18 +00:00
2020-01-24 12:09:01 +00:00
delete_group ( group )
2013-10-07 10:10:01 +00:00
end
2016-11-07 15:54:39 +00:00
desc 'Get a list of projects in this group.' do
success Entities :: Project
end
2016-12-04 17:11:19 +00:00
params do
2016-12-12 08:55:29 +00:00
optional :archived , type : Boolean , default : false , desc : 'Limit by archived status'
2017-02-16 13:56:14 +00:00
optional :visibility , type : String , values : Gitlab :: VisibilityLevel . string_values ,
2016-12-12 08:55:29 +00:00
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'
2016-12-13 12:51:30 +00:00
optional :simple , type : Boolean , default : false ,
desc : 'Return only the ID, URL, name, and path of each project'
2017-02-01 10:23:57 +00:00
optional :owned , type : Boolean , default : false , desc : 'Limit by owned by authenticated user'
optional :starred , type : Boolean , default : false , desc : 'Limit by starred status'
2018-07-02 08:04:43 +00:00
optional :with_issues_enabled , type : Boolean , default : false , desc : 'Limit by enabled issues feature'
optional :with_merge_requests_enabled , type : Boolean , default : false , desc : 'Limit by enabled merge requests feature'
2018-10-26 06:34:31 +00:00
optional :with_shared , type : Boolean , default : true , desc : 'Include projects shared to this group'
2018-10-26 06:02:20 +00:00
optional :include_subgroups , type : Boolean , default : false , desc : 'Includes projects in subgroups of this group'
2019-09-04 16:33:02 +00:00
optional :min_access_level , type : Integer , values : Gitlab :: Access . all_values , desc : 'Limit by minimum access level of authenticated user on projects'
2017-02-01 10:23:57 +00:00
2016-12-04 17:11:19 +00:00
use :pagination
2017-12-22 15:54:55 +00:00
use :with_custom_attributes
2019-08-28 14:26:42 +00:00
use :optional_projects_params
2016-12-04 17:11:19 +00:00
end
2015-12-07 16:10:40 +00:00
get " :id/projects " do
2017-11-24 12:20:52 +00:00
projects = find_group_projects ( params )
2017-11-27 11:24:33 +00:00
2017-12-22 15:54:55 +00:00
options = {
with : params [ :simple ] ? Entities :: BasicProjectDetails : Entities :: Project ,
current_user : current_user
}
projects , options = with_custom_attributes ( projects , options )
2019-12-13 03:07:50 +00:00
present options [ :with ] . prepare_relation ( projects ) , options
2015-12-07 16:10:40 +00:00
end
2017-11-09 16:07:04 +00:00
desc 'Get a list of subgroups in this group.' do
success Entities :: Group
end
params do
use :group_list_params
2017-12-22 15:54:55 +00:00
use :with_custom_attributes
2017-11-09 16:07:04 +00:00
end
get " :id/subgroups " do
2018-05-01 09:24:21 +00:00
groups = find_groups ( declared_params ( include_missing : false ) , params [ :id ] )
2017-11-09 16:07:04 +00:00
present_groups params , groups
end
2016-11-07 15:54:39 +00:00
desc 'Transfer a project to the group namespace. Available only for admin.' do
success Entities :: GroupDetail
end
params do
2017-01-02 18:19:47 +00:00
requires :project_id , type : String , desc : 'The ID or path of the project'
2016-11-07 15:54:39 +00:00
end
2017-03-15 18:09:24 +00:00
post " :id/projects/:project_id " , requirements : { project_id : / .+ / } do
2012-11-14 20:37:52 +00:00
authenticated_as_admin!
2017-01-02 18:19:47 +00:00
group = find_group! ( params [ :id ] )
project = find_project! ( params [ :project_id ] )
2015-07-02 12:31:25 +00:00
result = :: Projects :: TransferService . new ( project , current_user ) . execute ( group )
2014-05-28 16:03:45 +00:00
if result
2016-11-29 19:21:39 +00:00
present group , with : Entities :: GroupDetail , current_user : current_user
2012-11-14 20:37:52 +00:00
else
2015-01-07 09:46:00 +00:00
render_api_error! ( " Failed to transfer project #{ project . errors . messages } " , 400 )
2012-11-14 20:37:52 +00:00
end
2013-03-20 21:46:30 +00:00
end
2013-02-01 14:00:12 +00:00
end
2013-01-08 21:05:00 +00:00
end
end
2019-09-13 13:26:31 +00:00
API :: Groups . prepend_if_ee ( 'EE::API::Groups' )