Skip to content

Commit

Permalink
Allowing deletion of collections (elastic#91926)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathan-buttner authored Feb 19, 2021
1 parent eea6f82 commit a108469
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 45 deletions.
44 changes: 0 additions & 44 deletions x-pack/plugins/case/server/routes/api/cases/delete_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down Expand Up @@ -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);
});
});
});
};

0 comments on commit a108469

Please sign in to comment.