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
|
2012-06-29 06:46:01 -04:00
|
|
|
class Projects < Grape::API
|
2016-11-09 09:51:27 -05:00
|
|
|
include PaginationParams
|
2017-12-22 10:54:55 -05:00
|
|
|
include Helpers::CustomAttributes
|
2018-03-28 13:07:16 -04:00
|
|
|
include 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
|
|
|
|
params :optional_filter_params_ee do
|
|
|
|
# EE::API::Projects would override this helper
|
|
|
|
end
|
|
|
|
|
2018-07-27 11:24:43 -04:00
|
|
|
params :optional_update_params_ee do
|
|
|
|
# EE::API::Projects would override this helper
|
|
|
|
end
|
|
|
|
|
2018-07-19 14:32:12 -04:00
|
|
|
# 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]
|
|
|
|
|
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)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.update_params_at_least_one_of
|
|
|
|
[
|
|
|
|
:jobs_enabled,
|
|
|
|
:resolve_outdated_diff_discussions,
|
|
|
|
:ci_config_path,
|
|
|
|
:container_registry_enabled,
|
|
|
|
:default_branch,
|
|
|
|
:description,
|
|
|
|
:issues_enabled,
|
|
|
|
:lfs_enabled,
|
|
|
|
:merge_requests_enabled,
|
|
|
|
:merge_method,
|
|
|
|
:name,
|
|
|
|
:only_allow_merge_if_all_discussions_are_resolved,
|
|
|
|
:only_allow_merge_if_pipeline_succeeds,
|
|
|
|
:path,
|
|
|
|
:printing_merge_request_link_enabled,
|
|
|
|
:public_builds,
|
|
|
|
:request_access_enabled,
|
|
|
|
:shared_runners_enabled,
|
|
|
|
:snippets_enabled,
|
|
|
|
:tag_list,
|
|
|
|
:visibility,
|
|
|
|
:wiki_enabled,
|
|
|
|
:avatar
|
|
|
|
]
|
2018-07-19 14:32:12 -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
|
|
|
|
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'
|
|
|
|
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'
|
|
|
|
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'
|
2018-07-19 14:32:12 -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'
|
|
|
|
end
|
|
|
|
|
2017-09-19 01:48:22 -04:00
|
|
|
def load_projects
|
|
|
|
ProjectsFinder.new(current_user: current_user, params: project_finder_params).execute
|
|
|
|
end
|
|
|
|
|
|
|
|
def present_projects(projects, options = {})
|
2017-06-29 13:20:59 -04:00
|
|
|
projects = reorder_projects(projects)
|
2018-07-19 14:32:12 -04:00
|
|
|
projects = apply_filters(projects)
|
2017-11-27 06:24:33 -05:00
|
|
|
projects = paginate(projects)
|
2017-12-22 10:54:55 -05:00
|
|
|
projects, options = with_custom_attributes(projects, options)
|
2017-06-29 13:20:59 -04:00
|
|
|
|
|
|
|
options = options.reverse_merge(
|
|
|
|
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
|
|
|
|
statistics: params[:statistics],
|
2018-10-26 11:12:14 -04:00
|
|
|
current_user: current_user,
|
|
|
|
license: false
|
2017-06-29 13:20:59 -04:00
|
|
|
)
|
|
|
|
options[:with] = Entities::BasicProjectDetails if params[:simple]
|
|
|
|
|
2017-11-30 06:52:38 -05:00
|
|
|
present options[:with].prepare_relation(projects, options), 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
|
|
|
|
|
2017-09-19 01:48:22 -04:00
|
|
|
present_projects load_projects
|
2017-06-29 13:20:59 -04:00
|
|
|
end
|
|
|
|
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
|
2017-09-19 01:48:22 -04: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
|
2018-03-28 13:07:16 -04:00
|
|
|
use :optional_project_params
|
2016-11-09 09:51:27 -05:00
|
|
|
use :create_params
|
|
|
|
end
|
2012-08-31 03:15:37 -04:00
|
|
|
post do
|
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)
|
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
|
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
|
|
|
|
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)
|
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
|
|
|
|
optional :namespace, type: String, desc: 'The ID or name 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
|
2018-01-15 10:21:04 -05:00
|
|
|
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42284')
|
|
|
|
|
2016-11-09 09:51:27 -05:00
|
|
|
fork_params = declared_params(include_missing: false)
|
|
|
|
namespace_id = fork_params[:namespace]
|
2016-09-06 04:52:42 -04:00
|
|
|
|
2016-09-05 20:31:06 -04:00
|
|
|
if namespace_id.present?
|
2018-03-26 05:22:03 -04:00
|
|
|
fork_params[:namespace] = find_namespace(namespace_id)
|
2016-09-06 04:52:42 -04:00
|
|
|
|
2016-11-09 09:51:27 -05:00
|
|
|
unless fork_params[:namespace] && can?(current_user, :create_projects, fork_params[:namespace])
|
2016-09-21 10:40:46 -04:00
|
|
|
not_found!('Target Namespace')
|
|
|
|
end
|
2016-09-05 20:31:06 -04:00
|
|
|
end
|
2016-09-06 04:52:42 -04:00
|
|
|
|
2016-11-09 09:51:27 -05:00
|
|
|
forked_project = ::Projects::ForkService.new(user_project, current_user, fork_params).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,
|
2019-01-30 23:21:35 -05: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
|
|
|
|
|
|
|
|
present_projects forks
|
|
|
|
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
|
2018-07-27 11:24:43 -04:00
|
|
|
|
|
|
|
at_least_one_of(*::API::Projects.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)
|
2014-10-15 02:57:35 -04:00
|
|
|
|
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)
|
|
|
|
|
2018-08-02 15:39:46 -04:00
|
|
|
::Projects::UpdateService.new(@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)
|
|
|
|
user_project.reload
|
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)
|
|
|
|
user_project.reload
|
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
|
|
|
|
|
2018-04-13 04:06:04 -04:00
|
|
|
desc 'Get languages in project repository'
|
|
|
|
get ':id/languages' do
|
2019-02-25 02:57:34 -05:00
|
|
|
if user_project.repository_languages.present?
|
|
|
|
user_project.repository_languages.map { |l| [l.name, l.share] }.to_h
|
|
|
|
else
|
|
|
|
user_project.repository.languages.map { |language| language.values_at(:label, :value) }.to_h
|
|
|
|
end
|
2018-04-13 04:06:04 -04:00
|
|
|
end
|
|
|
|
|
2016-11-09 09:51:27 -05:00
|
|
|
desc 'Remove 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
|
|
|
|
2017-03-02 07:14:13 -05:00
|
|
|
destroy_conditionally!(user_project) do
|
|
|
|
::Projects::DestroyService.new(user_project, current_user, {}).async_execute
|
|
|
|
end
|
2017-02-22 12:37:13 -05:00
|
|
|
|
|
|
|
accepted!
|
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
|
|
|
|
2017-12-07 03:44:55 -05:00
|
|
|
result = ::Projects::ForkService.new(fork_from_project, current_user).execute(user_project)
|
|
|
|
|
|
|
|
if result
|
2019-01-30 23:21:35 -05:00
|
|
|
present user_project.reload, 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
|
|
|
|
|
|
|
result ? status(204) : not_modified!
|
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
|
|
|
|
2017-08-28 11:13:22 -04:00
|
|
|
destroy_conditionally!(link)
|
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
|
|
|
|
requires :file, type: File, desc: 'The file to be uploaded'
|
|
|
|
end
|
2016-01-07 07:37:14 -05:00
|
|
|
post ":id/uploads" do
|
2018-12-30 22:23:50 -05:00
|
|
|
UploadService.new(user_project, params[:file]).execute.to_h
|
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'
|
|
|
|
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?
|
|
|
|
|
|
|
|
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
|
|
|
|
::Projects::HousekeepingService.new(user_project).execute
|
|
|
|
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
|