From c5c9dce270516adf3a2e4a549d1c32b6a3223335 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Wed, 12 Jul 2017 16:58:48 -0300 Subject: Add group milestones API endpoint --- lib/api/api.rb | 3 +- lib/api/entities.rb | 4 +- lib/api/group_milestones.rb | 85 +++++++++++++++++++++++ lib/api/helpers.rb | 4 ++ lib/api/milestone_responses.rb | 98 ++++++++++++++++++++++++++ lib/api/milestones.rb | 154 ----------------------------------------- lib/api/project_milestones.rb | 91 ++++++++++++++++++++++++ 7 files changed, 282 insertions(+), 157 deletions(-) create mode 100644 lib/api/group_milestones.rb create mode 100644 lib/api/milestone_responses.rb delete mode 100644 lib/api/milestones.rb create mode 100644 lib/api/project_milestones.rb (limited to 'lib/api') diff --git a/lib/api/api.rb b/lib/api/api.rb index efcf0976a81..7e45c34731f 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -109,7 +109,8 @@ module API mount ::API::Members mount ::API::MergeRequestDiffs mount ::API::MergeRequests - mount ::API::Milestones + mount ::API::ProjectMilestones + mount ::API::GroupMilestones mount ::API::Namespaces mount ::API::Notes mount ::API::NotificationSettings diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 09a88869063..586325ddb0c 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -269,8 +269,8 @@ module API class Milestone < Grape::Entity expose :id, :iid - expose(:project_id) { |entity| entity&.project_id } - expose(:group_id) { |entity| entity&.group_id } + expose :project_id, if: -> (entity, options) { entity&.project_id } + expose :group_id, if: -> (entity, options) { entity&.group_id } expose :title, :description expose :state, :created_at, :updated_at expose :due_date diff --git a/lib/api/group_milestones.rb b/lib/api/group_milestones.rb new file mode 100644 index 00000000000..b85eb59dc0a --- /dev/null +++ b/lib/api/group_milestones.rb @@ -0,0 +1,85 @@ +module API + class GroupMilestones < Grape::API + include MilestoneResponses + include PaginationParams + + before do + authenticate! + end + + params do + requires :id, type: String, desc: 'The ID of a group' + end + resource :groups, requirements: { id: %r{[^/]+} } do + desc 'Get a list of group milestones' do + success Entities::Milestone + end + params do + use :list_params + end + get ":id/milestones" do + list_milestones_for(user_group) + end + + desc 'Get a single group milestone' do + success Entities::Milestone + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a group milestone' + end + get ":id/milestones/:milestone_id" do + authorize! :read_group, user_group + + get_milestone_for(user_group) + end + + desc 'Create a new group milestone' do + success Entities::Milestone + end + params do + requires :title, type: String, desc: 'The title of the milestone' + use :optional_params + end + post ":id/milestones" do + authorize! :admin_milestones, user_group + + create_milestone_for(user_group) + end + + desc 'Update an existing group milestone' do + success Entities::Milestone + end + params do + use :update_params + end + put ":id/milestones/:milestone_id" do + authorize! :admin_milestones, user_group + + update_milestone_for(user_group) + end + + desc 'Get all issues for a single group milestone' do + success Entities::IssueBasic + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a group milestone' + use :pagination + end + get ":id/milestones/:milestone_id/issues" do + milestone_issuables_for(user_group, :issue) + end + + desc 'Get all merge requests for a single group milestone' do + detail 'This feature was introduced in GitLab 9.' + success Entities::MergeRequestBasic + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a group milestone' + use :pagination + end + get ':id/milestones/:milestone_id/merge_requests' do + milestone_issuables_for(user_group, :merge_request) + end + end + end +end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 0f4791841d2..57e3e93500f 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -25,6 +25,10 @@ module API initial_current_user != current_user end + def user_group + @group ||= find_group!(params[:id]) + end + def user_project @project ||= find_project!(params[:id]) end diff --git a/lib/api/milestone_responses.rb b/lib/api/milestone_responses.rb new file mode 100644 index 00000000000..ef09d9505d2 --- /dev/null +++ b/lib/api/milestone_responses.rb @@ -0,0 +1,98 @@ +module API + module MilestoneResponses + extend ActiveSupport::Concern + + included do + helpers do + params :optional_params do + optional :description, type: String, desc: 'The description of the milestone' + optional :due_date, type: String, desc: 'The due date of the milestone. The ISO 8601 date format (%Y-%m-%d)' + optional :start_date, type: String, desc: 'The start date of the milestone. The ISO 8601 date format (%Y-%m-%d)' + end + + params :list_params do + optional :state, type: String, values: %w[active closed all], default: 'all', + desc: 'Return "active", "closed", or "all" milestones' + optional :iids, type: Array[Integer], desc: 'The IIDs of the milestones' + optional :search, type: String, desc: 'The search criteria for the title or description of the milestone' + use :pagination + end + + params :update_params do + requires :milestone_id, type: Integer, desc: 'The milestone ID number' + optional :title, type: String, desc: 'The title of the milestone' + optional :state_event, type: String, values: %w[close activate], + desc: 'The state event of the milestone ' + use :optional_params + at_least_one_of :title, :description, :due_date, :state_event + end + + def list_milestones_for(parent) + milestones = parent.milestones + milestones = Milestone.filter_by_state(milestones, params[:state]) + milestones = filter_by_iid(milestones, params[:iids]) if params[:iids].present? + milestones = filter_by_search(milestones, params[:search]) if params[:search] + + present paginate(milestones), with: Entities::Milestone + end + + def get_milestone_for(parent) + milestone = parent.milestones.find(params[:milestone_id]) + present milestone, with: Entities::Milestone + end + + def create_milestone_for(parent) + milestone = ::Milestones::CreateService.new(parent, current_user, declared_params).execute + + if milestone.valid? + present milestone, with: Entities::Milestone + else + render_api_error!("Failed to create milestone #{milestone.errors.messages}", 400) + end + end + + def update_milestone_for(parent) + milestone = parent.milestones.find(params.delete(:milestone_id)) + + milestone_params = declared_params(include_missing: false) + milestone = ::Milestones::UpdateService.new(parent, current_user, milestone_params).execute(milestone) + + if milestone.valid? + present milestone, with: Entities::Milestone + else + render_api_error!("Failed to update milestone #{milestone.errors.messages}", 400) + end + end + + def milestone_issuables_for(parent, type) + milestone = parent.milestones.find(params[:milestone_id]) + + finder_klass, entity = get_finder_and_entity(type) + + params = build_finder_params(milestone, parent) + + issuables = finder_klass.new(current_user, params).execute + present paginate(issuables), with: entity, current_user: current_user + end + + def build_finder_params(milestone, parent) + finder_params = { milestone_title: milestone.title, sort: 'label_priority' } + + if parent.is_a?(Group) + finder_params.merge(group_id: parent.id) + else + finder_params.merge(project_id: parent.id) + end + end + + def get_finder_and_entity(type) + if type == :issue + [IssuesFinder, Entities::IssueBasic] + else + [MergeRequestsFinder, Entities::MergeRequestBasic] + end + end + end + end + end +end diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb deleted file mode 100644 index 3541d3c95fb..00000000000 --- a/lib/api/milestones.rb +++ /dev/null @@ -1,154 +0,0 @@ -module API - class Milestones < Grape::API - include PaginationParams - - before { authenticate! } - - helpers do - def filter_milestones_state(milestones, state) - case state - when 'active' then milestones.active - when 'closed' then milestones.closed - else milestones - end - end - - params :optional_params do - optional :description, type: String, desc: 'The description of the milestone' - optional :due_date, type: String, desc: 'The due date of the milestone. The ISO 8601 date format (%Y-%m-%d)' - optional :start_date, type: String, desc: 'The start date of the milestone. The ISO 8601 date format (%Y-%m-%d)' - end - end - - params do - requires :id, type: String, desc: 'The ID of a project' - end - resource :projects, requirements: { id: %r{[^/]+} } do - desc 'Get a list of project milestones' do - success Entities::Milestone - end - params do - optional :state, type: String, values: %w[active closed all], default: 'all', - desc: 'Return "active", "closed", or "all" milestones' - optional :iids, type: Array[Integer], desc: 'The IIDs of the milestones' - optional :search, type: String, desc: 'The search criteria for the title or description of the milestone' - use :pagination - end - get ":id/milestones" do - authorize! :read_milestone, user_project - - milestones = user_project.milestones - milestones = filter_milestones_state(milestones, params[:state]) - milestones = filter_by_iid(milestones, params[:iids]) if params[:iids].present? - milestones = filter_by_search(milestones, params[:search]) if params[:search] - - present paginate(milestones), with: Entities::Milestone - end - - desc 'Get a single project milestone' do - success Entities::Milestone - end - params do - requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' - end - get ":id/milestones/:milestone_id" do - authorize! :read_milestone, user_project - - milestone = user_project.milestones.find(params[:milestone_id]) - present milestone, with: Entities::Milestone - end - - desc 'Create a new project milestone' do - success Entities::Milestone - end - params do - requires :title, type: String, desc: 'The title of the milestone' - use :optional_params - end - post ":id/milestones" do - authorize! :admin_milestone, user_project - - milestone = ::Milestones::CreateService.new(user_project, current_user, declared_params).execute - - if milestone.valid? - present milestone, with: Entities::Milestone - else - render_api_error!("Failed to create milestone #{milestone.errors.messages}", 400) - end - end - - desc 'Update an existing project milestone' do - success Entities::Milestone - end - params do - requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' - optional :title, type: String, desc: 'The title of the milestone' - optional :state_event, type: String, values: %w[close activate], - desc: 'The state event of the milestone ' - use :optional_params - at_least_one_of :title, :description, :due_date, :state_event - end - put ":id/milestones/:milestone_id" do - authorize! :admin_milestone, user_project - milestone = user_project.milestones.find(params.delete(:milestone_id)) - - milestone_params = declared_params(include_missing: false) - milestone = ::Milestones::UpdateService.new(user_project, current_user, milestone_params).execute(milestone) - - if milestone.valid? - present milestone, with: Entities::Milestone - else - render_api_error!("Failed to update milestone #{milestone.errors.messages}", 400) - end - end - - desc 'Get all issues for a single project milestone' do - success Entities::IssueBasic - end - params do - requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' - use :pagination - end - get ":id/milestones/:milestone_id/issues" do - authorize! :read_milestone, user_project - - milestone = user_project.milestones.find(params[:milestone_id]) - - finder_params = { - project_id: user_project.id, - milestone_title: milestone.title, - sort: 'label_priority' - } - - issues = IssuesFinder.new(current_user, finder_params).execute - present paginate(issues), with: Entities::IssueBasic, current_user: current_user, project: user_project - end - - desc 'Get all merge requests for a single project milestone' do - detail 'This feature was introduced in GitLab 9.' - success Entities::MergeRequestBasic - end - params do - requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' - use :pagination - end - get ':id/milestones/:milestone_id/merge_requests' do - authorize! :read_milestone, user_project - - milestone = user_project.milestones.find(params[:milestone_id]) - - finder_params = { - project_id: user_project.id, - milestone_title: milestone.title, - sort: 'label_priority' - } - - merge_requests = MergeRequestsFinder.new(current_user, finder_params).execute - present paginate(merge_requests), - with: Entities::MergeRequestBasic, - current_user: current_user, - project: user_project - end - end - end -end diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb new file mode 100644 index 00000000000..451998c726a --- /dev/null +++ b/lib/api/project_milestones.rb @@ -0,0 +1,91 @@ +module API + class ProjectMilestones < Grape::API + include PaginationParams + include MilestoneResponses + + before do + authenticate! + end + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: { id: %r{[^/]+} } do + desc 'Get a list of project milestones' do + success Entities::Milestone + end + params do + use :list_params + end + get ":id/milestones" do + authorize! :read_milestone, user_project + + list_milestones_for(user_project) + end + + desc 'Get a single project milestone' do + success Entities::Milestone + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' + end + get ":id/milestones/:milestone_id" do + authorize! :read_milestone, user_project + + get_milestone_for(user_project) + end + + desc 'Create a new project milestone' do + success Entities::Milestone + end + params do + requires :title, type: String, desc: 'The title of the milestone' + use :optional_params + end + post ":id/milestones" do + authorize! :admin_milestone, user_project + + create_milestone_for(user_project) + end + + desc 'Update an existing project milestone' do + success Entities::Milestone + end + params do + use :update_params + end + put ":id/milestones/:milestone_id" do + authorize! :admin_milestone, user_project + + update_milestone_for(user_project) + end + + desc 'Get all issues for a single project milestone' do + success Entities::IssueBasic + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' + use :pagination + end + get ":id/milestones/:milestone_id/issues" do + authorize! :read_milestone, user_project + + milestone_issuables_for(user_project, :issue) + end + + desc 'Get all merge requests for a single project milestone' do + detail 'This feature was introduced in GitLab 9.' + success Entities::MergeRequestBasic + end + params do + requires :milestone_id, type: Integer, desc: 'The ID of a project milestone' + use :pagination + end + get ':id/milestones/:milestone_id/merge_requests' do + authorize! :read_milestone, user_project + + milestone_issuables_for(user_project, :merge_request) + end + end + end +end -- cgit v1.2.3