2018-09-29 18:34:47 -04:00
# frozen_string_literal: true
2017-06-29 14:57:59 -04:00
require_dependency 'declarative_policy'
2017-04-11 17:07:46 -04:00
2013-05-14 08:33:31 -04:00
module API
2020-06-29 17:09:07 -04:00
class Projects < Grape :: API :: Instance
2016-11-09 09:51:27 -05:00
include PaginationParams
2017-12-22 10:54:55 -05:00
include Helpers :: CustomAttributes
2019-05-30 17:55:17 -04:00
helpers Helpers :: ProjectsHelpers
2016-11-09 09:51:27 -05:00
2016-11-30 09:48:19 -05:00
before { authenticate_non_get! }
2012-06-29 06:46:01 -04:00
2018-07-19 14:32:12 -04:00
helpers do
# EE::API::Projects would override this method
def apply_filters ( projects )
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 ]
projects = projects . with_statistics if params [ :statistics ]
2020-06-19 17:08:32 -04:00
projects = projects . joins ( :statistics ) if params [ :order_by ] . include? ( 'project_statistics' ) # rubocop: disable CodeReuse/ActiveRecord
2018-07-19 14:32:12 -04:00
2019-02-04 10:06:17 -05:00
lang = params [ :with_programming_language ]
projects = projects . with_programming_language ( lang ) if lang
2018-07-19 14:32:12 -04:00
projects
end
2018-07-27 11:24:43 -04:00
def verify_update_project_attrs! ( project , attrs )
2020-03-02 16:08:01 -05:00
attrs . delete ( :repository_storage ) unless can? ( current_user , :change_repository_storage , project )
2018-07-27 11:24:43 -04:00
end
2019-12-17 10:08:15 -05:00
2020-06-19 17:08:32 -04:00
def verify_project_filters! ( attrs )
attrs . delete ( :repository_storage ) unless can? ( current_user , :use_project_statistics_filters )
end
def verify_statistics_order_by_projects!
return unless Helpers :: ProjectsHelpers :: STATISTICS_SORT_PARAMS . include? ( params [ :order_by ] )
params [ :order_by ] = if can? ( current_user , :use_project_statistics_filters )
" project_statistics. #{ params [ :order_by ] } "
else
route . params [ 'order_by' ] [ :default ]
end
end
2019-12-17 10:08:15 -05:00
def delete_project ( user_project )
destroy_conditionally! ( user_project ) do
:: Projects :: DestroyService . new ( user_project , current_user , { } ) . async_execute
end
accepted!
end
2018-07-27 11:24:43 -04:00
end
2016-11-09 09:51:27 -05:00
helpers do
2017-05-01 05:42:42 -04:00
params :statistics_params do
optional :statistics , type : Boolean , default : false , desc : 'Include project statistics'
end
2017-06-29 13:20:59 -04:00
params :collection_params do
use :sort_params
use :filter_params
use :pagination
optional :simple , type : Boolean , default : false ,
desc : 'Return only the ID, URL, name, and path of each project'
end
params :sort_params do
2020-06-19 17:08:32 -04:00
optional :order_by , type : String ,
values : %w[ id name path created_at updated_at last_activity_at ] + Helpers :: ProjectsHelpers :: STATISTICS_SORT_PARAMS ,
default : 'created_at' , desc : " Return projects ordered by field. #{ Helpers :: ProjectsHelpers :: STATISTICS_SORT_PARAMS . join ( ', ' ) } are only available to admins. "
2017-06-29 13:20:59 -04:00
optional :sort , type : String , values : %w[ asc desc ] , default : 'desc' ,
desc : 'Return projects sorted in ascending and descending order'
end
params :filter_params do
2018-07-11 14:17:18 -04:00
optional :archived , type : Boolean , desc : 'Limit by archived status'
2017-06-29 13:20:59 -04:00
optional :visibility , type : String , values : Gitlab :: VisibilityLevel . string_values ,
desc : 'Limit by visibility'
optional :search , type : String , desc : 'Return list of projects matching the search criteria'
2020-03-23 08:09:47 -04:00
optional :search_namespaces , type : Boolean , desc : " Include ancestor namespaces when matching search criteria "
2017-06-29 13:20:59 -04: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'
optional :membership , type : Boolean , default : false , desc : 'Limit by projects that the current user is a member of'
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'
2019-02-04 10:06:17 -05:00
optional :with_programming_language , type : String , desc : 'Limit to repositories which use the given programming language'
2018-07-08 15:43:06 -04:00
optional :min_access_level , type : Integer , values : Gitlab :: Access . all_values , desc : 'Limit by minimum access level of authenticated user'
2019-11-15 01:06:13 -05:00
optional :id_after , type : Integer , desc : 'Limit results to projects with IDs greater than the specified ID'
optional :id_before , type : Integer , desc : 'Limit results to projects with IDs less than the specified ID'
2020-04-01 05:07:45 -04:00
optional :last_activity_after , type : DateTime , desc : 'Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
optional :last_activity_before , type : DateTime , desc : 'Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
2020-06-19 17:08:32 -04:00
optional :repository_storage , type : String , desc : 'Which storage shard the repository is on. Available only to admins'
2018-07-19 14:32:12 -04:00
2019-05-30 17:55:17 -04:00
use :optional_filter_params_ee
2017-06-29 13:20:59 -04:00
end
params :create_params do
optional :namespace_id , type : Integer , desc : 'Namespace ID for the new project. Default to the user namespace.'
optional :import_url , type : String , desc : 'URL from which the project is imported'
2019-09-16 20:06:11 -04:00
optional :template_name , type : String , desc : " Name of template from which to create project "
2019-11-18 13:06:53 -05:00
optional :template_project_id , type : Integer , desc : " Project ID of template from which to create project "
mutually_exclusive :import_url , :template_name , :template_project_id
2017-06-29 13:20:59 -04:00
end
2019-12-12 22:07:50 -05:00
def load_projects
2020-06-19 17:08:32 -04:00
params = project_finder_params
verify_project_filters! ( params )
ProjectsFinder . new ( current_user : current_user , params : params ) . execute
2017-09-19 01:48:22 -04:00
end
2019-12-12 22:07:50 -05:00
def present_projects ( projects , options = { } )
2020-06-19 17:08:32 -04:00
verify_statistics_order_by_projects!
2017-06-29 13:20:59 -04:00
projects = reorder_projects ( projects )
2018-07-19 14:32:12 -04:00
projects = apply_filters ( projects )
2020-01-10 10:07:47 -05:00
2020-05-05 17:09:42 -04:00
records , options = paginate_with_strategies ( projects , options [ :request_scope ] ) do | projects |
2020-01-10 10:07:47 -05:00
projects , options = with_custom_attributes ( projects , options )
options = options . reverse_merge (
with : current_user ? Entities :: ProjectWithAccess : Entities :: BasicProjectDetails ,
statistics : params [ :statistics ] ,
current_user : current_user ,
license : false
)
options [ :with ] = Entities :: BasicProjectDetails if params [ :simple ]
[ options [ :with ] . prepare_relation ( projects , options ) , options ]
end
present records , options
2017-06-29 13:20:59 -04:00
end
2018-04-21 14:02:21 -04:00
def translate_params_for_compatibility ( params )
params [ :builds_enabled ] = params . delete ( :jobs_enabled ) if params . key? ( :jobs_enabled )
params
end
2016-11-09 09:51:27 -05:00
end
2012-06-29 06:46:01 -04:00
2019-01-31 05:13:23 -05:00
resource :users , requirements : API :: USER_REQUIREMENTS do
2017-06-29 13:20:59 -04:00
desc 'Get a user projects' do
success Entities :: BasicProjectDetails
end
params do
requires :user_id , type : String , desc : 'The ID or username of the user'
use :collection_params
use :statistics_params
2017-12-22 10:54:55 -05:00
use :with_custom_attributes
2013-02-08 10:33:15 -05:00
end
2017-06-29 13:20:59 -04:00
get " :user_id/projects " do
user = find_user ( params [ :user_id ] )
not_found! ( 'User' ) unless user
2013-02-08 10:33:15 -05:00
2017-06-29 13:20:59 -04:00
params [ :user ] = user
2019-12-12 22:07:50 -05:00
present_projects load_projects
2017-06-29 13:20:59 -04:00
end
2019-01-27 06:45:43 -05:00
2019-01-28 14:01:18 -05:00
desc 'Get projects starred by a user' do
2019-01-27 06:45:43 -05:00
success Entities :: BasicProjectDetails
end
params do
requires :user_id , type : String , desc : 'The ID or username of the user'
use :collection_params
use :statistics_params
end
get " :user_id/starred_projects " do
user = find_user ( params [ :user_id ] )
not_found! ( 'User' ) unless user
2019-02-02 14:48:27 -05:00
starred_projects = StarredProjectsFinder . new ( user , params : project_finder_params , current_user : current_user ) . execute
2019-12-12 22:07:50 -05:00
present_projects starred_projects
2019-01-27 06:45:43 -05:00
end
2017-06-29 13:20:59 -04:00
end
resource :projects do
2017-09-18 09:03:24 -04:00
include CustomAttributesEndpoints
2016-11-30 09:48:19 -05:00
desc 'Get a list of visible projects for authenticated user' do
2016-11-09 09:51:27 -05:00
success Entities :: BasicProjectDetails
end
params do
2016-11-22 11:58:10 -05:00
use :collection_params
2017-05-01 05:42:42 -04:00
use :statistics_params
2017-12-22 10:54:55 -05:00
use :with_custom_attributes
2016-11-09 09:51:27 -05:00
end
2012-06-29 06:46:01 -04:00
get do
2019-12-12 22:07:50 -05:00
present_projects load_projects
2013-11-18 07:15:59 -05:00
end
2016-11-09 09:51:27 -05:00
desc 'Create new project' do
success Entities :: Project
end
params do
2017-02-21 09:12:32 -05:00
optional :name , type : String , desc : 'The name of the project'
2016-11-09 09:51:27 -05:00
optional :path , type : String , desc : 'The path of the repository'
2017-02-21 09:12:32 -05:00
at_least_one_of :name , :path
2019-09-16 20:06:11 -04:00
use :optional_create_project_params
2016-11-09 09:51:27 -05:00
use :create_params
end
2012-08-31 03:15:37 -04:00
post do
2020-03-05 16:08:13 -05:00
Gitlab :: QueryLimiting . whitelist ( 'https://gitlab.com/gitlab-org/gitlab/issues/21139' )
2017-03-01 15:23:00 -05:00
attrs = declared_params ( include_missing : false )
2018-04-21 14:02:21 -04:00
attrs = translate_params_for_compatibility ( attrs )
2019-07-17 03:20:17 -04:00
filter_attributes_using_license! ( attrs )
2016-11-09 09:51:27 -05:00
project = :: Projects :: CreateService . new ( current_user , attrs ) . execute
if project . saved?
present project , with : Entities :: Project ,
2019-01-30 23:21:35 -05:00
user_can_admin_project : can? ( current_user , :admin_project , project ) ,
current_user : current_user
2012-08-31 03:15:37 -04:00
else
2016-11-09 09:51:27 -05:00
if project . errors [ :limit_reached ] . present?
error! ( project . errors [ :limit_reached ] , 403 )
2013-02-14 09:51:56 -05:00
end
2018-01-11 11:34:01 -05:00
2016-11-09 09:51:27 -05:00
render_validation_error! ( project )
2012-08-31 03:15:37 -04:00
end
end
2016-11-09 09:51:27 -05:00
desc 'Create new project for a specified user. Only available to admin users.' do
success Entities :: Project
end
params do
requires :name , type : String , desc : 'The name of the project'
requires :user_id , type : Integer , desc : 'The ID of a user'
2017-06-02 02:27:30 -04:00
optional :path , type : String , desc : 'The path of the repository'
2016-11-09 09:51:27 -05:00
optional :default_branch , type : String , desc : 'The default branch of the project'
2018-03-28 13:07:16 -04:00
use :optional_project_params
2019-11-22 19:06:06 -05:00
use :optional_create_project_params
2016-11-09 09:51:27 -05:00
use :create_params
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2012-11-14 15:37:52 -05:00
post " user/:user_id " do
2020-03-05 16:08:13 -05:00
Gitlab :: QueryLimiting . whitelist ( 'https://gitlab.com/gitlab-org/gitlab/issues/21139' )
2012-11-14 15:37:52 -05:00
authenticated_as_admin!
2016-11-09 09:51:27 -05:00
user = User . find_by ( id : params . delete ( :user_id ) )
not_found! ( 'User' ) unless user
2017-03-01 15:23:00 -05:00
attrs = declared_params ( include_missing : false )
2018-04-21 14:02:21 -04:00
attrs = translate_params_for_compatibility ( attrs )
2019-07-17 03:20:17 -04:00
filter_attributes_using_license! ( attrs )
2016-11-09 09:51:27 -05:00
project = :: Projects :: CreateService . new ( user , attrs ) . execute
if project . saved?
present project , with : Entities :: Project ,
2019-01-30 23:21:35 -05:00
user_can_admin_project : can? ( current_user , :admin_project , project ) ,
current_user : current_user
2012-11-14 15:37:52 -05:00
else
2016-11-09 09:51:27 -05:00
render_validation_error! ( project )
2012-11-14 15:37:52 -05:00
end
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2016-11-09 09:51:27 -05:00
end
2012-11-14 15:37:52 -05:00
2016-11-09 09:51:27 -05:00
params do
requires :id , type : String , desc : 'The ID of a project'
end
2018-11-08 07:18:17 -05:00
resource :projects , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
2016-11-09 09:51:27 -05:00
desc 'Get a single project' do
success Entities :: ProjectWithAccess
end
2017-05-01 05:42:42 -04:00
params do
use :statistics_params
2017-12-22 10:54:55 -05:00
use :with_custom_attributes
2018-10-26 11:12:14 -04:00
optional :license , type : Boolean , default : false ,
desc : 'Include project license data'
2017-05-01 05:42:42 -04:00
end
2016-11-09 09:51:27 -05:00
get " :id " do
2017-12-22 10:54:55 -05:00
options = {
with : current_user ? Entities :: ProjectWithAccess : Entities :: BasicProjectDetails ,
current_user : current_user ,
user_can_admin_project : can? ( current_user , :admin_project , user_project ) ,
2018-10-26 11:12:14 -04:00
statistics : params [ :statistics ] ,
license : params [ :license ]
2017-12-22 10:54:55 -05:00
}
project , options = with_custom_attributes ( user_project , options )
present project , options
2016-11-09 09:51:27 -05:00
end
desc 'Fork new project for the current user or provided namespace.' do
success Entities :: Project
end
params do
2020-03-09 08:07:45 -04:00
optional :namespace , type : String , desc : '(deprecated) The ID or name of the namespace that the project will be forked into'
optional :namespace_id , type : Integer , desc : 'The ID of the namespace that the project will be forked into'
optional :namespace_path , type : String , desc : 'The path of the namespace that the project will be forked into'
2019-02-18 09:17:29 -05:00
optional :path , type : String , desc : 'The path that will be assigned to the fork'
optional :name , type : String , desc : 'The name that will be assigned to the fork'
2016-11-09 09:51:27 -05:00
end
2017-02-02 12:57:34 -05:00
post ':id/fork' do
2019-09-18 10:02:45 -04:00
Gitlab :: QueryLimiting . whitelist ( 'https://gitlab.com/gitlab-org/gitlab-foss/issues/42284' )
2018-01-15 10:21:04 -05:00
2020-02-20 04:09:13 -05:00
not_found! unless can? ( current_user , :fork_project , user_project )
2016-11-09 09:51:27 -05:00
fork_params = declared_params ( include_missing : false )
2020-03-09 08:07:45 -04:00
fork_params [ :namespace ] =
if fork_params [ :namespace_id ] . present?
find_namespace! ( fork_params [ :namespace_id ] )
elsif fork_params [ :namespace_path ] . present?
find_namespace_by_path! ( fork_params [ :namespace_path ] )
elsif fork_params [ :namespace ] . present?
find_namespace! ( fork_params [ :namespace ] )
end
2016-09-06 04:52:42 -04:00
2020-02-20 04:09:13 -05:00
service = :: Projects :: ForkService . new ( user_project , current_user , fork_params )
2016-09-06 04:52:42 -04:00
2020-02-20 04:09:13 -05:00
not_found! ( 'Target Namespace' ) unless service . valid_fork_target?
2016-09-06 04:52:42 -04:00
2020-02-20 04:09:13 -05:00
forked_project = service . execute
2016-09-06 04:52:42 -04:00
2016-11-09 09:51:27 -05:00
if forked_project . errors . any?
conflict! ( forked_project . errors . messages )
2014-10-01 04:20:40 -04:00
else
2016-11-09 09:51:27 -05:00
present forked_project , with : Entities :: Project ,
2020-03-09 08:07:45 -04:00
user_can_admin_project : can? ( current_user , :admin_project , forked_project ) ,
current_user : current_user
2016-01-22 14:13:37 -05:00
end
2014-10-01 04:20:40 -04:00
end
2017-09-19 01:48:22 -04:00
desc 'List forks of this project' do
success Entities :: Project
end
params do
use :collection_params
2017-12-22 10:54:55 -05:00
use :with_custom_attributes
2017-09-19 01:48:22 -04:00
end
get ':id/forks' do
forks = ForkProjectsFinder . new ( user_project , params : project_finder_params , current_user : current_user ) . execute
2020-05-05 17:09:42 -04:00
present_projects forks , request_scope : user_project
2017-09-19 01:48:22 -04:00
end
2018-10-05 09:41:11 -04:00
desc 'Check pages access of this project'
get ':id/pages_access' do
authorize! :read_pages_content , user_project unless user_project . public_pages?
status 200
end
2016-11-09 09:51:27 -05:00
desc 'Update an existing project' do
success Entities :: Project
end
params do
optional :name , type : String , desc : 'The name of the project'
optional :default_branch , type : String , desc : 'The default branch of the project'
optional :path , type : String , desc : 'The path of the repository'
2017-04-05 12:31:15 -04:00
2018-03-28 13:07:16 -04:00
use :optional_project_params
2019-05-30 17:55:17 -04:00
use :optional_update_params_ee
2018-07-27 11:24:43 -04:00
2019-03-22 11:14:22 -04:00
at_least_one_of ( * Helpers :: ProjectsHelpers . update_params_at_least_one_of )
2016-11-09 09:51:27 -05:00
end
2014-10-15 02:57:35 -04:00
put ':id' do
authorize_admin_project
2017-03-01 15:23:00 -05:00
attrs = declared_params ( include_missing : false )
2014-10-15 02:57:35 -04:00
authorize! :rename_project , user_project if attrs [ :name ] . present?
2017-03-01 15:23:00 -05:00
authorize! :change_visibility_level , user_project if attrs [ :visibility ] . present?
2014-10-15 02:57:35 -04:00
2018-04-21 14:02:21 -04:00
attrs = translate_params_for_compatibility ( attrs )
2019-07-17 03:20:17 -04:00
filter_attributes_using_license! ( attrs )
2018-07-27 11:24:43 -04:00
verify_update_project_attrs! ( user_project , attrs )
2017-01-15 01:58:05 -05:00
result = :: Projects :: UpdateService . new ( user_project , current_user , attrs ) . execute
2014-10-15 02:57:35 -04:00
2017-01-15 01:58:05 -05:00
if result [ :status ] == :success
2016-01-11 09:27:20 -05:00
present user_project , with : Entities :: Project ,
2019-01-30 23:21:35 -05:00
user_can_admin_project : can? ( current_user , :admin_project , user_project ) ,
current_user : current_user
2017-01-15 01:58:05 -05:00
else
render_validation_error! ( user_project )
2014-10-15 02:57:35 -04:00
end
end
2016-11-09 09:51:27 -05:00
desc 'Archive a project' do
success Entities :: Project
end
2016-03-24 08:36:45 -04:00
post ':id/archive' do
2016-03-23 17:36:35 -04:00
authorize! ( :archive_project , user_project )
2018-08-02 15:39:46 -04:00
:: Projects :: UpdateService . new ( user_project , current_user , archived : true ) . execute
2016-03-23 17:36:35 -04:00
2019-01-30 23:21:35 -05:00
present user_project , with : Entities :: Project , current_user : current_user
2016-03-23 17:36:35 -04:00
end
2016-11-09 09:51:27 -05:00
desc 'Unarchive a project' do
success Entities :: Project
end
2016-03-24 08:36:45 -04:00
post ':id/unarchive' do
2016-03-23 17:36:35 -04:00
authorize! ( :archive_project , user_project )
2020-01-03 10:08:33 -05:00
:: Projects :: UpdateService . new ( user_project , current_user , archived : false ) . execute
2016-03-23 17:36:35 -04:00
2019-01-30 23:21:35 -05:00
present user_project , with : Entities :: Project , current_user : current_user
2016-03-23 17:36:35 -04:00
end
2016-11-09 09:51:27 -05:00
desc 'Star a project' do
success Entities :: Project
end
2016-04-06 09:52:16 -04:00
post ':id/star' do
2016-04-12 12:52:43 -04:00
if current_user . starred? ( user_project )
not_modified!
else
2016-04-06 09:52:16 -04:00
current_user . toggle_star ( user_project )
2019-04-08 09:33:36 -04:00
user_project . reset
2016-04-13 06:50:00 -04:00
2019-01-30 23:21:35 -05:00
present user_project , with : Entities :: Project , current_user : current_user
2016-04-06 09:52:16 -04:00
end
end
2016-11-09 09:51:27 -05:00
desc 'Unstar a project' do
success Entities :: Project
end
2017-02-20 09:14:48 -05:00
post ':id/unstar' do
2016-04-06 09:52:16 -04:00
if current_user . starred? ( user_project )
current_user . toggle_star ( user_project )
2019-04-08 09:33:36 -04:00
user_project . reset
2016-04-13 06:50:00 -04:00
2019-01-30 23:21:35 -05:00
present user_project , with : Entities :: Project , current_user : current_user
2016-04-06 09:52:16 -04:00
else
not_modified!
end
end
2019-01-28 14:01:18 -05:00
desc 'Get the users who starred a project' do
2019-01-25 12:34:45 -05:00
success Entities :: UserBasic
end
params do
2019-01-28 14:01:18 -05:00
optional :search , type : String , desc : 'Return list of users matching the search criteria'
use :pagination
2019-01-25 12:34:45 -05:00
end
get ':id/starrers' do
2019-02-02 14:53:21 -05:00
starrers = UsersStarProjectsFinder . new ( user_project , params , current_user : current_user ) . execute
2019-01-25 12:34:45 -05:00
2019-02-02 14:48:27 -05:00
present paginate ( starrers ) , with : Entities :: UserStarsProject
2019-01-25 12:34:45 -05:00
end
2018-04-13 04:06:04 -04:00
desc 'Get languages in project repository'
get ':id/languages' do
2019-03-20 13:23:23 -04:00
:: Projects :: RepositoryLanguagesService
. new ( user_project , current_user )
. execute . map { | lang | [ lang . name , lang . share ] } . to_h
2018-04-13 04:06:04 -04:00
end
2020-08-12 17:09:54 -04:00
desc 'Delete a project'
2013-10-09 07:41:41 -04:00
delete " :id " do
authorize! :remove_project , user_project
2017-03-01 08:35:48 -05:00
2019-12-17 10:08:15 -05:00
delete_project ( user_project )
2013-10-09 07:41:41 -04:00
end
2012-11-14 15:37:52 -05:00
2016-11-09 09:51:27 -05:00
desc 'Mark this project as forked from another'
params do
requires :forked_from_id , type : String , desc : 'The ID of the project it was forked from'
end
2013-06-27 17:49:26 -04:00
post " :id/fork/:forked_from_id " do
2018-03-30 08:16:24 -04:00
authorize! :admin_project , user_project
2016-11-09 09:51:27 -05:00
2017-12-07 03:44:55 -05:00
fork_from_project = find_project! ( params [ :forked_from_id ] )
2016-11-09 09:51:27 -05:00
2017-12-07 03:44:55 -05:00
not_found! ( " Source Project " ) unless fork_from_project
2017-08-14 09:22:09 -04:00
2020-05-27 17:08:05 -04:00
authorize! :fork_project , fork_from_project
2017-12-07 03:44:55 -05:00
result = :: Projects :: ForkService . new ( fork_from_project , current_user ) . execute ( user_project )
if result
2019-04-08 09:33:36 -04:00
present user_project . reset , with : Entities :: Project , current_user : current_user
2013-06-27 17:49:26 -04:00
else
2017-12-07 03:44:55 -05:00
render_api_error! ( " Project already forked " , 409 ) if user_project . forked?
2013-06-27 17:49:26 -04:00
end
end
2016-11-09 09:51:27 -05:00
desc 'Remove a forked_from relationship'
2013-06-27 17:49:26 -04:00
delete " :id/fork " do
2015-10-13 18:04:22 -04:00
authorize! :remove_fork_project , user_project
2016-11-09 09:51:27 -05:00
2017-12-07 03:44:55 -05:00
result = destroy_conditionally! ( user_project ) do
:: Projects :: UnlinkForkService . new ( user_project , current_user ) . execute
2013-06-27 17:49:26 -04:00
end
2017-12-07 03:44:55 -05:00
2020-01-16 13:08:46 -05:00
not_modified! unless result
2013-06-27 17:49:26 -04:00
end
2016-01-07 07:37:14 -05:00
2016-11-09 09:51:27 -05:00
desc 'Share the project with a group' do
success Entities :: ProjectGroupLink
end
params do
requires :group_id , type : Integer , desc : 'The ID of a group'
2019-02-12 07:29:47 -05:00
requires :group_access , type : Integer , values : Gitlab :: Access . values , as : :link_group_access , desc : 'The group access level'
2016-11-09 09:51:27 -05:00
optional :expires_at , type : Date , desc : 'Share expiration date'
end
2016-03-13 06:46:16 -04:00
post " :id/share " do
authorize! :admin_project , user_project
2016-11-09 09:51:27 -05:00
group = Group . find_by_id ( params [ :group_id ] )
2016-10-11 06:20:35 -04:00
2016-03-13 06:46:16 -04:00
unless user_project . allowed_to_share_with_group?
2018-04-18 05:19:40 -04:00
break render_api_error! ( " The project sharing with group is disabled " , 400 )
2016-03-13 06:46:16 -04:00
end
2019-02-12 07:29:47 -05:00
result = :: Projects :: GroupLinks :: CreateService . new ( user_project , current_user , declared_params ( include_missing : false ) )
. execute ( group )
2016-09-22 16:31:18 -04:00
2019-02-12 07:29:47 -05:00
if result [ :status ] == :success
present result [ :link ] , with : Entities :: ProjectGroupLink
2016-03-13 06:46:16 -04:00
else
2019-02-12 07:29:47 -05:00
render_api_error! ( result [ :message ] , result [ :http_status ] )
2016-03-13 06:46:16 -04:00
end
end
2016-11-22 05:23:41 -05:00
params do
requires :group_id , type : Integer , desc : 'The ID of the group'
2016-01-07 07:37:14 -05:00
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2016-11-22 05:23:41 -05:00
delete " :id/share/:group_id " do
authorize! :admin_project , user_project
link = user_project . project_group_links . find_by ( group_id : params [ :group_id ] )
not_found! ( 'Group Link' ) unless link
2016-01-07 07:37:14 -05:00
2020-06-03 02:08:34 -04:00
destroy_conditionally! ( link ) do
:: Projects :: GroupLinks :: DestroyService . new ( user_project , current_user ) . execute ( link )
end
2016-11-22 05:23:41 -05:00
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2014-12-19 07:27:27 -05:00
2016-11-09 09:51:27 -05:00
desc 'Upload a file'
params do
2019-09-18 10:02:45 -04:00
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
2019-09-10 12:24:10 -04:00
requires :file , type : File , desc : 'The file to be uploaded' # rubocop:disable Scalability/FileUploads
2016-11-09 09:51:27 -05:00
end
2016-01-07 07:37:14 -05:00
post " :id/uploads " do
2020-02-28 10:09:13 -05:00
upload = UploadService . new ( user_project , params [ :file ] ) . execute
present upload , with : Entities :: ProjectUpload
2013-09-22 00:50:18 -04:00
end
2014-02-13 09:08:26 -05:00
2016-11-09 09:51:27 -05:00
desc 'Get the users list of a project' do
success Entities :: UserBasic
end
params do
optional :search , type : String , desc : 'Return list of users matching the search criteria'
2020-06-29 17:09:07 -04:00
optional :skip_users , type : Array [ Integer ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToIntegerArray . coerce , desc : 'Filter out users with the specified IDs'
2016-11-09 09:51:27 -05:00
use :pagination
2013-09-22 00:50:18 -04:00
end
2014-02-13 09:08:26 -05:00
get ':id/users' do
2017-04-11 17:07:46 -04:00
users = DeclarativePolicy . subject_scope { user_project . team . users }
2016-11-09 09:51:27 -05:00
users = users . search ( params [ :search ] ) if params [ :search ] . present?
2019-08-16 10:11:30 -04:00
users = users . where_not_in ( params [ :skip_users ] ) if params [ :skip_users ] . present?
2016-11-09 09:51:27 -05:00
present paginate ( users ) , with : Entities :: UserBasic
2014-02-13 09:08:26 -05:00
end
2017-02-21 09:51:31 -05:00
desc 'Start the housekeeping task for a project' do
detail 'This feature was introduced in GitLab 9.0.'
end
post ':id/housekeeping' do
authorize_admin_project
begin
2019-07-03 03:13:00 -04:00
:: Projects :: HousekeepingService . new ( user_project , :gc ) . execute
2017-02-21 09:51:31 -05:00
rescue :: Projects :: HousekeepingService :: LeaseTaken = > error
conflict! ( error . message )
end
2014-02-13 09:08:26 -05:00
end
2018-06-24 02:10:15 -04:00
desc 'Transfer a project to a new namespace'
params do
requires :namespace , type : String , desc : 'The ID or path of the new namespace'
end
put " :id/transfer " do
authorize! :change_namespace , user_project
namespace = find_namespace! ( params [ :namespace ] )
result = :: Projects :: TransferService . new ( user_project , current_user ) . execute ( namespace )
if result
2019-01-30 23:21:35 -05:00
present user_project , with : Entities :: Project , current_user : current_user
2018-06-24 02:10:15 -04:00
else
render_api_error! ( " Failed to transfer project #{ user_project . errors . messages } " , 400 )
end
end
2012-06-29 06:46:01 -04:00
end
end
end
2019-09-13 09:26:31 -04:00
API :: Projects . prepend_if_ee ( 'EE::API::Projects' )