diff --git a/x-pack/plugins/cases/common/api/cases/comment/index.test.ts b/x-pack/plugins/cases/common/api/cases/comment/index.test.ts index ab27b976a5f71..23ea839c5d540 100644 --- a/x-pack/plugins/cases/common/api/cases/comment/index.test.ts +++ b/x-pack/plugins/cases/common/api/cases/comment/index.test.ts @@ -31,7 +31,7 @@ import { BulkGetAttachmentsRequestRt, BulkGetAttachmentsResponseRt, } from '.'; -import { MAX_COMMENT_LENGTH } from '../../../constants'; +import { MAX_COMMENT_LENGTH, MAX_BULK_CREATE_ATTACHMENTS } from '../../../constants'; describe('Comments', () => { describe('CommentAttributesBasicRt', () => { @@ -843,6 +843,27 @@ describe('Comments', () => { right: defaultRequest, }); }); + + describe('errors', () => { + it(`throws error when attachments are more than ${MAX_BULK_CREATE_ATTACHMENTS}`, () => { + const comment = { + comment: 'Solve this fast!', + type: CommentType.user, + owner: 'cases', + }; + const attachments = Array(MAX_BULK_CREATE_ATTACHMENTS + 1).fill(comment); + + expect(PathReporter.report(BulkCreateCommentRequestRt.decode(attachments))).toContain( + `The length of the field attachments is too long. Array must be of length <= ${MAX_BULK_CREATE_ATTACHMENTS}.` + ); + }); + + it(`no errors when empty array of attachments`, () => { + expect(PathReporter.report(BulkCreateCommentRequestRt.decode([]))).toStrictEqual([ + 'No errors!', + ]); + }); + }); }); describe('BulkGetAttachmentsRequestRt', () => { diff --git a/x-pack/plugins/cases/common/api/cases/comment/index.ts b/x-pack/plugins/cases/common/api/cases/comment/index.ts index 50b93a8c70461..f23d0f82377be 100644 --- a/x-pack/plugins/cases/common/api/cases/comment/index.ts +++ b/x-pack/plugins/cases/common/api/cases/comment/index.ts @@ -10,6 +10,7 @@ import { MAX_BULK_GET_ATTACHMENTS, MAX_COMMENTS_PER_PAGE, MAX_COMMENT_LENGTH, + MAX_BULK_CREATE_ATTACHMENTS, } from '../../../constants'; import { limitedArraySchema, paginationSchema, limitedStringSchema } from '../../../schema'; import { jsonValueRt } from '../../runtime_types'; @@ -328,7 +329,12 @@ export const FindCommentsQueryParamsRt = rt.intersection([ paginationSchema({ maxPerPage: MAX_COMMENTS_PER_PAGE }), ]); -export const BulkCreateCommentRequestRt = rt.array(CommentRequestRt); +export const BulkCreateCommentRequestRt = limitedArraySchema({ + codec: CommentRequestRt, + min: 0, + max: MAX_BULK_CREATE_ATTACHMENTS, + fieldName: 'attachments', +}); export const BulkGetAttachmentsRequestRt = rt.strict({ ids: limitedArraySchema({ diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts index 540be4c149f2b..5e09a6bb1db30 100644 --- a/x-pack/plugins/cases/common/constants/index.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -125,6 +125,7 @@ export const MAX_LENGTH_PER_TAG = 256 as const; export const MAX_TAGS_PER_CASE = 200 as const; export const MAX_DELETE_IDS_LENGTH = 100 as const; export const MAX_CASES_TO_UPDATE = 100 as const; +export const MAX_BULK_CREATE_ATTACHMENTS = 100 as const; /** * Cases features diff --git a/x-pack/plugins/cases/server/client/attachments/bulk_create.test.ts b/x-pack/plugins/cases/server/client/attachments/bulk_create.test.ts index d9cb3d9ea190b..5d72eb17277b0 100644 --- a/x-pack/plugins/cases/server/client/attachments/bulk_create.test.ts +++ b/x-pack/plugins/cases/server/client/attachments/bulk_create.test.ts @@ -7,7 +7,7 @@ import { comment, actionComment } from '../../mocks'; import { createCasesClientMockArgs } from '../mocks'; -import { MAX_COMMENT_LENGTH } from '../../../common/constants'; +import { MAX_COMMENT_LENGTH, MAX_BULK_CREATE_ATTACHMENTS } from '../../../common/constants'; import { bulkCreate } from './bulk_create'; describe('bulkCreate', () => { @@ -24,6 +24,14 @@ describe('bulkCreate', () => { ).rejects.toThrow('invalid keys "foo"'); }); + it(`throws error when attachments are more than ${MAX_BULK_CREATE_ATTACHMENTS}`, async () => { + const attachments = Array(MAX_BULK_CREATE_ATTACHMENTS + 1).fill(comment); + + await expect(bulkCreate({ attachments, caseId: 'test-case' }, clientArgs)).rejects.toThrow( + `The length of the field attachments is too long. Array must be of length <= ${MAX_BULK_CREATE_ATTACHMENTS}.` + ); + }); + describe('comments', () => { it('should throw an error if the comment length is too long', async () => { const longComment = Array(MAX_COMMENT_LENGTH + 1) diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts index 0df7e207081a0..a0b626482f473 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts @@ -218,17 +218,6 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - it('should bulk create 100 file attachments when there is another attachment type in the request', async () => { - const fileRequests = [...Array(100).keys()].map(() => getFilesAttachmentReq()); - - const postedCase = await createCase(supertest, postCaseReq); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [postExternalReferenceSOReq, ...fileRequests], - }); - }); - it('should bulk create 99 file attachments when the case has a file associated to it', async () => { const postedCase = await createCase( supertestWithoutAuth, @@ -376,6 +365,23 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('400s when attempting to add more than 100 attachments', async () => { + const comment = { + type: CommentType.user, + comment: 'test', + owner: 'securitySolutionFixture', + }; + + const attachments = Array(101).fill(comment); + + await bulkCreateAttachments({ + supertest, + caseId: 'test-case-id', + params: attachments, + expectedHttpCode: 400, + }); + }); + it('400s when attempting to create a comment with a different owner than the case', async () => { const postedCase = await createCase( supertest,