Commit 01ea65e0 authored by Robert Schilling's avatar Robert Schilling

Paginate all endpoints that return an array

parent 28d8b865
---
title: 'API: Paginate all endpoints that return an array'
merge_request: 8606
author: Robert Schilling
......@@ -28,8 +28,8 @@ module API
end
get endpoint do
if can_read_awardable?
awards = paginate(awardable.award_emoji)
present awards, with: Entities::AwardEmoji
awards = awardable.award_emoji
present paginate(awards), with: Entities::AwardEmoji
else
not_found!("Award Emoji")
end
......
module API
# Boards API
class Boards < Grape::API
include PaginationParams
before { authenticate! }
params do
......@@ -11,9 +12,12 @@ module API
detail 'This feature was introduced in 8.13'
success Entities::Board
end
params do
use :pagination
end
get ':id/boards' do
authorize!(:read_board, user_project)
present user_project.boards, with: Entities::Board
present paginate(user_project.boards), with: Entities::Board
end
params do
......@@ -40,9 +44,12 @@ module API
detail 'Does not include `done` list. This feature was introduced in 8.13'
success Entities::List
end
params do
use :pagination
end
get '/lists' do
authorize!(:read_board, user_project)
present board_lists, with: Entities::List
present paginate(board_lists), with: Entities::List
end
desc 'Get a list of a project board' do
......
require 'mime/types'
module API
# Projects API
class Branches < Grape::API
include PaginationParams
before { authenticate! }
before { authorize! :download_code, user_project }
......@@ -13,10 +14,13 @@ module API
desc 'Get a project repository branches' do
success Entities::RepoBranch
end
params do
use :pagination
end
get ":id/repository/branches" do
branches = user_project.repository.branches.sort_by(&:name)
branches = ::Kaminari.paginate_array(user_project.repository.branches.sort_by(&:name))
present branches, with: Entities::RepoBranch, project: user_project
present paginate(branches), with: Entities::RepoBranch, project: user_project
end
desc 'Get a single branch' do
......
module API
class DeployKeys < Grape::API
include PaginationParams
before { authenticate! }
desc 'Return all deploy keys'
params do
use :pagination
end
get "deploy_keys" do
authenticated_as_admin!
keys = DeployKey.all
present keys, with: Entities::SSHKey
present paginate(DeployKey.all), with: Entities::SSHKey
end
params do
......@@ -18,8 +23,11 @@ module API
desc "Get a specific project's deploy keys" do
success Entities::SSHKey
end
params do
use :pagination
end
get ":id/deploy_keys" do
present user_project.deploy_keys, with: Entities::SSHKey
present paginate(user_project.deploy_keys), with: Entities::SSHKey
end
desc 'Get single deploy key' do
......
module API
# Projects API
class Files < Grape::API
helpers do
def commit_params(attrs)
......
......@@ -2,7 +2,7 @@ module API
module Helpers
module Pagination
def paginate(relation)
relation.page(params[:page]).per(params[:per_page].to_i).tap do |data|
relation.page(params[:page]).per(params[:per_page]).tap do |data|
add_pagination_headers(data)
end
end
......
module API
# Labels API
class Labels < Grape::API
include PaginationParams
before { authenticate! }
params do
......@@ -10,8 +11,11 @@ module API
desc 'Get all labels of the project' do
success Entities::Label
end
params do
use :pagination
end
get ':id/labels' do
present available_labels, with: Entities::Label, current_user: current_user, project: user_project
present paginate(available_labels), with: Entities::Label, current_user: current_user, project: user_project
end
desc 'Create a new label' do
......
module API
# MergeRequestDiff API
class MergeRequestDiffs < Grape::API
include PaginationParams
before { authenticate! }
resource :projects do
......@@ -12,12 +14,12 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
requires :merge_request_id, type: Integer, desc: 'The ID of a merge request'
use :pagination
end
get ":id/merge_requests/:merge_request_id/versions" do
merge_request = find_merge_request_with_access(params[:merge_request_id])
present merge_request.merge_request_diffs, with: Entities::MergeRequestDiff
present paginate(merge_request.merge_request_diffs), with: Entities::MergeRequestDiff
end
desc 'Get a single merge request diff version' do
......
......@@ -119,8 +119,9 @@ module API
end
get ':id/merge_requests/:merge_request_id/commits' do
merge_request = find_merge_request_with_access(params[:merge_request_id])
commits = ::Kaminari.paginate_array(merge_request.commits)
present merge_request.commits, with: Entities::RepoCommit
present paginate(commits), with: Entities::RepoCommit
end
desc 'Show the merge request changes' do
......
......@@ -15,8 +15,8 @@ module API
included do
helpers do
params :pagination do
optional :page, type: Integer, desc: 'Current page number'
optional :per_page, type: Integer, desc: 'Number of items per page'
optional :page, type: Integer, default: 1, desc: 'Current page number'
optional :per_page, type: Integer, default: 20, desc: 'Number of items per page'
end
end
end
......
......@@ -32,9 +32,7 @@ module API
use :pagination
end
get ":id/hooks" do
hooks = paginate user_project.hooks
present hooks, with: Entities::ProjectHook
present paginate(user_project.hooks), with: Entities::ProjectHook
end
desc 'Get a project hook' do
......
......@@ -2,6 +2,8 @@ require 'mime/types'
module API
class Repositories < Grape::API
include PaginationParams
before { authorize! :download_code, user_project }
params do
......@@ -24,6 +26,7 @@ module API
optional :ref_name, type: String, desc: 'The name of a repository branch or tag, if not given the default branch is used'
optional :path, type: String, desc: 'The path of the tree'
optional :recursive, type: Boolean, default: false, desc: 'Used to get a recursive tree'
use :pagination
end
get ':id/repository/tree' do
ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
......@@ -33,8 +36,8 @@ module API
not_found!('Tree') unless commit
tree = user_project.repository.tree(commit.id, path, recursive: params[:recursive])
present tree.sorted_entries, with: Entities::RepoTreeObject
entries = ::Kaminari.paginate_array(tree.sorted_entries)
present paginate(entries), with: Entities::RepoTreeObject
end
desc 'Get a raw file contents'
......@@ -100,10 +103,13 @@ module API
desc 'Get repository contributors' do
success Entities::Contributor
end
params do
use :pagination
end
get ':id/repository/contributors' do
begin
present user_project.repository.contributors,
with: Entities::Contributor
contributors = ::Kaminari.paginate_array(user_project.repository.contributors)
present paginate(contributors), with: Entities::Contributor
rescue
not_found!
end
......
module API
# Hooks API
class SystemHooks < Grape::API
include PaginationParams
before do
authenticate!
authenticated_as_admin!
......@@ -10,10 +11,11 @@ module API
desc 'Get the list of system hooks' do
success Entities::Hook
end
params do
use :pagination
end
get do
hooks = SystemHook.all
present hooks, with: Entities::Hook
present paginate(SystemHook.all), with: Entities::Hook
end
desc 'Create a new system hook' do
......
module API
# Git Tags API
class Tags < Grape::API
include PaginationParams
before { authorize! :download_code, user_project }
params do
......@@ -10,9 +11,12 @@ module API
desc 'Get a project repository tags' do
success Entities::RepoTag
end
params do
use :pagination
end
get ":id/repository/tags" do
present user_project.repository.tags.sort_by(&:name).reverse,
with: Entities::RepoTag, project: user_project
tags = ::Kaminari.paginate_array(user_project.repository.tags.sort_by(&:name).reverse)
present paginate(tags), with: Entities::RepoTag, project: user_project
end
desc 'Get a single repository tag' do
......
module API
class Templates < Grape::API
include PaginationParams
GLOBAL_TEMPLATE_TYPES = {
gitignores: {
klass: Gitlab::Template::GitignoreTemplate,
......@@ -51,12 +53,14 @@ module API
end
params do
optional :popular, type: Boolean, desc: 'If passed, returns only popular licenses'
use :pagination
end
get "templates/licenses" do
options = {
featured: declared(params).popular.present? ? true : nil
}
present Licensee::License.all(options), with: ::API::Entities::RepoLicense
licences = ::Kaminari.paginate_array(Licensee::License.all(options))
present paginate(licences), with: Entities::RepoLicense
end
desc 'Get the text for a specific license' do
......@@ -82,8 +86,12 @@ module API
detail "This feature was introduced in GitLab #{gitlab_version}."
success Entities::TemplatesList
end
params do
use :pagination
end
get "templates/#{template_type}" do
present klass.all, with: Entities::TemplatesList
templates = ::Kaminari.paginate_array(klass.all)
present paginate(templates), with: Entities::TemplatesLis
end
desc 'Get the text for a specific template present in local filesystem' do
......
......@@ -209,6 +209,7 @@ module API
end
params do
requires :id, type: Integer, desc: 'The ID of the user'
use :pagination
end
get ':id/keys' do
authenticated_as_admin!
......@@ -216,7 +217,7 @@ module API
user = User.find_by(id: params[:id])
not_found!('User') unless user
present user.keys, with: Entities::SSHKey
present paginate(user.keys), with: Entities::SSHKey
end
desc 'Delete an existing SSH key from a specified user. Available only for admins.' do
......@@ -266,13 +267,14 @@ module API
end
params do
requires :id, type: Integer, desc: 'The ID of the user'
use :pagination
end
get ':id/emails' do
authenticated_as_admin!
user = User.find_by(id: params[:id])
not_found!('User') unless user
present user.emails, with: Entities::Email
present paginate(user.emails), with: Entities::Email
end
desc 'Delete an email address of a specified user. Available only for admins.' do
......@@ -373,8 +375,11 @@ module API
desc "Get the currently authenticated user's SSH keys" do
success Entities::SSHKey
end
params do
use :pagination
end
get "keys" do
present current_user.keys, with: Entities::SSHKey
present paginate(current_user.keys), with: Entities::SSHKey
end
desc 'Get a single key owned by currently authenticated user' do
......@@ -423,8 +428,11 @@ module API
desc "Get the currently authenticated user's email addresses" do
success Entities::Email
end
params do
use :pagination
end
get "emails" do
present current_user.emails, with: Entities::Email
present paginate(current_user.emails), with: Entities::Email
end
desc 'Get a single email address owned by the currently authenticated user' do
......
......@@ -17,7 +17,7 @@ describe API::Branches, api: true do
it "returns an array of project branches" do
project.repository.expire_all_method_caches
get api("/projects/#{project.id}/repository/branches", user)
get api("/projects/#{project.id}/repository/branches", user), per_page: 100
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
branch_names = json_response.map { |x| x['name'] }
......
......@@ -191,6 +191,8 @@ describe API::MergeRequests, api: true do
commit = merge_request.commits.first
expect(response.status).to eq 200
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(merge_request.commits.size)
expect(json_response.first['id']).to eq(commit.id)
expect(json_response.first['title']).to eq(commit.title)
......
......@@ -41,16 +41,6 @@ describe API::Milestones, api: true do
expect(json_response.length).to eq(1)
expect(json_response.first['id']).to eq(closed_milestone.id)
end
end
describe 'GET /projects/:id/milestones/:milestone_id' do
it 'returns a project milestone by id' do
get api("/projects/#{project.id}/milestones/#{milestone.id}", user)
expect(response).to have_http_status(200)
expect(json_response['title']).to eq(milestone.title)
expect(json_response['iid']).to eq(milestone.iid)
end
it 'returns a project milestone by iid' do
get api("/projects/#{project.id}/milestones?iid=#{closed_milestone.iid}", user)
......@@ -69,6 +59,16 @@ describe API::Milestones, api: true do
expect(json_response.first['title']).to eq milestone.title
expect(json_response.first['id']).to eq milestone.id
end
end
describe 'GET /projects/:id/milestones/:milestone_id' do
it 'returns a project milestone by id' do
get api("/projects/#{project.id}/milestones/#{milestone.id}", user)
expect(response).to have_http_status(200)
expect(json_response['title']).to eq(milestone.title)
expect(json_response['iid']).to eq(milestone.iid)
end
it 'returns 401 error if user not authenticated' do
get api("/projects/#{project.id}/milestones/#{milestone.id}")
......
......@@ -507,8 +507,11 @@ describe API::Users, api: true do
it 'returns array of ssh keys' do
user.keys << key
user.save
get api("/users/#{user.id}/keys", admin)
expect(response).to have_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(key.title)
end
......@@ -774,8 +777,11 @@ describe API::Users, api: true do
it "returns array of ssh keys" do
user.keys << key
user.save
get api("/user/keys", user)
expect(response).to have_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first["title"]).to eq(key.title)
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment