2018-09-29 18:34:47 -04:00
# frozen_string_literal: true
2013-05-14 08:33:31 -04:00
module API
2020-10-14 20:08:42 -04:00
class Issues < :: API :: Base
2016-11-07 09:15:14 -05:00
include PaginationParams
2019-04-08 07:17:22 -04:00
helpers Helpers :: IssuesHelpers
2022-03-10 22:08:14 -05:00
helpers SpammableActions :: CaptchaCheck :: RestApiActionsSupport
2016-11-07 09:15:14 -05:00
2018-05-15 10:41:33 -04:00
before { authenticate_non_get! }
2012-07-24 08:19:51 -04:00
2021-10-27 11:13:41 -04:00
feature_category :team_planning
2022-05-13 11:07:43 -04:00
urgency :low
2020-10-29 14:09:11 -04:00
2014-08-14 06:41:16 -04:00
helpers do
2019-09-17 08:06:48 -04:00
params :negatable_issue_filter_params do
2020-06-29 17:09:07 -04:00
optional :labels , type : Array [ String ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToArray . coerce , desc : 'Comma-separated list of label names'
2016-10-26 04:08:58 -04:00
optional :milestone , type : String , desc : 'Milestone title'
2021-09-02 05:11:35 -04:00
optional :milestone_id , types : String , values : %w[ Any None Upcoming Started ] ,
desc : 'Return issues assigned to milestones without the specified timebox value ("Any", "None", "Upcoming" or "Started")'
mutually_exclusive :milestone_id , :milestone
2020-06-29 17:09:07 -04:00
optional :iids , type : Array [ Integer ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToIntegerArray . coerce , desc : 'The IID array of issues'
2021-03-08 16:09:45 -05:00
optional :author_id , type : Integer , desc : 'Return issues which are not authored by the user with the given ID'
optional :author_username , type : String , desc : 'Return issues which are not authored by the user with the given username'
mutually_exclusive :author_id , :author_username
optional :assignee_id , type : Integer , desc : 'Return issues which are not assigned to the user with the given ID'
optional :assignee_username , type : Array [ String ] , check_assignees_count : true ,
coerce_with : Validations :: Validators :: CheckAssigneesCount . coerce ,
desc : 'Return issues which are not assigned to the user with the given username'
mutually_exclusive :assignee_id , :assignee_username
use :negatable_issue_filter_params_ee
end
params :issues_stats_params do
optional :labels , type : Array [ String ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToArray . coerce , desc : 'Comma-separated list of label names'
optional :milestone , type : String , desc : 'Milestone title'
2021-09-02 05:11:35 -04:00
# 'milestone_id' only accepts wildcard values 'Any', 'None', 'Upcoming', 'Started'
# the param has '_id' in the name to keep consistency (ex. assignee_id accepts id and wildcard values).
optional :milestone_id , types : String , values : %w[ Any None Upcoming Started ] ,
desc : 'Return issues assigned to milestones with the specified timebox value ("Any", "None", "Upcoming" or "Started")'
2021-03-08 16:09:45 -05:00
optional :iids , type : Array [ Integer ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToIntegerArray . coerce , desc : 'The IID array of issues'
2019-02-05 03:32:27 -05:00
optional :search , type : String , desc : 'Search issues for text present in the title, description, or any combination of these'
optional :in , type : String , desc : '`title`, `description`, or a string joining them with comma'
2021-09-02 05:11:35 -04:00
mutually_exclusive :milestone_id , :milestone
2019-04-24 09:08:14 -04:00
2017-07-20 16:44:48 -04:00
optional :author_id , type : Integer , desc : 'Return issues which are authored by the user with the given ID'
2019-04-08 07:17:22 -04:00
optional :author_username , type : String , desc : 'Return issues which are authored by the user with the given username'
2019-04-24 09:08:14 -04:00
mutually_exclusive :author_id , :author_username
2018-10-25 10:20:06 -04:00
optional :assignee_id , types : [ Integer , String ] , integer_none_any : true ,
2019-09-17 08:06:48 -04:00
desc : 'Return issues which are assigned to the user with the given ID'
2019-04-24 09:08:14 -04:00
optional :assignee_username , type : Array [ String ] , check_assignees_count : true ,
2020-04-02 08:08:18 -04:00
coerce_with : Validations :: Validators :: CheckAssigneesCount . coerce ,
2019-09-17 08:06:48 -04:00
desc : 'Return issues which are assigned to the user with the given username'
2019-04-24 09:08:14 -04:00
mutually_exclusive :assignee_id , :assignee_username
2020-11-05 22:09:19 -05:00
2019-09-17 08:06:48 -04:00
optional :created_after , type : DateTime , desc : 'Return issues created after the specified time'
optional :created_before , type : DateTime , desc : 'Return issues created before the specified time'
optional :updated_after , type : DateTime , desc : 'Return issues updated after the specified time'
optional :updated_before , type : DateTime , desc : 'Return issues updated before the specified time'
optional :not , type : Hash do
use :negatable_issue_filter_params
end
2019-04-24 09:08:14 -04:00
2018-05-13 22:07:53 -04:00
optional :scope , type : String , values : %w[ created-by-me assigned-to-me created_by_me assigned_to_me all ] ,
desc : 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
2017-09-03 03:34:50 -04:00
optional :my_reaction_emoji , type : String , desc : 'Return issues reacted by the authenticated user by the given emoji'
2019-02-25 06:00:24 -05:00
optional :confidential , type : Boolean , desc : 'Filter confidential or public issues'
2018-10-30 08:24:34 -04:00
2021-03-08 16:09:45 -05:00
use :issues_stats_params_ee
2016-11-07 09:15:14 -05:00
end
2016-11-10 05:23:44 -05:00
2019-04-24 09:08:14 -04:00
params :issues_params do
2019-12-30 07:09:15 -05:00
optional :with_labels_details , type : Boolean , desc : 'Return titles of labels and other details' , default : false
2019-04-24 09:08:14 -04:00
optional :state , type : String , values : %w[ opened closed all ] , default : 'all' ,
desc : 'Return opened, closed, or all issues'
2019-08-15 06:56:33 -04:00
optional :order_by , type : String , values : Helpers :: IssuesHelpers . sort_options , default : 'created_at' ,
2021-09-09 05:11:16 -04:00
desc : 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
2019-04-24 09:08:14 -04:00
optional :sort , type : String , values : %w[ asc desc ] , default : 'desc' ,
desc : 'Return issues sorted in `asc` or `desc` order.'
2022-01-24 13:14:42 -05:00
optional :due_date , type : String , values : %w[ 0 any today tomorrow overdue week month next_month_and_previous_two_weeks ] << '' ,
2020-08-12 14:31:49 -04:00
desc : 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
2021-12-22 07:16:22 -05:00
optional :issue_type , type : String , values : WorkItems :: Type . allowed_types_for_issues , desc : " The type of the issue. Accepts: #{ WorkItems :: Type . allowed_types_for_issues . join ( ', ' ) } "
2019-04-24 09:08:14 -04:00
use :issues_stats_params
use :pagination
end
2018-10-30 08:24:34 -04:00
params :issue_params do
2016-11-07 09:15:14 -05:00
optional :description , type : String , desc : 'The description of an issue'
2020-06-29 17:09:07 -04:00
optional :assignee_ids , type : Array [ Integer ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToIntegerArray . coerce , desc : 'The array of user IDs to assign issue'
2017-05-04 08:11:15 -04:00
optional :assignee_id , type : Integer , desc : '[Deprecated] The ID of a user to assign issue'
2016-11-07 09:15:14 -05:00
optional :milestone_id , type : Integer , desc : 'The ID of a milestone to assign issue'
2020-06-29 17:09:07 -04:00
optional :labels , type : Array [ String ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToArray . coerce , desc : 'Comma-separated list of label names'
optional :add_labels , type : Array [ String ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToArray . coerce , desc : 'Comma-separated list of label names'
optional :remove_labels , type : Array [ String ] , coerce_with : :: API :: Validations :: Types :: CommaSeparatedToArray . coerce , desc : 'Comma-separated list of label names'
2017-04-12 07:19:45 -04:00
optional :due_date , type : String , desc : 'Date string in the format YEAR-MONTH-DAY'
2016-11-07 09:15:14 -05:00
optional :confidential , type : Boolean , desc : 'Boolean parameter if the issue should be confidential'
2017-09-01 08:03:57 -04:00
optional :discussion_locked , type : Boolean , desc : " Boolean parameter indicating if the issue's discussion is locked "
2021-12-22 07:16:22 -05:00
optional :issue_type , type : String , values : WorkItems :: Type . allowed_types_for_issues , desc : " The type of the issue. Accepts: #{ WorkItems :: Type . allowed_types_for_issues . join ( ', ' ) } "
2017-04-05 12:31:15 -04:00
2019-05-29 06:28:11 -04:00
use :optional_issue_params_ee
2017-04-05 12:31:15 -04:00
end
2014-08-14 06:41:16 -04:00
end
2019-04-08 07:17:22 -04:00
desc " Get currently authenticated user's issues statistics "
params do
2019-04-24 09:08:14 -04:00
use :issues_stats_params
2019-05-17 05:46:33 -04:00
optional :scope , type : String , values : %w[ created_by_me assigned_to_me all ] , default : 'created_by_me' ,
2019-04-08 07:17:22 -04:00
desc : 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
end
get '/issues_statistics' do
authenticate! unless params [ :scope ] == 'all'
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if params [ :search ] . present?
2019-04-08 07:17:22 -04:00
2019-05-17 05:46:33 -04:00
present issues_statistics , with : Grape :: Presenters :: Presenter
2019-04-08 07:17:22 -04:00
end
2012-07-24 08:19:51 -04:00
resource :issues do
2016-11-07 09:15:14 -05:00
desc " Get currently authenticated user's issues " do
2019-04-19 03:55:36 -04:00
success Entities :: Issue
2016-11-07 09:15:14 -05:00
end
params do
use :issues_params
2018-05-13 22:07:53 -04:00
optional :scope , type : String , values : %w[ created-by-me assigned-to-me created_by_me assigned_to_me all ] , default : 'created_by_me' ,
desc : 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
2020-04-28 14:09:35 -04:00
optional :non_archived , type : Boolean , default : true ,
desc : 'Return issues from non archived projects'
2016-11-07 09:15:14 -05:00
end
2012-07-24 08:19:51 -04:00
get do
2018-05-15 10:41:33 -04:00
authenticate! unless params [ :scope ] == 'all'
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if params [ :search ] . present?
2017-11-07 09:00:21 -05:00
issues = paginate ( find_issues )
2016-09-09 10:16:14 -04:00
2017-08-28 20:02:26 -04:00
options = {
2019-04-19 03:55:36 -04:00
with : Entities :: Issue ,
2019-05-17 05:46:33 -04:00
with_labels_details : declared_params [ :with_labels_details ] ,
2017-08-28 20:02:26 -04:00
current_user : current_user ,
2019-08-17 18:39:39 -04:00
include_subscribed : false
2017-08-28 20:02:26 -04:00
}
2017-08-21 18:42:03 -04:00
2017-11-07 09:00:21 -05:00
present issues , options
2012-07-24 08:19:51 -04:00
end
2020-08-25 11:10:17 -04:00
desc " Get specified issue (admin only) " do
success Entities :: Issue
end
params do
requires :id , type : String , desc : 'The ID of the Issue'
end
get " :id " do
authenticated_as_admin!
issue = Issue . find ( params [ 'id' ] )
present issue , with : Entities :: Issue , current_user : current_user , project : issue . project
end
2012-07-24 08:19:51 -04:00
end
2016-11-07 09:15:14 -05:00
params do
requires :id , type : String , desc : 'The ID of a group'
end
2018-11-08 07:18:17 -05:00
resource :groups , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
2016-11-07 09:15:14 -05:00
desc 'Get a list of group issues' do
2019-04-19 03:55:36 -04:00
success Entities :: Issue
2016-11-07 09:15:14 -05:00
end
params do
use :issues_params
2020-02-05 13:09:06 -05:00
optional :non_archived , type : Boolean , desc : 'Return issues from non archived projects' , default : true
2016-11-07 09:15:14 -05:00
end
2016-06-07 18:01:54 -04:00
get " :id/issues " do
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if declared_params [ :search ] . present?
2019-12-27 10:08:16 -05:00
issues = paginate ( find_issues ( group_id : user_group . id , include_subgroups : true ) )
2016-09-09 10:16:14 -04:00
2017-08-28 20:02:26 -04:00
options = {
2019-04-19 03:55:36 -04:00
with : Entities :: Issue ,
2019-05-17 05:46:33 -04:00
with_labels_details : declared_params [ :with_labels_details ] ,
2017-08-28 20:02:26 -04:00
current_user : current_user ,
2019-12-27 10:08:16 -05:00
include_subscribed : false ,
group : user_group
2017-08-28 20:02:26 -04:00
}
2017-08-21 18:42:03 -04:00
2017-11-07 09:00:21 -05:00
present issues , options
2016-06-07 18:01:54 -04:00
end
2019-04-08 07:17:22 -04:00
desc 'Get statistics for the list of group issues'
params do
2019-04-24 09:08:14 -04:00
use :issues_stats_params
2019-04-08 07:17:22 -04:00
end
get " :id/issues_statistics " do
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if declared_params [ :search ] . present?
2019-12-27 10:08:16 -05:00
present issues_statistics ( group_id : user_group . id , include_subgroups : true ) , with : Grape :: Presenters :: Presenter
2019-04-08 07:17:22 -04:00
end
2016-06-07 18:01:54 -04:00
end
2016-11-10 05:23:44 -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
2017-01-18 11:48:16 -05:00
include TimeTrackingEndpoints
2016-11-07 09:15:14 -05:00
desc 'Get a list of project issues' do
2019-04-19 03:55:36 -04:00
success Entities :: Issue
2016-11-07 09:15:14 -05:00
end
params do
use :issues_params
end
2012-07-24 08:19:51 -04:00
get " :id/issues " do
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if declared_params [ :search ] . present?
2019-12-27 10:08:16 -05:00
issues = paginate ( find_issues ( project_id : user_project . id ) )
2017-01-04 03:23:46 -05:00
2017-08-28 20:02:26 -04:00
options = {
2019-04-19 03:55:36 -04:00
with : Entities :: Issue ,
2019-05-17 05:46:33 -04:00
with_labels_details : declared_params [ :with_labels_details ] ,
2017-08-28 20:02:26 -04:00
current_user : current_user ,
project : user_project ,
2019-08-23 19:38:01 -04:00
include_subscribed : false
2017-08-28 20:02:26 -04:00
}
2017-08-21 18:42:03 -04:00
2017-11-07 09:00:21 -05:00
present issues , options
2012-07-24 08:19:51 -04:00
end
2019-04-08 07:17:22 -04:00
desc 'Get statistics for the list of project issues'
params do
2019-04-24 09:08:14 -04:00
use :issues_stats_params
2019-04-08 07:17:22 -04:00
end
get " :id/issues_statistics " do
2021-09-21 11:12:11 -04:00
validate_anonymous_search_access! if declared_params [ :search ] . present?
2019-12-27 10:08:16 -05:00
present issues_statistics ( project_id : user_project . id ) , with : Grape :: Presenters :: Presenter
2019-04-08 07:17:22 -04:00
end
2016-11-07 09:15:14 -05:00
desc 'Get a single project issue' do
success Entities :: Issue
end
params do
2017-02-25 03:44:09 -05:00
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
2016-11-07 09:15:14 -05:00
end
2017-07-25 05:35:45 -04:00
get " :id/issues/:issue_iid " , as : :api_v4_project_issue do
2017-02-25 03:44:09 -05:00
issue = find_project_issue ( params [ :issue_iid ] )
2016-11-07 09:15:14 -05:00
present issue , with : Entities :: Issue , current_user : current_user , project : user_project
2012-07-24 08:19:51 -04:00
end
2016-11-07 09:15:14 -05:00
desc 'Create a new project issue' do
success Entities :: Issue
end
params do
requires :title , type : String , desc : 'The title of an issue'
optional :created_at , type : DateTime ,
desc : 'Date time when the issue was created. Available only for admins and project owners.'
2017-03-10 03:19:12 -05:00
optional :merge_request_to_resolve_discussions_of , type : Integer ,
2016-11-07 09:15:14 -05:00
desc : 'The IID of a merge request for which to resolve discussions'
2016-12-22 07:31:12 -05:00
optional :discussion_to_resolve , type : String ,
2017-03-10 03:19:12 -05:00
desc : 'The ID of a discussion to resolve, also pass `merge_request_to_resolve_discussions_of`'
2018-08-01 05:03:14 -04:00
optional :iid , type : Integer ,
desc : 'The internal ID of a project issue. Available only for admins and project owners.'
2016-11-07 09:15:14 -05:00
use :issue_params
end
2016-07-12 11:59:21 -04:00
post ':id/issues' do
2021-04-08 14:09:32 -04:00
Gitlab :: QueryLimiting . disable! ( 'https://gitlab.com/gitlab-org/gitlab/-/issues/21140' )
2018-01-15 10:21:04 -05:00
2017-11-22 12:24:11 -05:00
authorize! :create_issue , user_project
2016-11-07 09:15:14 -05:00
issue_params = declared_params ( include_missing : false )
2016-12-06 11:13:14 -05:00
2017-05-04 08:11:15 -04:00
issue_params = convert_parameters_from_legacy_format ( issue_params )
2020-01-14 10:07:55 -05:00
begin
2021-06-21 08:07:45 -04:00
spam_params = :: Spam :: SpamParams . new_from_request ( request : request )
2021-05-11 23:10:21 -04:00
issue = :: Issues :: CreateService . new ( project : user_project ,
current_user : current_user ,
2021-06-21 08:07:45 -04:00
params : issue_params ,
spam_params : spam_params ) . execute
2020-01-14 10:07:55 -05:00
if issue . valid?
present issue , with : Entities :: Issue , current_user : current_user , project : user_project
else
2022-03-10 22:08:14 -05:00
with_captcha_check_rest_api ( spammable : issue ) do
render_validation_error! ( issue )
end
2020-01-14 10:07:55 -05:00
end
rescue :: ActiveRecord :: RecordNotUnique
render_api_error! ( 'Duplicated issue' , 409 )
2012-07-24 08:19:51 -04:00
end
end
2016-11-10 05:23:44 -05:00
desc 'Update an existing issue' do
success Entities :: Issue
end
params do
2017-02-25 03:44:09 -05:00
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
2016-11-07 09:15:14 -05:00
optional :title , type : String , desc : 'The title of an issue'
optional :updated_at , type : DateTime ,
2020-02-25 04:09:10 -05:00
allow_blank : false ,
2016-11-07 09:15:14 -05:00
desc : 'Date time when the issue was updated. Available only for admins and project owners.'
2016-12-22 03:41:53 -05:00
optional :state_event , type : String , values : %w[ reopen close ] , desc : 'State of the issue'
2016-11-07 09:15:14 -05:00
use :issue_params
2019-03-21 12:01:08 -04:00
at_least_one_of ( * Helpers :: IssuesHelpers . update_params_at_least_one_of )
2016-11-10 05:23:44 -05:00
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2017-02-25 03:44:09 -05:00
put ':id/issues/:issue_iid' do
2021-03-24 23:09:35 -04:00
Gitlab :: QueryLimiting . disable! ( 'https://gitlab.com/gitlab-org/gitlab/-/issues/20775' )
2018-01-15 10:21:04 -05:00
2017-02-25 03:44:09 -05:00
issue = user_project . issues . find_by! ( iid : params . delete ( :issue_iid ) )
2015-06-26 09:55:56 -04:00
authorize! :update_issue , issue
2016-08-15 12:50:41 -04:00
2021-06-21 08:07:45 -04:00
update_params = declared_params ( include_missing : false )
2017-02-14 14:07:11 -05:00
2017-05-04 08:11:15 -04:00
update_params = convert_parameters_from_legacy_format ( update_params )
2021-06-21 08:07:45 -04:00
spam_params = :: Spam :: SpamParams . new_from_request ( request : request )
2021-05-11 23:10:21 -04:00
issue = :: Issues :: UpdateService . new ( project : user_project ,
current_user : current_user ,
2021-06-21 08:07:45 -04:00
params : update_params ,
spam_params : spam_params ) . execute ( issue )
2017-02-14 14:07:11 -05:00
2014-04-02 06:54:41 -04:00
if issue . valid?
2016-11-04 14:19:08 -04:00
present issue , with : Entities :: Issue , current_user : current_user , project : user_project
2014-04-02 06:54:41 -04:00
else
2022-03-10 22:08:14 -05:00
with_captcha_check_rest_api ( spammable : issue ) do
render_validation_error! ( issue )
end
2012-07-24 08:19:51 -04:00
end
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2012-07-24 08:19:51 -04:00
2020-06-30 11:08:48 -04:00
desc 'Reorder an existing issue' do
success Entities :: Issue
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
optional :move_after_id , type : Integer , desc : 'The ID of the issue we want to be after'
optional :move_before_id , type : Integer , desc : 'The ID of the issue we want to be before'
at_least_one_of :move_after_id , :move_before_id
end
# rubocop: disable CodeReuse/ActiveRecord
put ':id/issues/:issue_iid/reorder' do
issue = user_project . issues . find_by ( iid : params [ :issue_iid ] )
not_found! ( 'Issue' ) unless issue
authorize! :update_issue , issue
2021-05-11 23:10:21 -04:00
if :: Issues :: ReorderService . new ( project : user_project , current_user : current_user , params : params ) . execute ( issue )
2020-06-30 11:08:48 -04:00
present issue , with : Entities :: Issue , current_user : current_user , project : user_project
else
render_api_error! ( { error : 'Unprocessable Entity' } , 422 )
end
end
# rubocop: enable CodeReuse/ActiveRecord
2016-11-07 09:15:14 -05:00
desc 'Move an existing issue' do
success Entities :: Issue
end
params do
2017-02-25 03:44:09 -05:00
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
2016-11-07 09:15:14 -05:00
requires :to_project_id , type : Integer , desc : 'The ID of the new project'
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2017-02-25 03:44:09 -05:00
post ':id/issues/:issue_iid/move' do
2021-03-24 23:09:35 -04:00
Gitlab :: QueryLimiting . disable! ( 'https://gitlab.com/gitlab-org/gitlab/-/issues/20776' )
2018-01-15 10:21:04 -05:00
2017-02-25 03:44:09 -05:00
issue = user_project . issues . find_by ( iid : params [ :issue_iid ] )
2016-11-07 09:15:14 -05:00
not_found! ( 'Issue' ) unless issue
2016-04-07 08:07:17 -04:00
2016-11-07 09:15:14 -05:00
new_project = Project . find_by ( id : params [ :to_project_id ] )
not_found! ( 'Project' ) unless new_project
2016-04-07 08:07:17 -04:00
begin
2021-05-11 23:10:21 -04:00
issue = :: Issues :: MoveService . new ( project : user_project , current_user : current_user ) . execute ( issue , new_project )
2016-11-04 14:19:08 -04:00
present issue , with : Entities :: Issue , current_user : current_user , project : user_project
2016-04-07 08:07:17 -04:00
rescue :: Issues :: MoveService :: MoveError = > error
render_api_error! ( error . message , 400 )
end
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2016-04-07 08:07:17 -04:00
2021-09-20 23:11:06 -04:00
desc 'Clone an existing issue' do
success Entities :: Issue
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
requires :to_project_id , type : Integer , desc : 'The ID of the new project'
optional :with_notes , type : Boolean , desc : 'Clone issue with notes' , default : false
end
# rubocop: disable CodeReuse/ActiveRecord
post ':id/issues/:issue_iid/clone' do
Gitlab :: QueryLimiting . disable! ( 'https://gitlab.com/gitlab-org/gitlab/-/issues/340252' )
issue = user_project . issues . find_by ( iid : params [ :issue_iid ] )
not_found! ( 'Issue' ) unless issue
target_project = Project . find_by ( id : params [ :to_project_id ] )
not_found! ( 'Project' ) unless target_project
begin
issue = :: Issues :: CloneService . new ( project : user_project , current_user : current_user )
. execute ( issue , target_project , with_notes : params [ :with_notes ] )
present issue , with : Entities :: Issue , current_user : current_user , project : target_project
rescue :: Issues :: CloneService :: CloneError = > error
render_api_error! ( error . message , 400 )
end
end
# rubocop: enable CodeReuse/ActiveRecord
2016-11-07 09:15:14 -05:00
desc 'Delete a project issue'
params do
2017-02-25 03:44:09 -05:00
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
2016-11-07 09:15:14 -05:00
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2017-02-25 03:44:09 -05:00
delete " :id/issues/:issue_iid " do
issue = user_project . issues . find_by ( iid : params [ :issue_iid ] )
2016-11-07 09:15:14 -05:00
not_found! ( 'Issue' ) unless issue
2016-02-26 03:55:43 -05:00
2016-03-21 09:12:52 -04:00
authorize! ( :destroy_issue , issue )
2017-03-01 08:35:48 -05:00
2017-11-25 10:04:45 -05:00
destroy_conditionally! ( issue ) do | issue |
2021-05-11 23:10:21 -04:00
Issuable :: DestroyService . new ( project : user_project , current_user : current_user ) . execute ( issue )
2017-11-25 10:04:45 -05:00
end
2012-07-24 08:19:51 -04:00
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2017-04-12 07:38:00 -04:00
2019-01-16 07:09:29 -05:00
desc 'List merge requests that are related to the issue' do
2018-09-19 04:06:03 -04:00
success Entities :: MergeRequestBasic
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
end
get ':id/issues/:issue_iid/related_merge_requests' do
issue = find_project_issue ( params [ :issue_iid ] )
2021-05-11 23:10:21 -04:00
merge_requests = :: Issues :: ReferencedMergeRequestsService . new ( project : user_project , current_user : current_user )
2018-09-19 04:06:03 -04:00
. execute ( issue )
2019-04-05 12:17:13 -04:00
. first
2018-09-19 04:06:03 -04:00
2019-02-14 17:11:06 -05:00
present paginate ( :: Kaminari . paginate_array ( merge_requests ) ) ,
2019-04-04 05:01:09 -04:00
with : Entities :: MergeRequest ,
2019-02-14 17:11:06 -05:00
current_user : current_user ,
2019-10-01 05:10:39 -04:00
project : user_project ,
include_subscribed : false
2018-09-19 04:06:03 -04:00
end
2019-01-16 07:09:29 -05:00
desc 'List merge requests closing issue' do
2017-04-12 07:38:00 -04:00
success Entities :: MergeRequestBasic
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
end
2018-08-27 11:31:01 -04:00
# rubocop: disable CodeReuse/ActiveRecord
2017-04-12 07:38:00 -04:00
get ':id/issues/:issue_iid/closed_by' do
issue = find_project_issue ( params [ :issue_iid ] )
merge_request_ids = MergeRequestsClosingIssues . where ( issue_id : issue ) . select ( :merge_request_id )
merge_requests = MergeRequestsFinder . new ( current_user , project_id : user_project . id ) . execute . where ( id : merge_request_ids )
present paginate ( merge_requests ) , with : Entities :: MergeRequestBasic , current_user : current_user , project : user_project
end
2018-08-27 11:31:01 -04:00
# rubocop: enable CodeReuse/ActiveRecord
2017-07-05 10:27:32 -04:00
2019-01-16 07:09:29 -05:00
desc 'List participants for an issue' do
2018-01-05 10:21:53 -05:00
success Entities :: UserBasic
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
end
get ':id/issues/:issue_iid/participants' do
issue = find_project_issue ( params [ :issue_iid ] )
2021-12-08 19:13:41 -05:00
participants = :: Kaminari . paginate_array ( issue . visible_participants ( current_user ) )
2018-01-05 10:21:53 -05:00
present paginate ( participants ) , with : Entities :: UserBasic , current_user : current_user , project : user_project
end
2017-07-05 10:27:32 -04:00
desc 'Get the user agent details for an issue' do
success Entities :: UserAgentDetail
end
params do
requires :issue_iid , type : Integer , desc : 'The internal ID of a project issue'
end
get " :id/issues/:issue_iid/user_agent_detail " do
authenticated_as_admin!
issue = find_project_issue ( params [ :issue_iid ] )
2018-04-18 05:19:40 -04:00
break not_found! ( 'UserAgentDetail' ) unless issue . user_agent_detail
2017-07-05 10:27:32 -04:00
2017-07-06 09:19:14 -04:00
present issue . user_agent_detail , with : Entities :: UserAgentDetail
2017-07-05 10:27:32 -04:00
end
2012-07-24 08:19:51 -04:00
end
end
end
2020-11-20 07:09:35 -05:00
2021-05-11 17:10:21 -04:00
API :: Issues . prepend_mod_with ( 'API::Issues' )