"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.deleteCases = deleteCases; exports.getFileEntities = void 0; var _boom = require("@hapi/boom"); var _pMap = _interopRequireDefault(require("p-map")); var _lodash = require("lodash"); var _api = require("../../../common/types/api"); var _api2 = require("../../../common/api"); var _constants = require("../../../common/constants"); var _error = require("../../common/error"); var _authorization = require("../../authorization"); var _files = require("../files"); /* * 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. */ /** * Deletes the specified cases and their attachments. */ async function deleteCases(ids, clientArgs) { const { services: { caseService, attachmentService, userActionService, alertsService }, logger, authorization, fileService } = clientArgs; try { const caseIds = (0, _api2.decodeWithExcessOrThrow)(_api.CasesDeleteRequestRt)(ids); const cases = await caseService.getCases({ caseIds }); const entities = new Map(); for (const theCase of cases.saved_objects) { // bulkGet can return an error. if (theCase.error != null) { throw (0, _error.createCaseError)({ message: `Failed to delete cases ids: ${JSON.stringify(ids)}: ${theCase.error.error}`, error: new _boom.Boom(theCase.error.message, { statusCode: theCase.error.statusCode }), logger }); } entities.set(theCase.id, { id: theCase.id, owner: theCase.attributes.owner }); } const fileEntities = await getFileEntities(ids, fileService); await authorization.ensureAuthorized({ operation: _authorization.Operations.deleteCase, entities: [...Array.from(entities.values()), ...fileEntities] }); const attachmentIds = await attachmentService.getter.getAttachmentIdsForCases({ caseIds: ids }); const userActionIds = await userActionService.getUserActionIdsForCases(ids); const bulkDeleteEntities = [...ids.map(id => ({ id, type: _constants.CASE_SAVED_OBJECT })), ...attachmentIds.map(id => ({ id, type: _constants.CASE_COMMENT_SAVED_OBJECT })), ...userActionIds.map(id => ({ id, type: _constants.CASE_USER_ACTION_SAVED_OBJECT }))]; const fileIds = fileEntities.map(entity => entity.id); await Promise.all([(0, _files.deleteFiles)(fileIds, fileService), caseService.bulkDeleteCaseEntities({ entities: bulkDeleteEntities, options: { refresh: 'wait_for' } }), alertsService.removeCaseIdsFromAllAlerts({ caseIds: ids })]); await userActionService.creator.bulkAuditLogCaseDeletion(cases.saved_objects.map(caseInfo => caseInfo.id)); } catch (error) { throw (0, _error.createCaseError)({ message: `Failed to delete cases ids: ${JSON.stringify(ids)}: ${error}`, error, logger }); } } const getFileEntities = async (caseIds, fileService) => { // using 50 just to be safe, each case can have 100 files = 50 * 100 = 5000 which is half the max number of docs that // the client can request const chunkSize = _constants.MAX_FILES_PER_CASE / 2; const chunkedIds = (0, _lodash.chunk)(caseIds, chunkSize); const entityResults = await (0, _pMap.default)(chunkedIds, async ids => { const findRes = await fileService.find({ perPage: _constants.MAX_DOCS_PER_PAGE, meta: { caseIds: ids } }); const fileEntities = (0, _files.createFileEntities)(findRes.files); return fileEntities; }); const entities = entityResults.flatMap(res => res); return entities; }; exports.getFileEntities = getFileEntities;