Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SIEM] [Cases] External services not getting all comments bug fix #65307

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions x-pack/plugins/siem/public/containers/case/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,11 @@ export const REOPENED_CASES = ({
defaultMessage: 'Reopened {totalCases, plural, =1 {"{caseTitle}"} other {{totalCases} cases}}',
});

export const TAG_FETCH_FAILURE = i18n.translate(
'xpack.siem.containers.case.tagFetchFailDescription',
{
defaultMessage: 'Failed to fetch Tags',
}
);

export const SUCCESS_SEND_TO_EXTERNAL_SERVICE = i18n.translate(
'xpack.siem.containers.case.pushToExterService',
{
defaultMessage: 'Successfully sent to ServiceNow',
}
);
export const SUCCESS_SEND_TO_EXTERNAL_SERVICE = (serviceName: string) =>
i18n.translate('xpack.siem.containers.case.pushToExternalService', {
values: { serviceName },
defaultMessage: 'Successfully sent to { serviceName }',
});

export const ERROR_PUSH_TO_SERVICE = i18n.translate(
'xpack.siem.case.configure.errorPushingToService',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,14 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [],
hasDataToPush: false,
},
},
});
});

it('Correctly marks first/last index - hasDataToPush: true', () => {
it('Correctly marks first/last index and comment id - hasDataToPush: true', () => {
const userActions = [
...caseUserActions,
getUserAction(['pushed'], 'push-to-service'),
Expand All @@ -142,6 +143,83 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [userActions[userActions.length - 1].commentId],
hasDataToPush: true,
},
},
});
});

it('Correctly marks first/last index and multiple comment ids, both needs push', () => {
const userActions = [
...caseUserActions,
getUserAction(['pushed'], 'push-to-service'),
getUserAction(['comment'], 'create'),
{ ...getUserAction(['comment'], 'create'), commentId: 'muahaha' },
];
const result = getPushedInfo(userActions, '123');
expect(result).toEqual({
hasDataToPush: true,
caseServices: {
'123': {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [
userActions[userActions.length - 2].commentId,
userActions[userActions.length - 1].commentId,
],
hasDataToPush: true,
},
},
});
});

it('Correctly marks first/last index and multiple comment ids, one needs push', () => {
const userActions = [
...caseUserActions,
getUserAction(['pushed'], 'push-to-service'),
getUserAction(['comment'], 'create'),
getUserAction(['pushed'], 'push-to-service'),
{ ...getUserAction(['comment'], 'create'), commentId: 'muahaha' },
];
const result = getPushedInfo(userActions, '123');
expect(result).toEqual({
hasDataToPush: true,
caseServices: {
'123': {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 5,
commentsToUpdate: [userActions[userActions.length - 1].commentId],
hasDataToPush: true,
},
},
});
});

it('Correctly marks first/last index and multiple comment ids, one needs push and one needs update', () => {
const userActions = [
...caseUserActions,
getUserAction(['pushed'], 'push-to-service'),
getUserAction(['comment'], 'create'),
getUserAction(['pushed'], 'push-to-service'),
{ ...getUserAction(['comment'], 'create'), commentId: 'muahaha' },
getUserAction(['comment'], 'update'),
getUserAction(['comment'], 'update'),
];
const result = getPushedInfo(userActions, '123');
expect(result).toEqual({
hasDataToPush: true,
caseServices: {
'123': {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 5,
commentsToUpdate: [
userActions[userActions.length - 3].commentId,
userActions[userActions.length - 1].commentId,
],
hasDataToPush: true,
},
},
Expand All @@ -162,6 +240,7 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [],
hasDataToPush: false,
},
},
Expand All @@ -182,11 +261,34 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 5,
commentsToUpdate: [],
hasDataToPush: false,
},
},
});
});
it('Correctly handles comment update with multiple push actions', () => {
const userActions = [
...caseUserActions,
getUserAction(['pushed'], 'push-to-service'),
getUserAction(['comment'], 'create'),
getUserAction(['pushed'], 'push-to-service'),
getUserAction(['comment'], 'update'),
];
const result = getPushedInfo(userActions, '123');
expect(result).toEqual({
hasDataToPush: true,
caseServices: {
'123': {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 5,
commentsToUpdate: [userActions[userActions.length - 1].commentId],
hasDataToPush: true,
},
},
});
});

it('Multiple connector tracking - hasDataToPush: true', () => {
const pushAction123 = getUserAction(['pushed'], 'push-to-service');
Expand Down Expand Up @@ -215,6 +317,7 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [userActions[userActions.length - 2].commentId],
hasDataToPush: true,
},
'456': {
Expand All @@ -224,6 +327,7 @@ describe('useGetCaseUserActions', () => {
externalId: 'other_external_id',
firstPushIndex: 5,
lastPushIndex: 5,
commentsToUpdate: [],
hasDataToPush: false,
},
},
Expand Down Expand Up @@ -257,6 +361,7 @@ describe('useGetCaseUserActions', () => {
...basicPush,
firstPushIndex: 3,
lastPushIndex: 3,
commentsToUpdate: [userActions[userActions.length - 2].commentId],
hasDataToPush: true,
},
'456': {
Expand All @@ -266,6 +371,7 @@ describe('useGetCaseUserActions', () => {
externalId: 'other_external_id',
firstPushIndex: 5,
lastPushIndex: 5,
commentsToUpdate: [],
hasDataToPush: false,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { CaseFullExternalService } from '../../../../case/common/api/cases';
interface CaseService extends CaseExternalService {
firstPushIndex: number;
lastPushIndex: number;
commentsToUpdate: string[];
hasDataToPush: boolean;
}

Expand Down Expand Up @@ -69,11 +70,30 @@ export const getPushedInfo = (
.action !== 'push-to-service'
);
};
const commentsAndIndex = caseUserActions.reduce<
Array<{
commentId: string;
commentIndex: number;
}>
>(
(bacc, mua, index) =>
mua.actionField[0] === 'comment' && mua.commentId != null
? [
...bacc,
{
commentId: mua.commentId,
commentIndex: index,
},
]
: bacc,
[]
);

const caseServices = caseUserActions.reduce<CaseServices>((acc, cua, i) => {
if (cua.action !== 'push-to-service') {
return acc;
}

const externalService = getExternalService(`${cua.newValue}`);
if (externalService === null) {
return acc;
Expand All @@ -87,6 +107,18 @@ export const getPushedInfo = (
...acc[externalService.connectorId],
...externalService,
lastPushIndex: i,
commentsToUpdate: commentsAndIndex.reduce<string[]>(
stephmilovic marked this conversation as resolved.
Show resolved Hide resolved
(bacc, currentComment) =>
currentComment.commentIndex > i
? bacc.indexOf(currentComment.commentId) > -1
? [
...bacc.filter(e => e !== currentComment.commentId),
currentComment.commentId,
]
: [...bacc, currentComment.commentId]
: bacc,
[]
),
},
}
: {
Expand All @@ -95,6 +127,18 @@ export const getPushedInfo = (
firstPushIndex: i,
lastPushIndex: i,
hasDataToPush: hasDataToPushForConnector(externalService.connectorId),
commentsToUpdate: commentsAndIndex.reduce<string[]>(
stephmilovic marked this conversation as resolved.
Show resolved Hide resolved
(bacc, currentComment) =>
currentComment.commentIndex > i
? bacc.indexOf(currentComment.commentId) > -1
? [
...bacc.filter(e => e !== currentComment.commentId),
currentComment.commentId,
]
: [...bacc, currentComment.commentId]
: bacc,
[]
),
},
}),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
serviceConnectorUser,
} from './mock';
import * as api from './api';
import { CaseServices } from './use_get_case_user_actions';

jest.mock('./api');

Expand All @@ -32,6 +33,7 @@ describe('usePostPushToService', () => {
...basicPush,
firstPushIndex: 1,
lastPushIndex: 1,
commentsToUpdate: [basicComment.id],
hasDataToPush: false,
},
},
Expand Down Expand Up @@ -64,13 +66,15 @@ describe('usePostPushToService', () => {
...basicPush,
firstPushIndex: 1,
lastPushIndex: 1,
commentsToUpdate: [basicComment.id],
hasDataToPush: true,
},
'456': {
...basicPush,
connectorId: '456',
externalId: 'other_external_id',
firstPushIndex: 4,
commentsToUpdate: [basicComment.id],
lastPushIndex: 6,
hasDataToPush: false,
},
Expand Down Expand Up @@ -127,6 +131,31 @@ describe('usePostPushToService', () => {
await waitForNextUpdate();
expect(spyOnPushToService).toBeCalledWith(
samplePush.connectorId,
formatServiceRequestData(basicCase, '123', sampleCaseServices as CaseServices),
abortCtrl.signal
);
});
});

it('calls pushToService with correct arguments when no push history', async () => {
const samplePush2 = {
caseId: pushedCase.id,
caseServices: {},
connectorName: 'connector name',
connectorId: 'none',
updateCase,
};
const spyOnPushToService = jest.spyOn(api, 'pushToService');

await act(async () => {
const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() =>
usePostPushToService()
);
await waitForNextUpdate();
result.current.postPushToService(samplePush2);
await waitForNextUpdate();
expect(spyOnPushToService).toBeCalledWith(
samplePush2.connectorId,
formatServiceRequestData(basicCase, 'none', {}),
abortCtrl.signal
);
Expand Down
Loading