From dd1022236350cd31ac6dc0b397f77911d06aace0 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Tue, 4 Jul 2023 12:40:04 +0200 Subject: [PATCH 1/7] add guardrails and tests for post and patch comment --- .../cases/common/api/cases/comment/index.ts | 28 ++++- .../plugins/cases/common/constants/index.ts | 1 + .../server/client/attachments/add.test.ts | 29 +++++ .../client/attachments/bulk_create.test.ts | 78 +++++++++++++- .../server/client/attachments/update.test.ts | 100 ++++++++++++++++++ x-pack/plugins/cases/server/mocks.ts | 16 +++ .../tests/common/comments/patch_comment.ts | 67 ++++++++++++ .../tests/common/comments/post_comment.ts | 43 ++++++++ 8 files changed, 360 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/cases/server/client/attachments/update.test.ts 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 f688dc24fdf85..e733eeadf4e7f 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,8 @@ import { jsonValueRt } from '../../runtime_types'; import { NumberFromString } from '../../saved_object'; import { UserRt } from '../../user'; +import { limitedStringSchema } from '../../../schema'; +import { MAX_COMMENT_LENGTH } from '../../../constants'; export * from './files'; @@ -192,7 +194,31 @@ const BasicCommentRequestRt = rt.union([ PersistableStateAttachmentRt, ]); -export const CommentRequestRt = rt.union([BasicCommentRequestRt, ExternalReferenceSORt]); +export const CommentRequestRt = rt.union([ + rt.strict({ + comment: limitedStringSchema({ fieldName: 'comment', min: 1, max: MAX_COMMENT_LENGTH }), + type: rt.literal(CommentType.user), + owner: rt.string, + }), + AlertCommentRequestRt, + rt.strict({ + type: rt.literal(CommentType.actions), + comment: limitedStringSchema({ fieldName: 'comment', min: 1, max: MAX_COMMENT_LENGTH }), + actions: rt.strict({ + targets: rt.array( + rt.strict({ + hostname: rt.string, + endpointId: rt.string, + }) + ), + type: rt.string, + }), + owner: rt.string, + }), + ExternalReferenceNoSORt, + ExternalReferenceSORt, + PersistableStateAttachmentRt, +]); export const CommentRequestWithoutRefsRt = rt.union([ BasicCommentRequestRt, diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts index bee8ff9f3b17e..02d4645c8f55d 100644 --- a/x-pack/plugins/cases/common/constants/index.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -117,6 +117,7 @@ export const MAX_REPORTERS_FILTER_LENGTH = 100 as const; export const MAX_TITLE_LENGTH = 160 as const; export const MAX_CATEGORY_LENGTH = 50 as const; export const MAX_DESCRIPTION_LENGTH = 30000 as const; +export const MAX_COMMENT_LENGTH = 30000 as const; 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; diff --git a/x-pack/plugins/cases/server/client/attachments/add.test.ts b/x-pack/plugins/cases/server/client/attachments/add.test.ts index 0e39ff30a65ec..86646d0c36306 100644 --- a/x-pack/plugins/cases/server/client/attachments/add.test.ts +++ b/x-pack/plugins/cases/server/client/attachments/add.test.ts @@ -7,6 +7,7 @@ import { comment } from '../../mocks'; import { createCasesClientMockArgs } from '../mocks'; +import { MAX_COMMENT_LENGTH } from '../../../common/constants'; import { addComment } from './add'; describe('addComment', () => { @@ -22,4 +23,32 @@ describe('addComment', () => { addComment({ comment: { ...comment, foo: 'bar' }, caseId: 'test-case' }, clientArgs) ).rejects.toThrow('invalid keys "foo"'); }); + + it('should throw an error if the comment length is too long', async () => { + const longComment = Array(MAX_COMMENT_LENGTH + 1) + .fill('x') + .toString(); + + await expect( + addComment({ comment: { ...comment, comment: longComment }, caseId: 'test-case' }, clientArgs) + ).rejects.toThrow( + `Failed while adding a comment to case id: test-case error: Error: The length of the comment is too long. The maximum length is ${MAX_COMMENT_LENGTH}.` + ); + }); + + it('should throw an error if the comment is an empty string', async () => { + await expect( + addComment({ comment: { ...comment, comment: '' }, caseId: 'test-case' }, clientArgs) + ).rejects.toThrow( + 'Failed while adding a comment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); + + it('should throw an error if the description is a string with empty characters', async () => { + await expect( + addComment({ comment: { ...comment, comment: ' ' }, caseId: 'test-case' }, clientArgs) + ).rejects.toThrow( + 'Failed while adding a comment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); }); 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 7d9cdcf150a20..d9cb3d9ea190b 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 @@ -5,8 +5,9 @@ * 2.0. */ -import { comment } from '../../mocks'; +import { comment, actionComment } from '../../mocks'; import { createCasesClientMockArgs } from '../mocks'; +import { MAX_COMMENT_LENGTH } from '../../../common/constants'; import { bulkCreate } from './bulk_create'; describe('bulkCreate', () => { @@ -22,4 +23,79 @@ describe('bulkCreate', () => { bulkCreate({ attachments: [{ ...comment, foo: 'bar' }], caseId: 'test-case' }, clientArgs) ).rejects.toThrow('invalid keys "foo"'); }); + + describe('comments', () => { + it('should throw an error if the comment length is too long', async () => { + const longComment = Array(MAX_COMMENT_LENGTH + 1) + .fill('x') + .toString(); + + await expect( + bulkCreate( + { attachments: [{ ...comment, comment: longComment }], caseId: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + `Failed while bulk creating attachment to case id: test-case error: Error: The length of the comment is too long. The maximum length is ${MAX_COMMENT_LENGTH}.` + ); + }); + + it('should throw an error if the comment is an empty string', async () => { + await expect( + bulkCreate({ attachments: [{ ...comment, comment: '' }], caseId: 'test-case' }, clientArgs) + ).rejects.toThrow( + 'Failed while bulk creating attachment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); + + it('should throw an error if the description is a string with empty characters', async () => { + await expect( + bulkCreate( + { attachments: [{ ...comment, comment: ' ' }], caseId: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed while bulk creating attachment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); + }); + + describe('actions', () => { + it('should throw an error if the comment length is too long', async () => { + const longComment = Array(MAX_COMMENT_LENGTH + 1) + .fill('x') + .toString(); + + await expect( + bulkCreate( + { attachments: [{ ...actionComment, comment: longComment }], caseId: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + `Failed while bulk creating attachment to case id: test-case error: Error: The length of the comment is too long. The maximum length is ${MAX_COMMENT_LENGTH}.` + ); + }); + + it('should throw an error if the comment is an empty string', async () => { + await expect( + bulkCreate( + { attachments: [{ ...actionComment, comment: '' }], caseId: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed while bulk creating attachment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); + + it('should throw an error if the description is a string with empty characters', async () => { + await expect( + bulkCreate( + { attachments: [{ ...actionComment, comment: ' ' }], caseId: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed while bulk creating attachment to case id: test-case error: Error: The comment field cannot be an empty string.' + ); + }); + }); }); diff --git a/x-pack/plugins/cases/server/client/attachments/update.test.ts b/x-pack/plugins/cases/server/client/attachments/update.test.ts new file mode 100644 index 0000000000000..c3ebb40d396d5 --- /dev/null +++ b/x-pack/plugins/cases/server/client/attachments/update.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { comment, actionComment } from '../../mocks'; +import { createCasesClientMockArgs } from '../mocks'; +import { MAX_COMMENT_LENGTH } from '../../../common/constants'; +import { update } from './update'; + +describe('update', () => { + const clientArgs = createCasesClientMockArgs(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('comments', () => { + const updateComment = { ...comment, id: 'comment-id', version: 'WzAsMV0=' }; + it('should throw an error if the comment length is too long', async () => { + const longComment = Array(MAX_COMMENT_LENGTH + 1) + .fill('x') + .toString(); + + await expect( + update( + { updateRequest: { ...updateComment, comment: longComment }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + `Failed to patch comment case id: test-case: Error: The length of the comment is too long. The maximum length is ${MAX_COMMENT_LENGTH}.` + ); + }); + + it('should throw an error if the comment is an empty string', async () => { + await expect( + update( + { updateRequest: { ...updateComment, comment: '' }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed to patch comment case id: test-case: Error: The comment field cannot be an empty string.' + ); + }); + + it('should throw an error if the description is a string with empty characters', async () => { + await expect( + update( + { updateRequest: { ...updateComment, comment: ' ' }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed to patch comment case id: test-case: Error: The comment field cannot be an empty string.' + ); + }); + }); + + describe('actions', () => { + const updateActionComment = { ...actionComment, id: 'comment-id', version: 'WzAsMV0=' }; + + it('should throw an error if the comment length is too long', async () => { + const longComment = Array(MAX_COMMENT_LENGTH + 1) + .fill('x') + .toString(); + + await expect( + update( + { updateRequest: { ...updateActionComment, comment: longComment }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + `Failed to patch comment case id: test-case: Error: The length of the comment is too long. The maximum length is ${MAX_COMMENT_LENGTH}.` + ); + }); + + it('should throw an error if the comment is an empty string', async () => { + await expect( + update( + { updateRequest: { ...updateActionComment, comment: '' }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed to patch comment case id: test-case: Error: The comment field cannot be an empty string.' + ); + }); + + it('should throw an error if the description is a string with empty characters', async () => { + await expect( + update( + { updateRequest: { ...updateActionComment, comment: ' ' }, caseID: 'test-case' }, + clientArgs + ) + ).rejects.toThrow( + 'Failed to patch comment case id: test-case: Error: The comment field cannot be an empty string.' + ); + }); + }); +}); diff --git a/x-pack/plugins/cases/server/mocks.ts b/x-pack/plugins/cases/server/mocks.ts index 479873f7c0a9e..8eacf10c59e15 100644 --- a/x-pack/plugins/cases/server/mocks.ts +++ b/x-pack/plugins/cases/server/mocks.ts @@ -9,6 +9,7 @@ import type { SavedObject } from '@kbn/core/server'; import type { CasePostRequest, CommentAttributes, + CommentRequestActionsType, CommentRequestAlertType, CommentRequestUserType, ConnectorMappings, @@ -664,6 +665,21 @@ export const comment: CommentRequestUserType = { owner: SECURITY_SOLUTION_OWNER, }; +export const actionComment: CommentRequestActionsType = { + type: CommentType.actions, + comment: 'I just isolated the host!', + actions: { + targets: [ + { + hostname: 'host1', + endpointId: '001', + }, + ], + type: 'isolate', + }, + owner: 'cases', +}; + export const alertComment: CommentRequestAlertType = { alertId: 'alert-id-1', index: 'alert-index-1', diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/patch_comment.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/patch_comment.ts index fc7d86306fc41..16029e3f84615 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/patch_comment.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/patch_comment.ts @@ -173,6 +173,73 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('unhappy path - 400s when comment is too long', async () => { + const postedCase = await createCase(supertest, postCaseReq); + const patchedCase = await createComment({ + supertest, + caseId: postedCase.id, + params: postCommentUserReq, + }); + const longComment = Array(30001).fill('a').toString(); + + await updateComment({ + supertest, + caseId: postedCase.id, + req: { + id: patchedCase.comments![0].id, + version: patchedCase.comments![0].version, + type: CommentType.user, + comment: longComment, + owner: 'securitySolutionFixture', + }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when comment is empty', async () => { + const postedCase = await createCase(supertest, postCaseReq); + const patchedCase = await createComment({ + supertest, + caseId: postedCase.id, + params: postCommentUserReq, + }); + + await updateComment({ + supertest, + caseId: postedCase.id, + req: { + id: patchedCase.comments![0].id, + version: patchedCase.comments![0].version, + type: CommentType.user, + comment: '', + owner: 'securitySolutionFixture', + }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when comment is a string of empty characters', async () => { + const postedCase = await createCase(supertest, postCaseReq); + const patchedCase = await createComment({ + supertest, + caseId: postedCase.id, + params: postCommentUserReq, + }); + + await updateComment({ + supertest, + caseId: postedCase.id, + req: { + id: patchedCase.comments![0].id, + version: patchedCase.comments![0].version, + type: CommentType.user, + comment: ' ', + owner: 'securitySolutionFixture', + }, + expectedHttpCode: 400, + }); + }); + it('unhappy path - 400s when trying to change comment type', async () => { const postedCase = await createCase(supertest, postCaseReq); const patchedCase = await createComment({ diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts index 34854939b4771..8851a95c6ebc3 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts @@ -274,6 +274,49 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('400s when adding too long comment', async () => { + const postedCase = await createCase(supertest, postCaseReq); + const longComment = Array(30001).fill('a').toString(); + + await createComment({ + supertest, + caseId: postedCase.id, + // @ts-expect-error + params: { + comment: longComment, + }, + expectedHttpCode: 400, + }); + }); + + it('400s when adding empty comment', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + await createComment({ + supertest, + caseId: postedCase.id, + // @ts-expect-error + params: { + comment: '', + }, + expectedHttpCode: 400, + }); + }); + + it('400s when adding a comment with only empty characters', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + await createComment({ + supertest, + caseId: postedCase.id, + // @ts-expect-error + params: { + comment: ' ', + }, + expectedHttpCode: 400, + }); + }); + it('400s when adding excess attributes for type user', async () => { const postedCase = await createCase(supertest, postCaseReq); From f87deb5b92f811ea45f41c9602645da7ee86bec4 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:58:45 +0200 Subject: [PATCH 2/7] update the docs --- x-pack/plugins/cases/docs/openapi/bundled.json | 2 ++ x-pack/plugins/cases/docs/openapi/bundled.yaml | 2 ++ .../components/schemas/add_user_comment_request_properties.yaml | 1 + .../schemas/update_user_comment_request_properties.yaml | 1 + 4 files changed, 6 insertions(+) diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json index 4d6905006c08d..e50a84556f37b 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.json +++ b/x-pack/plugins/cases/docs/openapi/bundled.json @@ -5568,6 +5568,7 @@ "comment": { "description": "The new comment. It is required only when `type` is `user`.", "type": "string", + "maxLength": 30000, "example": "A new comment." }, "owner": { @@ -5657,6 +5658,7 @@ "comment": { "description": "The new comment. It is required only when `type` is `user`.", "type": "string", + "maxLength": 30000, "example": "A new comment." }, "id": { diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml index 7608a44f3e45e..92227b16fe9ce 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.yaml +++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml @@ -3606,6 +3606,7 @@ components: comment: description: The new comment. It is required only when `type` is `user`. type: string + maxLength: 30000 example: A new comment. owner: $ref: '#/components/schemas/owners' @@ -3672,6 +3673,7 @@ components: comment: description: The new comment. It is required only when `type` is `user`. type: string + maxLength: 30000 example: A new comment. id: type: string diff --git a/x-pack/plugins/cases/docs/openapi/components/schemas/add_user_comment_request_properties.yaml b/x-pack/plugins/cases/docs/openapi/components/schemas/add_user_comment_request_properties.yaml index 40efb7f945f45..beac63c377ade 100644 --- a/x-pack/plugins/cases/docs/openapi/components/schemas/add_user_comment_request_properties.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/schemas/add_user_comment_request_properties.yaml @@ -5,6 +5,7 @@ properties: comment: description: The new comment. It is required only when `type` is `user`. type: string + maxLength: 30000 example: A new comment. owner: $ref: 'owners.yaml' diff --git a/x-pack/plugins/cases/docs/openapi/components/schemas/update_user_comment_request_properties.yaml b/x-pack/plugins/cases/docs/openapi/components/schemas/update_user_comment_request_properties.yaml index 22fb76d9bba74..a83050e93eaaf 100644 --- a/x-pack/plugins/cases/docs/openapi/components/schemas/update_user_comment_request_properties.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/schemas/update_user_comment_request_properties.yaml @@ -5,6 +5,7 @@ properties: comment: description: The new comment. It is required only when `type` is `user`. type: string + maxLength: 30000 example: A new comment. id: type: string From c71948402a42786027badbdbc99cd7554d9f2af3 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:03:18 +0200 Subject: [PATCH 3/7] PR feedback --- .../common/api/cases/comment/index.test.ts | 18 ++++++++++++++++++ .../server/client/attachments/add.test.ts | 4 +--- .../common/internal/bulk_create_attachments.ts | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) 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 b0f99125226c3..353f78cb10331 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 @@ -29,6 +29,7 @@ import { BulkGetAttachmentsRequestRt, BulkGetAttachmentsResponseRt, } from '.'; +import { MAX_COMMENT_LENGTH } from '../../../constants'; describe('Comments', () => { describe('CommentAttributesBasicRt', () => { @@ -340,6 +341,23 @@ describe('Comments', () => { right: defaultRequest, }); }); + + it.skip('throws error when comment is too long', () => { + const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); + + expect(CommentRequestRt.decode({ ...defaultRequest, comment: longComment })).toMatchObject({ + _tag: 'Left', + left: [{ + context:[{ + actual: { + ...defaultRequest, + comment: longComment, + message: "The length of the comment is too long. The maximum length is 30000." + } + }] + }] + }); + }); }); describe('CommentRt', () => { diff --git a/x-pack/plugins/cases/server/client/attachments/add.test.ts b/x-pack/plugins/cases/server/client/attachments/add.test.ts index 86646d0c36306..b78ec1219088b 100644 --- a/x-pack/plugins/cases/server/client/attachments/add.test.ts +++ b/x-pack/plugins/cases/server/client/attachments/add.test.ts @@ -25,9 +25,7 @@ describe('addComment', () => { }); it('should throw an error if the comment length is too long', async () => { - const longComment = Array(MAX_COMMENT_LENGTH + 1) - .fill('x') - .toString(); + const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); await expect( addComment({ comment: { ...comment, comment: longComment }, caseId: 'test-case' }, clientArgs) 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 6788cc26fef94..0df7e207081a0 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 @@ -441,6 +441,23 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('400s when comment is too long', async () => { + const longComment = 'x'.repeat(30001); + + await bulkCreateAttachments({ + supertest, + caseId: 'case-id', + params: [ + { + type: CommentType.user, + comment: longComment, + owner: 'securitySolutionFixture', + }, + ], + expectedHttpCode: 400, + }); + }); + it('400s when adding excess attributes for type user', async () => { const postedCase = await createCase(supertest, postCaseReq); From 74868c00d8d1fb39f0628b867e976380a49e0bfc Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 5 Jul 2023 14:07:54 +0000 Subject: [PATCH 4/7] [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' --- .../common/api/cases/comment/index.test.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) 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 353f78cb10331..ce6b0d4dcd247 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 @@ -347,15 +347,19 @@ describe('Comments', () => { expect(CommentRequestRt.decode({ ...defaultRequest, comment: longComment })).toMatchObject({ _tag: 'Left', - left: [{ - context:[{ - actual: { - ...defaultRequest, - comment: longComment, - message: "The length of the comment is too long. The maximum length is 30000." - } - }] - }] + left: [ + { + context: [ + { + actual: { + ...defaultRequest, + comment: longComment, + message: 'The length of the comment is too long. The maximum length is 30000.', + }, + }, + ], + }, + ], }); }); }); From a3795f67990bbbf024c454dc3d0a4bc189675e15 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:40:20 +0200 Subject: [PATCH 5/7] added path reporter to check validation for commentRequestRt --- .../common/api/cases/comment/index.test.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) 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 353f78cb10331..f840e47ec5e65 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 @@ -5,6 +5,8 @@ * 2.0. */ +import { PathReporter } from 'io-ts/lib/PathReporter'; + import { CommentAttributesBasicRt, CommentType, @@ -342,21 +344,12 @@ describe('Comments', () => { }); }); - it.skip('throws error when comment is too long', () => { + it('throws error when comment is too long', () => { const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); - expect(CommentRequestRt.decode({ ...defaultRequest, comment: longComment })).toMatchObject({ - _tag: 'Left', - left: [{ - context:[{ - actual: { - ...defaultRequest, - comment: longComment, - message: "The length of the comment is too long. The maximum length is 30000." - } - }] - }] - }); + expect( + PathReporter.report(CommentRequestRt.decode({ ...defaultRequest, comment: longComment })) + ).toContain('The length of the comment is too long. The maximum length is 30000.'); }); }); From 480adefe3de41afd7275b3d43ba025adb46cc93e Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:23:36 +0200 Subject: [PATCH 6/7] added tests for commentRequestRt --- .../common/api/cases/comment/index.test.ts | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) 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 f840e47ec5e65..ab27b976a5f71 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 @@ -326,6 +326,7 @@ describe('Comments', () => { type: CommentType.user, owner: 'cases', }; + it('has expected attributes in request', () => { const query = CommentRequestRt.decode(defaultRequest); @@ -344,12 +345,66 @@ describe('Comments', () => { }); }); - it('throws error when comment is too long', () => { - const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); + describe('errors', () => { + describe('commentType: user', () => { + it('throws error when comment is too long', () => { + const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); + + expect( + PathReporter.report( + CommentRequestRt.decode({ ...defaultRequest, comment: longComment }) + ) + ).toContain('The length of the comment is too long. The maximum length is 30000.'); + }); + + it('throws error when comment is empty', () => { + expect( + PathReporter.report(CommentRequestRt.decode({ ...defaultRequest, comment: '' })) + ).toContain('The comment field cannot be an empty string.'); + }); + + it('throws error when comment string of empty characters', () => { + expect( + PathReporter.report(CommentRequestRt.decode({ ...defaultRequest, comment: ' ' })) + ).toContain('The comment field cannot be an empty string.'); + }); + }); + + describe('commentType: action', () => { + const request = { + type: CommentType.actions, + actions: { + targets: [ + { + hostname: 'host1', + endpointId: '001', + }, + ], + type: 'isolate', + }, + owner: 'cases', + }; + + it('throws error when comment is too long', () => { + const longComment = 'x'.repeat(MAX_COMMENT_LENGTH + 1); - expect( - PathReporter.report(CommentRequestRt.decode({ ...defaultRequest, comment: longComment })) - ).toContain('The length of the comment is too long. The maximum length is 30000.'); + expect( + PathReporter.report(CommentRequestRt.decode({ ...request, comment: longComment })) + ).toContain('The length of the comment is too long. The maximum length is 30000.'); + }); + + it('throws error when comment is empty', () => { + expect( + PathReporter.report(CommentRequestRt.decode({ ...request, comment: '' })) + ).toContain('The comment field cannot be an empty string.'); + }); + + it('throws error when comment string of empty characters', () => { + expect( + PathReporter.report(CommentRequestRt.decode({ ...request, comment: ' ' })) + ).toContain('The comment field cannot be an empty string.'); + }); + }); }); }); From 3ca8625864cbb11d659802787eba6e375e1a9df8 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:42:03 +0200 Subject: [PATCH 7/7] lint fix --- x-pack/plugins/cases/common/api/cases/comment/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 c6ce0b2dd9ebc..50b93a8c70461 100644 --- a/x-pack/plugins/cases/common/api/cases/comment/index.ts +++ b/x-pack/plugins/cases/common/api/cases/comment/index.ts @@ -6,13 +6,15 @@ */ import * as rt from 'io-ts'; -import { MAX_BULK_GET_ATTACHMENTS, MAX_COMMENTS_PER_PAGE } from '../../../constants'; -import { limitedArraySchema, paginationSchema } from '../../../schema'; +import { + MAX_BULK_GET_ATTACHMENTS, + MAX_COMMENTS_PER_PAGE, + MAX_COMMENT_LENGTH, +} from '../../../constants'; +import { limitedArraySchema, paginationSchema, limitedStringSchema } from '../../../schema'; import { jsonValueRt } from '../../runtime_types'; import { UserRt } from '../../user'; -import { limitedStringSchema } from '../../../schema'; -import { MAX_COMMENT_LENGTH } from '../../../constants'; export * from './files';