mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.6] [Security Solution] [Exceptions] Fix edit the exception while adding new comment. (#145575) (#145724)
# Backport This will backport the following commits from `main` to `8.6`: - [[Security Solution] [Exceptions] Fix edit the exception while adding new comment. (#145575)](https://github.com/elastic/kibana/pull/145575) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Wafaa Nasr","email":"wafaa.nasr@elastic.co"},"sourceCommit":{"committedDate":"2022-11-18T13:35:03Z","message":"[Security Solution] [Exceptions] Fix edit the exception while adding new comment. (#145575)\n\n## Summary\r\n\r\nAddress https://github.com/elastic/kibana/issues/144523\r\n\r\n1. Fix type schema check to use `updateExceptionListItemSchema` instead\r\nof `exceptionListItemSchema` as the comments array could be empty when\r\nthe user adds the Exceptions and in Editing with adding a new comment(s)\r\nit will contain only (comment and id) in the newly created comment\r\n\r\n2. Add `removeCreatedAtCreatedByFromCommentsOnUpdate` to remove the\r\n`createdAt`, and `createdBy` from the updated exception Item if a\r\ncomment was added before to fix the `400 Schema validations` as per the\r\nbelow Schema\r\n\r\nThe\r\n`packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts`\r\n \r\n ```\r\n export const updateComment = t.intersection([\r\n t.exact(\r\n t.type({\r\n comment: NonEmptyString,\r\n })\r\n ),\r\n t.exact(\r\n t.partial({\r\n id,\r\n })\r\n ),\r\n ]);\r\n ```\r\n3. Moving tests and mocks to the `hooks` package as well add new tests\r\nfor the new `removeCreatedAtCreatedByFromCommentsOnUpdate`\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\nCo-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>","sha":"2bd2226cb259312b90ad32b1cd5618a0cc2e8b49","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team: SecuritySolution","Team:Security Solution Platform","v8.6.0","v8.7.0"],"number":145575,"url":"https://github.com/elastic/kibana/pull/145575","mergeCommit":{"message":"[Security Solution] [Exceptions] Fix edit the exception while adding new comment. (#145575)\n\n## Summary\r\n\r\nAddress https://github.com/elastic/kibana/issues/144523\r\n\r\n1. Fix type schema check to use `updateExceptionListItemSchema` instead\r\nof `exceptionListItemSchema` as the comments array could be empty when\r\nthe user adds the Exceptions and in Editing with adding a new comment(s)\r\nit will contain only (comment and id) in the newly created comment\r\n\r\n2. Add `removeCreatedAtCreatedByFromCommentsOnUpdate` to remove the\r\n`createdAt`, and `createdBy` from the updated exception Item if a\r\ncomment was added before to fix the `400 Schema validations` as per the\r\nbelow Schema\r\n\r\nThe\r\n`packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts`\r\n \r\n ```\r\n export const updateComment = t.intersection([\r\n t.exact(\r\n t.type({\r\n comment: NonEmptyString,\r\n })\r\n ),\r\n t.exact(\r\n t.partial({\r\n id,\r\n })\r\n ),\r\n ]);\r\n ```\r\n3. Moving tests and mocks to the `hooks` package as well add new tests\r\nfor the new `removeCreatedAtCreatedByFromCommentsOnUpdate`\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\nCo-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>","sha":"2bd2226cb259312b90ad32b1cd5618a0cc2e8b49"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/145575","number":145575,"mergeCommit":{"message":"[Security Solution] [Exceptions] Fix edit the exception while adding new comment. (#145575)\n\n## Summary\r\n\r\nAddress https://github.com/elastic/kibana/issues/144523\r\n\r\n1. Fix type schema check to use `updateExceptionListItemSchema` instead\r\nof `exceptionListItemSchema` as the comments array could be empty when\r\nthe user adds the Exceptions and in Editing with adding a new comment(s)\r\nit will contain only (comment and id) in the newly created comment\r\n\r\n2. Add `removeCreatedAtCreatedByFromCommentsOnUpdate` to remove the\r\n`createdAt`, and `createdBy` from the updated exception Item if a\r\ncomment was added before to fix the `400 Schema validations` as per the\r\nbelow Schema\r\n\r\nThe\r\n`packages/kbn-securitysolution-io-ts-list-types/src/common/update_comment/index.ts`\r\n \r\n ```\r\n export const updateComment = t.intersection([\r\n t.exact(\r\n t.type({\r\n comment: NonEmptyString,\r\n })\r\n ),\r\n t.exact(\r\n t.partial({\r\n id,\r\n })\r\n ),\r\n ]);\r\n ```\r\n3. Moving tests and mocks to the `hooks` package as well add new tests\r\nfor the new `removeCreatedAtCreatedByFromCommentsOnUpdate`\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n\r\nCo-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>","sha":"2bd2226cb259312b90ad32b1cd5618a0cc2e8b49"}}]}] BACKPORT--> Co-authored-by: Wafaa Nasr <wafaa.nasr@elastic.co>
This commit is contained in:
parent
4f85f53671
commit
68bd9a95e7
7 changed files with 577 additions and 6 deletions
|
@ -5,6 +5,15 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import {
|
||||
CommentsArray,
|
||||
EntriesArray,
|
||||
Entry,
|
||||
EntryMatch,
|
||||
EntryNested,
|
||||
OsTypeArray,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
export const DATE_NOW = '2020-04-20T15:25:31.830Z';
|
||||
export const USER = 'some user';
|
||||
export const ELASTIC_USER = 'elastic';
|
||||
|
@ -18,3 +27,73 @@ export const TYPE = 'ip';
|
|||
|
||||
export const VERSION = 1;
|
||||
export const IMMUTABLE = false;
|
||||
// Exception List specific
|
||||
export const ID = 'uuid_here';
|
||||
export const NAMESPACE_TYPE = 'single';
|
||||
export const OS_TYPES: OsTypeArray = ['windows'];
|
||||
export const TAGS = [];
|
||||
export const UPDATED_COMMENTS = [
|
||||
{
|
||||
comment: 'old comment',
|
||||
id: 'old_created_id',
|
||||
},
|
||||
{
|
||||
comment: 'new comment',
|
||||
id: 'new_id',
|
||||
},
|
||||
];
|
||||
export const COMMENTS = [];
|
||||
export const ENTRIES: EntriesArray = [
|
||||
{
|
||||
entries: [{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' }],
|
||||
field: 'some.parentField',
|
||||
type: 'nested',
|
||||
},
|
||||
{ field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' },
|
||||
];
|
||||
export const ITEM_ID = 'some-list-item-id';
|
||||
export const ITEM_TYPE = 'simple';
|
||||
export const LIST_ITEM_ID = 'some-list-item-id';
|
||||
// ENTRIES_WITH_IDS should only be used to mock out functionality of a collection of transforms
|
||||
// that are UI specific and useful for UI concerns that are inserted between the
|
||||
// API and the actual user interface. In some ways these might be viewed as
|
||||
// technical debt or to compensate for the differences and preferences
|
||||
// of how ReactJS might prefer data vs. how we want to model data.
|
||||
export const ENTRIES_WITH_IDS: EntriesArray = [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as EntryMatch & { id: string },
|
||||
],
|
||||
field: 'some.parentField',
|
||||
id: '123',
|
||||
type: 'nested',
|
||||
} as EntryNested & { id: string },
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as Entry & { id: string },
|
||||
];
|
||||
|
||||
export const COMMENTS_WITH_CREATEDAT_CREATEDBY: CommentsArray = [
|
||||
{
|
||||
comment: 'old comment',
|
||||
id: 'old_created_id',
|
||||
created_at: '2022-01-08T15:25:31.830Z',
|
||||
created_by: 'elastic',
|
||||
},
|
||||
{
|
||||
comment: 'new comment',
|
||||
id: 'new_id',
|
||||
created_at: '2022-05-14T15:25:31.830Z',
|
||||
created_by: 'elastic',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
import {
|
||||
COMMENTS,
|
||||
DESCRIPTION,
|
||||
ENTRIES,
|
||||
ITEM_ID,
|
||||
ITEM_TYPE,
|
||||
LIST_ID,
|
||||
META,
|
||||
NAME,
|
||||
NAMESPACE_TYPE,
|
||||
OS_TYPES,
|
||||
TAGS,
|
||||
} from '../constants.mock';
|
||||
|
||||
export const getCreateExceptionListItemSchemaMock = (): CreateExceptionListItemSchema => ({
|
||||
comments: COMMENTS,
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
item_id: undefined,
|
||||
list_id: LIST_ID,
|
||||
meta: META,
|
||||
name: NAME,
|
||||
namespace_type: NAMESPACE_TYPE,
|
||||
os_types: OS_TYPES,
|
||||
tags: TAGS,
|
||||
type: ITEM_TYPE,
|
||||
});
|
||||
|
||||
/**
|
||||
* Useful for end to end testing
|
||||
*/
|
||||
export const getCreateExceptionListItemMinimalSchemaMock = (): CreateExceptionListItemSchema => ({
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
item_id: ITEM_ID,
|
||||
list_id: LIST_ID,
|
||||
name: NAME,
|
||||
os_types: OS_TYPES,
|
||||
type: ITEM_TYPE,
|
||||
});
|
||||
|
||||
/**
|
||||
* Useful for end to end testing
|
||||
*/
|
||||
export const getCreateExceptionListItemMinimalSchemaMockWithoutId =
|
||||
(): CreateExceptionListItemSchema => ({
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
list_id: LIST_ID,
|
||||
name: NAME,
|
||||
os_types: OS_TYPES,
|
||||
type: ITEM_TYPE,
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
import {
|
||||
DESCRIPTION,
|
||||
ENTRIES,
|
||||
ID,
|
||||
ITEM_ID,
|
||||
ITEM_TYPE,
|
||||
LIST_ITEM_ID,
|
||||
META,
|
||||
NAME,
|
||||
NAMESPACE_TYPE,
|
||||
OS_TYPES,
|
||||
TAGS,
|
||||
UPDATED_COMMENTS,
|
||||
} from '../constants.mock';
|
||||
|
||||
export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({
|
||||
_version: undefined,
|
||||
comments: UPDATED_COMMENTS,
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
id: ID,
|
||||
item_id: LIST_ITEM_ID,
|
||||
meta: META,
|
||||
name: NAME,
|
||||
namespace_type: NAMESPACE_TYPE,
|
||||
os_types: ['linux'],
|
||||
tags: TAGS,
|
||||
type: ITEM_TYPE,
|
||||
});
|
||||
|
||||
/**
|
||||
* Useful for end to end tests and other mechanisms which want to fill in the values
|
||||
* after doing a get of the structure.
|
||||
*/
|
||||
export const getUpdateMinimalExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
item_id: ITEM_ID,
|
||||
name: NAME,
|
||||
os_types: OS_TYPES,
|
||||
type: ITEM_TYPE,
|
||||
});
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
import {
|
||||
COMMENTS,
|
||||
DATE_NOW,
|
||||
DESCRIPTION,
|
||||
ELASTIC_USER,
|
||||
ENTRIES,
|
||||
ITEM_ID,
|
||||
ITEM_TYPE,
|
||||
LIST_ID,
|
||||
META,
|
||||
NAME,
|
||||
NAMESPACE_TYPE,
|
||||
OS_TYPES,
|
||||
TIE_BREAKER,
|
||||
USER,
|
||||
} from '../constants.mock';
|
||||
|
||||
export const getExceptionListItemSchemaMock = (
|
||||
overrides?: Partial<ExceptionListItemSchema>
|
||||
): ExceptionListItemSchema => ({
|
||||
_version: undefined,
|
||||
comments: COMMENTS,
|
||||
created_at: DATE_NOW,
|
||||
created_by: USER,
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
id: '1',
|
||||
item_id: 'endpoint_list_item',
|
||||
list_id: 'endpoint_list_id',
|
||||
meta: META,
|
||||
name: NAME,
|
||||
namespace_type: NAMESPACE_TYPE,
|
||||
os_types: [],
|
||||
tags: ['user added string for a tag', 'malware'],
|
||||
tie_breaker_id: TIE_BREAKER,
|
||||
type: ITEM_TYPE,
|
||||
updated_at: DATE_NOW,
|
||||
updated_by: USER,
|
||||
...(overrides || {}),
|
||||
});
|
||||
|
||||
/**
|
||||
* This is useful for end to end tests where we remove the auto generated parts for comparisons
|
||||
* such as created_at, updated_at, and id.
|
||||
*/
|
||||
export const getExceptionListItemResponseMockWithoutAutoGeneratedValues =
|
||||
(): Partial<ExceptionListItemSchema> => ({
|
||||
comments: [],
|
||||
created_by: ELASTIC_USER,
|
||||
description: DESCRIPTION,
|
||||
entries: ENTRIES,
|
||||
item_id: ITEM_ID,
|
||||
list_id: LIST_ID,
|
||||
name: NAME,
|
||||
namespace_type: 'single',
|
||||
os_types: OS_TYPES,
|
||||
tags: [],
|
||||
type: ITEM_TYPE,
|
||||
updated_by: ELASTIC_USER,
|
||||
});
|
|
@ -6,9 +6,293 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type {
|
||||
CreateExceptionListItemSchema,
|
||||
Entry,
|
||||
EntryMatch,
|
||||
EntryNested,
|
||||
ExceptionListItemSchema,
|
||||
UpdateExceptionListItemSchema,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
addIdToExceptionItemEntries,
|
||||
removeIdFromExceptionItemsEntries,
|
||||
transformInput,
|
||||
transformOutput,
|
||||
} from '@kbn/securitysolution-list-hooks';
|
||||
|
||||
import { getCreateExceptionListItemSchemaMock } from '../mocks/request/create_exception_list_item_schema.mock';
|
||||
import { getUpdateExceptionListItemSchemaMock } from '../mocks/request/update_exception_list_item_schema.mock';
|
||||
import { getExceptionListItemSchemaMock } from '../mocks/response/exception_list_item_schema.mock';
|
||||
import { COMMENTS_WITH_CREATEDAT_CREATEDBY, ENTRIES_WITH_IDS } from '../mocks/constants.mock';
|
||||
|
||||
jest.mock('uuid', () => ({
|
||||
v4: jest.fn().mockReturnValue('123'),
|
||||
}));
|
||||
|
||||
describe('Exceptions transforms', () => {
|
||||
test('Tests should be ported', () => {
|
||||
// TODO: Port all the tests from: x-pack/plugins/lists/public/exceptions/transforms.test.ts here once mocks are figured out and kbn package mocks are figured out
|
||||
expect(true).toBe(true);
|
||||
describe('transformOutput', () => {
|
||||
it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => {
|
||||
const mockCreateExceptionItem = {
|
||||
...getCreateExceptionListItemSchemaMock(),
|
||||
entries: ENTRIES_WITH_IDS,
|
||||
};
|
||||
const output = transformOutput(mockCreateExceptionItem);
|
||||
const expectedOutput: CreateExceptionListItemSchema = getCreateExceptionListItemSchemaMock();
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => {
|
||||
const mockUpdateExceptionItem = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: ENTRIES_WITH_IDS,
|
||||
};
|
||||
const output = transformOutput(mockUpdateExceptionItem);
|
||||
const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock();
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
it('should return output as input with stripped createdAt and createdBy per entry - UpdateExceptionListItemSchema', () => {
|
||||
const mockUpdateExceptionItem = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: ENTRIES_WITH_IDS,
|
||||
comments: COMMENTS_WITH_CREATEDAT_CREATEDBY,
|
||||
};
|
||||
const output = transformOutput(mockUpdateExceptionItem);
|
||||
const expectedOutput: UpdateExceptionListItemSchema = getUpdateExceptionListItemSchemaMock();
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformInput', () => {
|
||||
it('should return same output as input with added ids per entry', () => {
|
||||
const mockExceptionItem = getExceptionListItemSchemaMock();
|
||||
const output = transformInput(mockExceptionItem);
|
||||
const expectedOutput: ExceptionListItemSchema = {
|
||||
...getExceptionListItemSchemaMock(),
|
||||
entries: ENTRIES_WITH_IDS,
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addIdToExceptionItemEntries', () => {
|
||||
it('should return same output as input with added ids per entry', () => {
|
||||
const mockExceptionItem: ExceptionListItemSchema = {
|
||||
...getExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
};
|
||||
const output = addIdToExceptionItemEntries(mockExceptionItem);
|
||||
const expectedOutput: ExceptionListItemSchema = {
|
||||
...getExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as Entry & { id: string },
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should return same output as input with added ids per nested entry', () => {
|
||||
const mockExceptionItem: ExceptionListItemSchema = {
|
||||
...getExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
field: 'some.parentField',
|
||||
type: 'nested',
|
||||
},
|
||||
],
|
||||
};
|
||||
const output = addIdToExceptionItemEntries(mockExceptionItem);
|
||||
const expectedOutput: ExceptionListItemSchema = {
|
||||
...getExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as EntryMatch & { id: string },
|
||||
],
|
||||
field: 'some.parentField',
|
||||
id: '123',
|
||||
type: 'nested',
|
||||
} as EntryNested & { id: string },
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeIdFromExceptionItemsEntries', () => {
|
||||
it('should return same output as input with stripped ids per entry - CreateExceptionListItemSchema', () => {
|
||||
const mockCreateExceptionItem = {
|
||||
...getCreateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as Entry & { id: string },
|
||||
],
|
||||
};
|
||||
const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem);
|
||||
const expectedOutput: CreateExceptionListItemSchema = {
|
||||
...getCreateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should return same output as input with stripped ids per nested entry - CreateExceptionListItemSchema', () => {
|
||||
const mockCreateExceptionItem = {
|
||||
...getCreateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as EntryMatch & { id: string },
|
||||
],
|
||||
field: 'some.parentField',
|
||||
id: '123',
|
||||
type: 'nested',
|
||||
} as EntryNested & { id: string },
|
||||
],
|
||||
};
|
||||
const output = removeIdFromExceptionItemsEntries(mockCreateExceptionItem);
|
||||
const expectedOutput: CreateExceptionListItemSchema = {
|
||||
...getCreateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
field: 'some.parentField',
|
||||
type: 'nested',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should return same output as input with stripped ids per entry - UpdateExceptionListItemSchema', () => {
|
||||
const mockUpdateExceptionItem = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as Entry & { id: string },
|
||||
],
|
||||
};
|
||||
const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem);
|
||||
const expectedOutput: UpdateExceptionListItemSchema = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it('should return same output as input with stripped ids per nested entry - UpdateExceptionListItemSchema', () => {
|
||||
const mockUpdateExceptionItem = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
id: '123',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
} as EntryMatch & { id: string },
|
||||
],
|
||||
field: 'some.parentField',
|
||||
id: '123',
|
||||
type: 'nested',
|
||||
} as EntryNested & { id: string },
|
||||
],
|
||||
};
|
||||
const output = removeIdFromExceptionItemsEntries(mockUpdateExceptionItem);
|
||||
const expectedOutput: UpdateExceptionListItemSchema = {
|
||||
...getUpdateExceptionListItemSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
field: 'some.parentField',
|
||||
type: 'nested',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(output).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -36,7 +36,10 @@ import type {
|
|||
export const transformOutput = (
|
||||
exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema
|
||||
): UpdateExceptionListItemSchema | ExceptionListItemSchema =>
|
||||
flow(removeIdFromExceptionItemsEntries)(exceptionItem);
|
||||
flow(
|
||||
removeCreatedAtCreatedByFromCommentsOnUpdate,
|
||||
removeIdFromExceptionItemsEntries
|
||||
)(exceptionItem);
|
||||
|
||||
export const transformNewItemOutput = (
|
||||
exceptionItem: CreateExceptionListItemSchema
|
||||
|
@ -112,3 +115,23 @@ export const removeIdFromExceptionItemsEntries = <T extends { entries: EntriesAr
|
|||
});
|
||||
return { ...exceptionItem, entries: entriesNoId };
|
||||
};
|
||||
|
||||
/**
|
||||
* This removes createdAt, createdBy from the exceptionItem if a comment was added to
|
||||
* the Exception item, and return the comment message with id to prevent creating the commet
|
||||
* twice
|
||||
* @param exceptionItem The exceptionItem to remove createdAt, createdBy from the comments array.
|
||||
* @returns exceptionItem The exceptionItem with comments do not have createdAt, createdBy.
|
||||
*/
|
||||
export const removeCreatedAtCreatedByFromCommentsOnUpdate = (
|
||||
exceptionItem: UpdateExceptionListItemSchema | ExceptionListItemSchema
|
||||
) => {
|
||||
const { comments } = exceptionItem;
|
||||
if (!comments || !comments.length) return exceptionItem;
|
||||
|
||||
const entriesNoCreatedAtAndBy = comments.map(({ comment, id }) => ({
|
||||
comment,
|
||||
id,
|
||||
}));
|
||||
return { ...exceptionItem, comments: entriesNoCreatedAtAndBy };
|
||||
};
|
||||
|
|
|
@ -27,8 +27,8 @@ import type {
|
|||
ExceptionListSchema,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
updateExceptionListItemSchema,
|
||||
ExceptionListTypeEnum,
|
||||
exceptionListItemSchema,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
import type { ExceptionsBuilderReturnExceptionItem } from '@kbn/securitysolution-list-utils';
|
||||
|
@ -237,7 +237,7 @@ const EditExceptionFlyoutComponent: React.FC<EditExceptionFlyoutProps> = ({
|
|||
|
||||
const areItemsReadyForUpdate = useCallback(
|
||||
(items: ExceptionsBuilderReturnExceptionItem[]): items is ExceptionListItemSchema[] => {
|
||||
return items.every((item) => exceptionListItemSchema.is(item));
|
||||
return items.every((item) => updateExceptionListItemSchema.is(item));
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue