diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/api.ts index e98c25869048..7d5ae53b78ff 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/api.ts @@ -19,7 +19,9 @@ import { ServiceConnectorCaseResponse, ActionTypeExecutorResult, } from '../../../../../../plugins/case/common/api'; + import { KibanaServices } from '../../lib/kibana'; + import { ActionLicense, AllCases, @@ -30,7 +32,9 @@ import { SortFieldCase, CaseUserActions, } from './types'; + import { CASES_URL } from './constants'; + import { convertToCamelCase, convertAllCasesToCamel, @@ -43,12 +47,17 @@ import { decodeServiceConnectorCaseResponse, } from './utils'; -export const getCase = async (caseId: string, includeComments: boolean = true): Promise => { +export const getCase = async ( + caseId: string, + includeComments: boolean = true, + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/${caseId}`, { method: 'GET', query: { includeComments, }, + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; @@ -64,9 +73,10 @@ export const getCasesStatus = async (signal: AbortSignal): Promise return convertToCamelCase(decodeCasesStatusResponse(response)); }; -export const getTags = async (): Promise => { +export const getTags = async (signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/tags`, { method: 'GET', + signal, }); return response ?? []; }; @@ -106,6 +116,7 @@ export const getCases = async ({ sortField: SortFieldCase.createdAt, sortOrder: 'desc', }, + signal, }: FetchCasesProps): Promise => { const query = { reporters: filterOptions.reporters.map(r => r.username), @@ -117,14 +128,16 @@ export const getCases = async ({ const response = await KibanaServices.get().http.fetch(`${CASES_URL}/_find`, { method: 'GET', query, + signal, }); return convertAllCasesToCamel(decodeCasesFindResponse(response)); }; -export const postCase = async (newCase: CasePostRequest): Promise => { +export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'POST', body: JSON.stringify(newCase), + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; @@ -132,29 +145,40 @@ export const postCase = async (newCase: CasePostRequest): Promise => { export const patchCase = async ( caseId: string, updatedCase: Pick, - version: string + version: string, + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases: [{ ...updatedCase, id: caseId, version }] }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const patchCasesStatus = async (cases: BulkUpdateStatus[]): Promise => { +export const patchCasesStatus = async ( + cases: BulkUpdateStatus[], + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const postComment = async (newComment: CommentRequest, caseId: string): Promise => { +export const postComment = async ( + newComment: CommentRequest, + caseId: string, + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'POST', body: JSON.stringify(newComment), + signal, } ); return convertToCamelCase(decodeCaseResponse(response)); @@ -164,22 +188,25 @@ export const patchComment = async ( caseId: string, commentId: string, commentUpdate: string, - version: string + version: string, + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'PATCH', body: JSON.stringify({ comment: commentUpdate, id: commentId, version }), + signal, } ); return convertToCamelCase(decodeCaseResponse(response)); }; -export const deleteCases = async (caseIds: string[]): Promise => { +export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'DELETE', query: { ids: JSON.stringify(caseIds) }, + signal, }); return response === 'true' ? true : false; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/types.ts b/x-pack/legacy/plugins/siem/public/containers/case/types.ts index bbbb13788d53..bb215d6ac271 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/types.ts @@ -93,7 +93,7 @@ export interface ElasticUser { readonly username: string; } -export interface FetchCasesProps { +export interface FetchCasesProps extends ApiProps { queryParams?: QueryParams; filterOptions?: FilterOptions; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx index 77d779ab906c..f1129bae9f53 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx @@ -66,10 +66,12 @@ export const useUpdateCases = (): UseUpdateCase => { const dispatchUpdateCases = useCallback((cases: BulkUpdateStatus[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const patchData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await patchCasesStatus(cases); + await patchCasesStatus(cases, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -87,6 +89,7 @@ export const useUpdateCases = (): UseUpdateCase => { patchData(); return () => { cancel = true; + abortCtrl.abort(); }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx index d5a3b3cf9314..b44e01d06aca 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx @@ -74,10 +74,12 @@ export const useDeleteCases = (): UseDeleteCase => { const dispatchDeleteCases = useCallback((caseIds: string[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const deleteData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await deleteCases(caseIds); + await deleteCases(caseIds, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -94,6 +96,7 @@ export const useDeleteCases = (): UseDeleteCase => { }; deleteData(); return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx index 506be62614c1..835fb7153dc9 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx @@ -92,10 +92,12 @@ export const useGetCase = (caseId: string): UseGetCase => { const callFetch = useCallback(async () => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getCase(caseId); + const response = await getCase(caseId, true, abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -113,6 +115,7 @@ export const useGetCase = (caseId: string): UseGetCase => { fetchData(); return () => { didCancel = true; + abortCtrl.abort(); }; }, [caseId]); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx index ae7b8f3c043f..323dc23e1b24 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx @@ -149,12 +149,15 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const fetchCases = useCallback((filterOptions: FilterOptions, queryParams: QueryParams) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'cases' }); try { const response = await getCases({ filterOptions, queryParams, + signal: abortCtrl.signal, }); if (!didCancel) { dispatch({ @@ -175,6 +178,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); @@ -187,13 +191,17 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const dispatchUpdateCaseProperty = useCallback( ({ updateKey, updateValue, caseId, refetchCasesStatus, version }: UpdateCase) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'caseUpdate' }); try { await patchCase( caseId, { [updateKey]: updateValue }, - version ?? '' // saved object versions are typed as string | undefined, hope that's not true + // saved object versions are typed as string | undefined, hope that's not true + version ?? '', + abortCtrl.signal ); if (!didCancel) { dispatch({ type: 'FETCH_UPDATE_CASE_SUCCESS' }); @@ -209,6 +217,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx index e3657f5b09da..b41d5aab5c07 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx @@ -57,10 +57,12 @@ export const useGetTags = (): TagsState => { useEffect(() => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getTags(); + const response = await getTags(abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -77,6 +79,7 @@ export const useGetTags = (): TagsState => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx index 2ad7a0847320..0e01364721dc 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx @@ -61,9 +61,11 @@ export const usePostCase = (): UsePostCase => { const postMyCase = useCallback(async (data: CasePostRequest) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT' }); - const response = await postCase(data); + const response = await postCase(data, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', @@ -81,6 +83,7 @@ export const usePostCase = (): UsePostCase => { } } return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx index 86b7f92ace5a..207b05814717 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx @@ -55,9 +55,11 @@ export const usePostComment = (caseId: string): UsePostComment => { const postMyComment = useCallback( async (data: CommentRequest, updateCase: (newCase: Case) => void) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT' }); - const response = await postComment(data, caseId); + const response = await postComment(data, caseId, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS' }); updateCase(response); @@ -73,6 +75,7 @@ export const usePostComment = (caseId: string): UsePostComment => { } } return () => { + abortCtrl.abort(); cancel = true; }; }, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx index d00755a9f242..03e10249317e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx @@ -87,7 +87,7 @@ export const usePostPushToService = (): UsePostPushToService => { const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT' }); - const casePushData = await getCase(caseId); + const casePushData = await getCase(caseId, true, abortCtrl.signal); const responseService = await pushToService( connectorId, formatServiceRequestData(casePushData), diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx index d1015d3f7425..85ad4fd3fc47 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx @@ -76,9 +76,16 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => const dispatchUpdateCaseProperty = useCallback( async ({ fetchCaseUserActions, updateKey, updateValue, updateCase, version }: UpdateByKey) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT', payload: updateKey }); - const response = await patchCase(caseId, { [updateKey]: updateValue }, version); + const response = await patchCase( + caseId, + { [updateKey]: updateValue }, + version, + abortCtrl.signal + ); if (!cancel) { if (fetchCaseUserActions != null) { fetchCaseUserActions(caseId); @@ -100,6 +107,7 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => } return () => { cancel = true; + abortCtrl.abort(); }; }, [] diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx index b83ed2c01708..faf9649a705c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx @@ -81,9 +81,16 @@ export const useUpdateComment = (): UseUpdateComment => { version, }: UpdateComment) => { let cancel = false; + const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT', payload: commentId }); - const response = await patchComment(caseId, commentId, commentUpdate, version); + const response = await patchComment( + caseId, + commentId, + commentUpdate, + version, + abortCtrl.signal + ); if (!cancel) { updateCase(response); fetchUserActions(); @@ -101,6 +108,7 @@ export const useUpdateComment = (): UseUpdateComment => { } return () => { cancel = true; + abortCtrl.abort(); }; }, []