Allowing deletion of collections (#91926)

This commit is contained in:
Jonathan Buttner 2021-02-19 10:50:35 -05:00 committed by GitHub
parent eea6f82e4e
commit a108469ec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 45 deletions

View file

@ -8,43 +8,12 @@
import { schema } from '@kbn/config-schema';
import { SavedObjectsClientContract } from 'src/core/server';
import { CaseType } from '../../../../common/api';
import { buildCaseUserActionItem } from '../../../services/user_actions/helpers';
import { RouteDeps } from '../types';
import { wrapError } from '../utils';
import { CASES_URL } from '../../../../common/constants';
import { CaseServiceSetup } from '../../../services';
async function unremovableCases({
caseService,
client,
ids,
force,
}: {
caseService: CaseServiceSetup;
client: SavedObjectsClientContract;
ids: string[];
force: boolean | undefined;
}): Promise<string[]> {
// if the force flag was included then we can skip checking whether the cases are collections and go ahead
// and delete them
if (force) {
return [];
}
const cases = await caseService.getCases({ caseIds: ids, client });
const parentCases = cases.saved_objects.filter(
/**
* getCases will return an array of saved_objects and some can be successful cases where as others
* might have failed to find the ID. If it fails to find it, it will set the error field but not
* the attributes so check that we didn't receive an error.
*/
(caseObj) => !caseObj.error && caseObj.attributes.type === CaseType.collection
);
return parentCases.map((parentCase) => parentCase.id);
}
async function deleteSubCases({
caseService,
client,
@ -84,25 +53,12 @@ export function initDeleteCasesApi({ caseService, router, userActionService }: R
validate: {
query: schema.object({
ids: schema.arrayOf(schema.string()),
force: schema.maybe(schema.boolean()),
}),
},
},
async (context, request, response) => {
try {
const client = context.core.savedObjects.client;
const unremovable = await unremovableCases({
caseService,
client,
ids: request.query.ids,
force: request.query.force,
});
if (unremovable.length > 0) {
return response.badRequest({
body: `Case IDs: [${unremovable.join(' ,')}] are not removable`,
});
}
await Promise.all(
request.query.ids.map((id) =>
caseService.deleteCase({

View file

@ -10,7 +10,17 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { CASES_URL } from '../../../../../plugins/case/common/constants';
import { postCaseReq, postCommentUserReq } from '../../../common/lib/mock';
import { deleteCases, deleteCasesUserActions, deleteComments } from '../../../common/lib/utils';
import {
createCaseAction,
createSubCase,
deleteAllCaseItems,
deleteCaseAction,
deleteCases,
deleteCasesUserActions,
deleteComments,
} from '../../../common/lib/utils';
import { getSubCaseDetailsUrl } from '../../../../../plugins/case/common/api/helpers';
import { CollectionWithSubCaseResponse } from '../../../../../plugins/case/common/api';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext): void => {
@ -79,5 +89,64 @@ export default ({ getService }: FtrProviderContext): void => {
.send()
.expect(404);
});
describe('sub cases', () => {
let actionID: string;
before(async () => {
actionID = await createCaseAction(supertest);
});
after(async () => {
await deleteCaseAction(supertest, actionID);
});
afterEach(async () => {
await deleteAllCaseItems(es);
});
it('should delete the sub cases when deleting a collection', async () => {
const { newSubCaseInfo: caseInfo } = await createSubCase({ supertest, actionID });
expect(caseInfo.subCase?.id).to.not.eql(undefined);
const { body } = await supertest
.delete(`${CASES_URL}?ids=["${caseInfo.id}"]`)
.set('kbn-xsrf', 'true')
.send()
.expect(204);
expect(body).to.eql({});
await supertest
.get(getSubCaseDetailsUrl(caseInfo.id, caseInfo.subCase!.id))
.send()
.expect(404);
});
it(`should delete a sub case's comments when that case gets deleted`, async () => {
const { newSubCaseInfo: caseInfo } = await createSubCase({ supertest, actionID });
expect(caseInfo.subCase?.id).to.not.eql(undefined);
// there should be two comments on the sub case now
const {
body: patchedCaseWithSubCase,
}: { body: CollectionWithSubCaseResponse } = await supertest
.post(`${CASES_URL}/${caseInfo.id}/comments`)
.set('kbn-xsrf', 'true')
.query({ subCaseID: caseInfo.subCase!.id })
.send(postCommentUserReq)
.expect(200);
const subCaseCommentUrl = `${CASES_URL}/${patchedCaseWithSubCase.id}/comments/${
patchedCaseWithSubCase.subCase!.comments![1].id
}`;
// make sure we can get the second comment
await supertest.get(subCaseCommentUrl).set('kbn-xsrf', 'true').send().expect(200);
await supertest
.delete(`${CASES_URL}?ids=["${caseInfo.id}"]`)
.set('kbn-xsrf', 'true')
.send()
.expect(204);
await supertest.get(subCaseCommentUrl).set('kbn-xsrf', 'true').send().expect(404);
});
});
});
};