diff options
author | Ryan Cobb <rcobb@gitlab.com> | 2019-05-20 13:12:12 -0600 |
---|---|---|
committer | Ryan Cobb <rcobb@gitlab.com> | 2019-05-20 13:12:12 -0600 |
commit | 06c3a4b733613dba33ae36ad99d977103f0843aa (patch) | |
tree | b2cc0966aa52b53d8bfcfb211d44d0ef9f0ed5ef /lib/api | |
parent | 618dd80c7d8ebcdb573977780f29bf1475efa4f2 (diff) | |
parent | bdc2eb33e160006cd34128e391becff86a3bc060 (diff) | |
download | gitlab-ce-61964-sys-proctable-performance.tar.gz |
Merge branch 'master' into 61964-sys-proctable-performance61964-sys-proctable-performance
Diffstat (limited to 'lib/api')
-rw-r--r-- | lib/api/entities.rb | 19 | ||||
-rw-r--r-- | lib/api/groups.rb | 24 | ||||
-rw-r--r-- | lib/api/helpers/groups_helpers.rb | 9 | ||||
-rw-r--r-- | lib/api/helpers/issues_helpers.rb | 33 | ||||
-rw-r--r-- | lib/api/issues.rb | 101 | ||||
-rw-r--r-- | lib/api/runner.rb | 1 | ||||
-rw-r--r-- | lib/api/validations/check_assignees_count.rb | 32 |
7 files changed, 167 insertions, 52 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 296688ba25b..625fada4f08 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -542,10 +542,15 @@ module API class IssueBasic < ProjectEntity expose :closed_at expose :closed_by, using: Entities::UserBasic - expose :labels do |issue| - # Avoids an N+1 query since labels are preloaded - issue.labels.map(&:title).sort + + expose :labels do |issue, options| + if options[:with_labels_details] + ::API::Entities::LabelBasic.represent(issue.labels.sort_by(&:title)) + else + issue.labels.map(&:title).sort + end end + expose :milestone, using: Entities::Milestone expose :assignees, :author, using: Entities::UserBasic @@ -573,6 +578,14 @@ module API class Issue < IssueBasic include ::API::Helpers::RelatedResourcesHelpers + expose(:has_tasks) do |issue, _| + !issue.task_list_items.empty? + end + + expose :task_status, if: -> (issue, _) do + !issue.task_list_items.empty? + end + expose :_links do expose :self do |issue| expose_url(api_v4_project_issue_path(id: issue.project_id, issue_iid: issue.iid)) diff --git a/lib/api/groups.rb b/lib/api/groups.rb index ad16f26f5cc..6893c8c40be 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -20,20 +20,19 @@ module API optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group' end - if Gitlab.ee? - params :optional_params_ee do - optional :membership_lock, type: Boolean, desc: 'Prevent adding new members to project membership within this group' - optional :ldap_cn, type: String, desc: 'LDAP Common Name' - optional :ldap_access, type: Integer, desc: 'A valid access level' - optional :shared_runners_minutes_limit, type: Integer, desc: '(admin-only) Pipeline minutes quota for this group' - optional :extra_shared_runners_minutes_limit, type: Integer, desc: '(admin-only) Extra pipeline minutes quota for this group' - all_or_none_of :ldap_cn, :ldap_access - end + params :optional_params_ee do + end + + params :optional_update_params_ee do end + end + include ::API::Helpers::GroupsHelpers + + helpers do params :optional_params do use :optional_params_ce - use :optional_params_ee if Gitlab.ee? + use :optional_params_ee end params :statistics_params do @@ -176,10 +175,7 @@ module API optional :name, type: String, desc: 'The name of the group' optional :path, type: String, desc: 'The path of the group' use :optional_params - - if Gitlab.ee? - optional :file_template_project_id, type: Integer, desc: 'The ID of a project to use for custom templates in this group' - end + use :optional_update_params_ee end put ':id' do group = find_group!(params[:id]) diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb new file mode 100644 index 00000000000..ae677547760 --- /dev/null +++ b/lib/api/helpers/groups_helpers.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module API + module Helpers + module GroupsHelpers + extend ActiveSupport::Concern + end + end +end diff --git a/lib/api/helpers/issues_helpers.rb b/lib/api/helpers/issues_helpers.rb index f6762910b0c..fc66cec5341 100644 --- a/lib/api/helpers/issues_helpers.rb +++ b/lib/api/helpers/issues_helpers.rb @@ -18,6 +18,39 @@ module API :title ] end + + def issue_finder(args = {}) + args = declared_params.merge(args) + + args.delete(:id) + args[:milestone_title] ||= args.delete(:milestone) + args[:label_name] ||= args.delete(:labels) + args[:scope] = args[:scope].underscore if args[:scope] + + IssuesFinder.new(current_user, args) + end + + def find_issues(args = {}) + finder = issue_finder(args) + issues = finder.execute.with_api_entity_associations + + issues.reorder(order_options_with_tie_breaker) # rubocop: disable CodeReuse/ActiveRecord + end + + def issues_statistics(args = {}) + finder = issue_finder(args) + counter = Gitlab::IssuablesCountForState.new(finder) + + { + statistics: { + counts: { + all: counter[:all], + closed: counter[:closed], + opened: counter[:opened] + } + } + } + end end end end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index d0a93b77951..0b4da01f3c8 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -3,27 +3,12 @@ module API class Issues < Grape::API include PaginationParams + helpers Helpers::IssuesHelpers + helpers ::Gitlab::IssuableMetadata before { authenticate_non_get! } - helpers ::Gitlab::IssuableMetadata - helpers do - # rubocop: disable CodeReuse/ActiveRecord - def find_issues(args = {}) - args = declared_params.merge(args) - - args.delete(:id) - args[:milestone_title] = args.delete(:milestone) - args[:label_name] = args.delete(:labels) - args[:scope] = args[:scope].underscore if args[:scope] - - issues = IssuesFinder.new(current_user, args).execute - .with_api_entity_associations - issues.reorder(order_options_with_tie_breaker) - end - # rubocop: enable CodeReuse/ActiveRecord - if Gitlab.ee? params :issues_params_ee do optional :weight, types: [Integer, String], integer_none_any: true, desc: 'The weight of the issue' @@ -34,13 +19,9 @@ module API end end - params :issues_params do + params :issues_stats_params do optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' optional :milestone, type: String, desc: 'Milestone title' - optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at', - desc: 'Return issues ordered by `created_at` or `updated_at` fields.' - optional :sort, type: String, values: %w[asc desc], default: 'desc', - desc: 'Return issues sorted in `asc` or `desc` order.' optional :milestone, type: String, desc: 'Return issues for a specific milestone' optional :iids, type: Array[Integer], desc: 'The IID array of issues' optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these' @@ -49,18 +30,39 @@ module API 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 :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID' + optional :author_username, type: String, desc: 'Return issues which are authored by the user with the given username' + mutually_exclusive :author_id, :author_username + optional :assignee_id, types: [Integer, String], integer_none_any: true, desc: 'Return issues which are assigned to the user with the given ID' + optional :assignee_username, type: Array[String], check_assignees_count: true, + coerce_with: Validations::CheckAssigneesCount.coerce, + desc: 'Return issues which are assigned to the user with the given username' + mutually_exclusive :assignee_id, :assignee_username + 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`' optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji' optional :confidential, type: Boolean, desc: 'Filter confidential or public issues' - use :pagination use :issues_params_ee if Gitlab.ee? end + params :issues_params do + optional :with_labels_details, type: Boolean, desc: 'Return more label data than just lable title', default: false + optional :state, type: String, values: %w[opened closed all], default: 'all', + desc: 'Return opened, closed, or all issues' + optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at', + desc: 'Return issues ordered by `created_at` or `updated_at` fields.' + optional :sort, type: String, values: %w[asc desc], default: 'desc', + desc: 'Return issues sorted in `asc` or `desc` order.' + + use :issues_stats_params + use :pagination + end + params :issue_params do optional :description, type: String, desc: 'The description of an issue' optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue' @@ -75,13 +77,23 @@ module API end end + desc "Get currently authenticated user's issues statistics" + params do + use :issues_stats_params + optional :scope, type: String, values: %w[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`' + end + get '/issues_statistics' do + authenticate! unless params[:scope] == 'all' + + present issues_statistics, with: Grape::Presenters::Presenter + end + resource :issues do desc "Get currently authenticated user's issues" do - success Entities::IssueBasic + success Entities::Issue end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params 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`' @@ -91,7 +103,8 @@ module API issues = paginate(find_issues) options = { - with: Entities::IssueBasic, + with: Entities::Issue, + with_labels_details: declared_params[:with_labels_details], current_user: current_user, issuable_metadata: issuable_meta_data(issues, 'Issue') } @@ -105,11 +118,9 @@ module API end resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do desc 'Get a list of group issues' do - success Entities::IssueBasic + success Entities::Issue end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params end get ":id/issues" do @@ -118,13 +129,24 @@ module API issues = paginate(find_issues(group_id: group.id, include_subgroups: true)) options = { - with: Entities::IssueBasic, + with: Entities::Issue, + with_labels_details: declared_params[:with_labels_details], current_user: current_user, issuable_metadata: issuable_meta_data(issues, 'Issue') } present issues, options end + + desc 'Get statistics for the list of group issues' + params do + use :issues_stats_params + end + get ":id/issues_statistics" do + group = find_group!(params[:id]) + + present issues_statistics(group_id: group.id, include_subgroups: true), with: Grape::Presenters::Presenter + end end params do @@ -134,11 +156,9 @@ module API include TimeTrackingEndpoints desc 'Get a list of project issues' do - success Entities::IssueBasic + success Entities::Issue end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params end get ":id/issues" do @@ -147,7 +167,8 @@ module API issues = paginate(find_issues(project_id: project.id)) options = { - with: Entities::IssueBasic, + with: Entities::Issue, + with_labels_details: declared_params[:with_labels_details], current_user: current_user, project: user_project, issuable_metadata: issuable_meta_data(issues, 'Issue') @@ -156,6 +177,16 @@ module API present issues, options end + desc 'Get statistics for the list of project issues' + params do + use :issues_stats_params + end + get ":id/issues_statistics" do + project = find_project!(params[:id]) + + present issues_statistics(project_id: project.id), with: Grape::Presenters::Presenter + end + desc 'Get a single project issue' do success Entities::Issue end diff --git a/lib/api/runner.rb b/lib/api/runner.rb index ea36c24eca2..fdf4904e9f5 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -98,6 +98,7 @@ module API optional :certificate, type: String, desc: %q(Session's certificate) optional :authorization, type: String, desc: %q(Session's authorization) end + optional :job_age, type: Integer, desc: %q(Job should be older than passed age in seconds to be ran on runner) end post '/request' do authenticate_runner! diff --git a/lib/api/validations/check_assignees_count.rb b/lib/api/validations/check_assignees_count.rb new file mode 100644 index 00000000000..836ec936b31 --- /dev/null +++ b/lib/api/validations/check_assignees_count.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module API + module Validations + class CheckAssigneesCount < Grape::Validations::Base + def self.coerce + lambda do |value| + case value + when String, Array + Array.wrap(value) + else + [] + end + end + end + + def validate_param!(attr_name, params) + return if param_allowed?(attr_name, params) + + raise Grape::Exceptions::Validation, + params: [@scope.full_name(attr_name)], + message: "allows one value, but found #{params[attr_name].size}: #{params[attr_name].join(", ")}" + end + + private + + def param_allowed?(attr_name, params) + params[attr_name].size <= 1 + end + end + end +end |