Skip to content
Snippets Groups Projects
Commit 01ea65e0 authored by Robert Schilling's avatar Robert Schilling
Browse files

Paginate all endpoints that return an array

parent 28d8b865
No related branches found
No related tags found
No related merge requests found
Showing
with 108 additions and 51 deletions
---
title: 'API: Paginate all endpoints that return an array'
merge_request: 8606
author: Robert Schilling
Loading
Loading
@@ -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
Loading
Loading
module API
# Boards API
class Boards < Grape::API
include PaginationParams
before { authenticate! }
 
params do
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
require 'mime/types'
 
module API
# Projects API
class Branches < Grape::API
include PaginationParams
before { authenticate! }
before { authorize! :download_code, user_project }
 
Loading
Loading
@@ -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
Loading
Loading
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
Loading
Loading
@@ -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
Loading
Loading
module API
# Projects API
class Files < Grape::API
helpers do
def commit_params(attrs)
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
module API
# Labels API
class Labels < Grape::API
include PaginationParams
before { authenticate! }
 
params do
Loading
Loading
@@ -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
Loading
Loading
module API
# MergeRequestDiff API
class MergeRequestDiffs < Grape::API
include PaginationParams
before { authenticate! }
 
resource :projects do
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -2,6 +2,8 @@ require 'mime/types'
 
module API
class Repositories < Grape::API
include PaginationParams
before { authorize! :download_code, user_project }
 
params do
Loading
Loading
@@ -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'
Loading
Loading
@@ -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'
Loading
Loading
@@ -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
Loading
Loading
module API
# Hooks API
class SystemHooks < Grape::API
include PaginationParams
before do
authenticate!
authenticated_as_admin!
Loading
Loading
@@ -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
Loading
Loading
module API
# Git Tags API
class Tags < Grape::API
include PaginationParams
before { authorize! :download_code, user_project }
 
params do
Loading
Loading
@@ -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
Loading
Loading
module API
class Templates < Grape::API
include PaginationParams
GLOBAL_TEMPLATE_TYPES = {
gitignores: {
klass: Gitlab::Template::GitignoreTemplate,
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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!
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
Loading
Loading
@@ -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'] }
Loading
Loading
Loading
Loading
@@ -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)
Loading
Loading
Loading
Loading
@@ -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)
Loading
Loading
@@ -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}")
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment