import { validate } from '@kbn/securitysolution-io-ts-utils' ; import { transformError } from '@kbn/securitysolution-es-utils' ; import { EntriesArray , ExceptionListItemSchema , FoundExceptionListSchema , deleteListSchema , exceptionListItemSchema , listSchema , } from '@kbn/securitysolution-io-ts-list-types' ; import { getSavedObjectType } from '@kbn/securitysolution-list-utils' ; import { LIST_URL } from '@kbn/securitysolution-list-constants' ; import type { ListsPluginRouter } from '../types' ; import { ExceptionListClient } from '../services/exception_lists/exception_list_client' ; import { escapeQuotes } from '../services/utils/escape_query' ; import { buildRouteValidation , buildSiemResponse } from './utils' ; import { getExceptionListClient , getListClient } from '.' ; export const deleteListRoute = ( router ) : void => { router . delete ( { options : { tags : [ 'access:lists-all' ] , } , path : LIST_URL , validate : { query : buildRouteValidation ( deleteListSchema ) , } , } , async ( context , request , response ) => { const siemResponse = buildSiemResponse ( response ) ; try { const lists = getListClient ( context ) ; const exceptionLists = getExceptionListClient ( context ) ; const { id , deleteReferences , ignoreReferences } = request . query ; let deleteExceptionItemResponses ; if ( ! ignoreReferences ) { const referencedExceptionListItems = await exceptionLists . findValueListExceptionListItems ( { page : 1 , perPage : 10000 , sortField : undefined , sortOrder : undefined , valueListId : id , } ) ; if ( referencedExceptionListItems ?. data ?. length ) { if ( deleteReferences ) { deleteExceptionItemResponses = await Promise . all ( referencedExceptionListItems . data . map ( async ( listItem ) => { const remainingEntries = listItem . entries . filter ( ( e ) => e ?. list ?. id !== id ) ; if ( remainingEntries . length === 0 ) { return deleteExceptionListItem ( exceptionLists , listItem ) ; } else { return updateExceptionListItems ( exceptionLists , listItem , remainingEntries ) ; } } ) ) ; } else { const referencedExceptionLists = await getReferencedExceptionLists ( exceptionLists , referencedExceptionListItems . data ) ; const refError = `Value list '${ id }' is referenced in existing exception list(s)` ; const references = referencedExceptionListItems . data . map ( ( item ) => ( { exception_item : item , exception_list : referencedExceptionLists . data . find ( ( l ) => l . list_id === item . list_id ) , } ) ) ; return siemResponse . error ( { body : { error : { message : refError , references , value_list_id : id , } , } , statusCode : 409 , } ) ; } } } const deleted = await lists . deleteList ( { id } ) ; if ( deleted == null ) { return siemResponse . error ( { body : `list id: "${ id }" was not found` , statusCode : 404 , } ) ; } else { const [ validated , errors ] = validate ( deleted , listSchema ) ; if ( errors != null ) { return siemResponse . error ( { body : errors , statusCode : 500 } ) ; } else { return response . ok ( { body : validated ?? { deleteItemResponses : deleteExceptionItemResponses , } , } ) ; } } } catch ( err ) { const error = transformError ( err ) ; return siemResponse . error ( { body : error . message , statusCode : error . statusCode , } ) ; } } ) ; } ; param exceptionLists param exceptionListItems const getReferencedExceptionLists = async ( exceptionLists , exceptionListItems ) : Promise < FoundExceptionListSchema > => { const filter = exceptionListItems . map ( ( item ) => `${ getSavedObjectType ( { namespaceType : item . namespace_type , } ) }.attributes.list_id: "${ escapeQuotes ( item . list_id ) }"` ) . join ( ' OR ' ) ; return exceptionLists . findExceptionList ( { filter : `(${ filter })` , namespaceType : [ 'agnostic' , 'single' ] , page : 1 , perPage : 10000 , sortField : undefined , sortOrder : undefined , } ) ; } ; param exceptionLists param listItem const deleteExceptionListItem = async ( exceptionLists , listItem ) : Promise < unknown > => { const deletedExceptionListItem = await exceptionLists . deleteExceptionListItem ( { id : listItem . id , itemId : listItem . item_id , namespaceType : listItem . namespace_type , } ) ; if ( deletedExceptionListItem == null ) { return { body : `list item with id: "${ listItem . id }" not found` , statusCode : 404 , } ; } else { const [ validated , errors ] = validate ( deletedExceptionListItem , exceptionListItemSchema ) ; if ( errors != null ) { return { body : errors , statusCode : 500 } ; } else { return { body : validated ?? { } } ; } } } ; param exceptionLists param listItem param remainingEntries const updateExceptionListItems = async ( exceptionLists , listItem , remainingEntries ) : Promise < unknown > => { const updateExceptionListItem = await exceptionLists . updateExceptionListItem ( { _version : listItem . _version , comments : listItem . comments , description : listItem . description , entries : remainingEntries , id : listItem . id , itemId : listItem . item_id , meta : listItem . meta , name : listItem . name , namespaceType : listItem . namespace_type , osTypes : listItem . os_types , tags : listItem . tags , type : listItem . type , } ) ; if ( updateExceptionListItem == null ) { return { body : `exception list item id: "${ listItem . item_id }" does not exist` , statusCode : 404 , } ; } else { const [ validated , errors ] = validate ( updateExceptionListItem , exceptionListItemSchema ) ; if ( errors != null ) { return { body : errors , statusCode : 500 } ; } else { return { body : validated ?? { } } ; } } } ;