diff --git a/docs/api-generated/cases/case-apis-passthru.asciidoc b/docs/api-generated/cases/case-apis-passthru.asciidoc
index d0e7a67c5066..f007882af237 100644
--- a/docs/api-generated/cases/case-apis-passthru.asciidoc
+++ b/docs/api-generated/cases/case-apis-passthru.asciidoc
@@ -556,7 +556,7 @@ Any modifications made to this file will be overwritten.
Query Parameter — The page number to return. default: 1
perPage (optional)
- Query Parameter — The number of items to return. default: 20
sortOrder (optional)
+ Query Parameter — The number of items to return. Limited to 100 items. default: 20
sortOrder (optional)
Query Parameter — Determines the sort order. default: desc
diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts
index 33473a9c80bf..1a49de004e73 100644
--- a/x-pack/plugins/cases/common/constants/index.ts
+++ b/x-pack/plugins/cases/common/constants/index.ts
@@ -104,6 +104,7 @@ export const MAX_DOCS_PER_PAGE = 10000 as const;
export const MAX_BULK_GET_ATTACHMENTS = MAX_DOCS_PER_PAGE;
export const MAX_CONCURRENT_SEARCHES = 10 as const;
export const MAX_BULK_GET_CASES = 1000 as const;
+export const MAX_COMMENTS_PER_PAGE = 100 as const;
export const MAX_CATEGORY_FILTER_LENGTH = 100 as const;
/**
diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json
index 92dcfe577930..78ba5444f40a 100644
--- a/x-pack/plugins/cases/docs/openapi/bundled.json
+++ b/x-pack/plugins/cases/docs/openapi/bundled.json
@@ -1852,7 +1852,15 @@
"$ref": "#/components/parameters/page_index"
},
{
- "$ref": "#/components/parameters/page_size"
+ "name": "perPage",
+ "in": "query",
+ "description": "The number of items to return. Limited to 100 items.",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "default": 20,
+ "maximum": 100
+ }
},
{
"$ref": "#/components/parameters/sort_order"
diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml
index 3d53916c89df..405cf4fb689f 100644
--- a/x-pack/plugins/cases/docs/openapi/bundled.yaml
+++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml
@@ -1156,7 +1156,14 @@ paths:
parameters:
- $ref: '#/components/parameters/case_id'
- $ref: '#/components/parameters/page_index'
- - $ref: '#/components/parameters/page_size'
+ - name: perPage
+ in: query
+ description: The number of items to return. Limited to 100 items.
+ required: false
+ schema:
+ type: integer
+ default: 20
+ maximum: 100
- $ref: '#/components/parameters/sort_order'
- $ref: '#/components/parameters/space_id'
responses:
diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@_find.yaml
index b1dd32a65951..bb43f4dcc0b2 100644
--- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@_find.yaml
+++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@_find.yaml
@@ -10,7 +10,14 @@ get:
parameters:
- $ref: '../components/parameters/case_id.yaml'
- $ref: '../components/parameters/page_index.yaml'
- - $ref: '../components/parameters/page_size.yaml'
+ - name: perPage
+ in: query
+ description: The number of items to return. Limited to 100 items.
+ required: false
+ schema:
+ type: integer
+ default: 20
+ maximum: 100
- $ref: '../components/parameters/sort_order.yaml'
- $ref: '../components/parameters/space_id.yaml'
responses:
diff --git a/x-pack/plugins/cases/server/client/attachments/get.test.ts b/x-pack/plugins/cases/server/client/attachments/get.test.ts
index 250cfa9f0b25..c2c3423b2388 100644
--- a/x-pack/plugins/cases/server/client/attachments/get.test.ts
+++ b/x-pack/plugins/cases/server/client/attachments/get.test.ts
@@ -18,12 +18,20 @@ describe('get', () => {
it('Invalid total items results in error', async () => {
await expect(() =>
- findComment({ caseID: 'mock-id', findQueryParams: { page: 2, perPage: 9001 } }, clientArgs)
+ findComment({ caseID: 'mock-id', findQueryParams: { page: 209, perPage: 100 } }, clientArgs)
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Failed to find comments case id: mock-id: Error: The number of documents is too high. Paginating through more than 10,000 documents is not possible."`
);
});
+ it('Invalid perPage items results in error', async () => {
+ await expect(() =>
+ findComment({ caseID: 'mock-id', findQueryParams: { page: 2, perPage: 9001 } }, clientArgs)
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
+ `"Failed to find comments case id: mock-id: Error: The provided perPage value was too high. The maximum allowed perPage value is 100."`
+ );
+ });
+
it('throws with excess fields', async () => {
await expect(
findComment(
diff --git a/x-pack/plugins/cases/server/client/attachments/validators.test.ts b/x-pack/plugins/cases/server/client/attachments/validators.test.ts
index 4626fd13fba3..ce6c43a665a1 100644
--- a/x-pack/plugins/cases/server/client/attachments/validators.test.ts
+++ b/x-pack/plugins/cases/server/client/attachments/validators.test.ts
@@ -6,10 +6,13 @@
*/
import { validateFindCommentsPagination } from './validators';
+import { MAX_COMMENTS_PER_PAGE } from '../../../common/constants';
const ERROR_MSG =
'The number of documents is too high. Paginating through more than 10,000 documents is not possible.';
+const ERROR_MSG_PER_PAGE = `The provided perPage value was too high. The maximum allowed perPage value is ${MAX_COMMENTS_PER_PAGE}.`;
+
describe('validators', () => {
describe('validateFindCommentsPagination', () => {
it('does not throw if only page is undefined', () => {
@@ -20,20 +23,30 @@ describe('validators', () => {
expect(() => validateFindCommentsPagination({ page: 100 })).not.toThrowError();
});
+ it('does not throw if page and perPage are defined and valid', () => {
+ expect(() => validateFindCommentsPagination({ page: 2, perPage: 100 })).not.toThrowError();
+ });
+
it('returns if page and perPage are undefined', () => {
expect(() => validateFindCommentsPagination({})).not.toThrowError();
});
+ it('returns if perPage < 0', () => {
+ expect(() => validateFindCommentsPagination({ perPage: -1 })).not.toThrowError();
+ });
+
it('throws if page > 10k', () => {
expect(() => validateFindCommentsPagination({ page: 10001 })).toThrow(ERROR_MSG);
});
- it('throws if perPage > 10k', () => {
- expect(() => validateFindCommentsPagination({ perPage: 10001 })).toThrowError(ERROR_MSG);
+ it('throws if perPage > 100', () => {
+ expect(() =>
+ validateFindCommentsPagination({ perPage: MAX_COMMENTS_PER_PAGE + 1 })
+ ).toThrowError(ERROR_MSG_PER_PAGE);
});
it('throws if page * perPage > 10k', () => {
- expect(() => validateFindCommentsPagination({ page: 10, perPage: 1001 })).toThrow(ERROR_MSG);
+ expect(() => validateFindCommentsPagination({ page: 101, perPage: 100 })).toThrow(ERROR_MSG);
});
});
});
diff --git a/x-pack/plugins/cases/server/client/attachments/validators.ts b/x-pack/plugins/cases/server/client/attachments/validators.ts
index 770d9d8e88c0..ea38fa71e702 100644
--- a/x-pack/plugins/cases/server/client/attachments/validators.ts
+++ b/x-pack/plugins/cases/server/client/attachments/validators.ts
@@ -6,7 +6,7 @@
*/
import Boom from '@hapi/boom';
-import { MAX_DOCS_PER_PAGE } from '../../../common/constants';
+import { MAX_DOCS_PER_PAGE, MAX_COMMENTS_PER_PAGE } from '../../../common/constants';
import {
isCommentRequestTypeExternalReference,
isCommentRequestTypePersistableState,
@@ -51,7 +51,13 @@ export const validateFindCommentsPagination = (params?: FindCommentsQueryParams)
const pageAsNumber = params.page ?? 0;
const perPageAsNumber = params.perPage ?? 0;
- if (Math.max(pageAsNumber, perPageAsNumber, pageAsNumber * perPageAsNumber) > MAX_DOCS_PER_PAGE) {
+ if (perPageAsNumber > MAX_COMMENTS_PER_PAGE) {
+ throw Boom.badRequest(
+ `The provided perPage value was too high. The maximum allowed perPage value is ${MAX_COMMENTS_PER_PAGE}.`
+ );
+ }
+
+ if (Math.max(pageAsNumber, pageAsNumber * perPageAsNumber) > MAX_DOCS_PER_PAGE) {
throw Boom.badRequest(
'The number of documents is too high. Paginating through more than 10,000 documents is not possible.'
);
diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts
index 267f5472e6eb..6da8cfccf135 100644
--- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts
+++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts
@@ -7,7 +7,7 @@
import expect from '@kbn/expect';
import type SuperTest from 'supertest';
-import { MAX_DOCS_PER_PAGE } from '@kbn/cases-plugin/common/constants';
+import { MAX_COMMENTS_PER_PAGE } from '@kbn/cases-plugin/common/constants';
import {
Alerts,
createCaseAttachAlertAndDeleteCase,
@@ -170,7 +170,7 @@ export default ({ getService }: FtrProviderContext): void => {
supertest: supertestWithoutAuth,
caseId: postedCase.id,
query: {
- perPage: MAX_DOCS_PER_PAGE,
+ perPage: MAX_COMMENTS_PER_PAGE,
},
}),
]);
@@ -210,14 +210,14 @@ export default ({ getService }: FtrProviderContext): void => {
supertest: supertestWithoutAuth,
caseId: postedCase1.id,
query: {
- perPage: MAX_DOCS_PER_PAGE,
+ perPage: MAX_COMMENTS_PER_PAGE,
},
}),
findAttachments({
supertest: supertestWithoutAuth,
caseId: postedCase2.id,
query: {
- perPage: MAX_DOCS_PER_PAGE,
+ perPage: MAX_COMMENTS_PER_PAGE,
},
}),
]);
@@ -457,7 +457,7 @@ export default ({ getService }: FtrProviderContext): void => {
supertest: supertestWithoutAuth,
caseId: postedCase.id,
query: {
- perPage: MAX_DOCS_PER_PAGE,
+ perPage: MAX_COMMENTS_PER_PAGE,
},
auth: { user: secAllUser, space: 'space1' },
}),
diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/find_comments.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/find_comments.ts
index a218350ec95c..761959db29f6 100644
--- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/find_comments.ts
+++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/find_comments.ts
@@ -114,7 +114,7 @@ export default ({ getService }: FtrProviderContext): void => {
{ name: 'field is wrong type', queryParams: { perPage: true } },
{ name: 'field is unknown', queryParams: { foo: 'bar' } },
{ name: 'page > 10k', queryParams: { page: 10001 } },
- { name: 'perPage > 10k', queryParams: { perPage: 10001 } },
+ { name: 'perPage > 100', queryParams: { perPage: 101 } },
{ name: 'page * perPage > 10k', queryParams: { page: 2, perPage: 9001 } },
]) {
it(`400s when ${errorScenario.name}`, async () => {