Skip to content

Commit cfb9c83

Browse files
[Security Solution][Case][Bug] Removing empty collections when filtering on status (#92048) (#93096)
* Removing empty collections when not filtering on status * Fixing add comment response Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
1 parent 8235656 commit cfb9c83

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

x-pack/plugins/case/server/services/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
CaseType,
3333
CaseResponse,
3434
caseTypeField,
35+
CasesFindRequest,
3536
} from '../../common/api';
3637
import { combineFilters, defaultSortField, groupTotalAlertsByID } from '../common';
3738
import { defaultPage, defaultPerPage } from '../routes/api';
@@ -194,6 +195,8 @@ interface CasesMapWithPageInfo {
194195
perPage: number;
195196
}
196197

198+
type FindCaseOptions = CasesFindRequest & SavedObjectFindOptions;
199+
197200
export interface CaseServiceSetup {
198201
deleteCase(args: GetCaseArgs): Promise<{}>;
199202
deleteComment(args: GetCommentArgs): Promise<{}>;
@@ -271,7 +274,7 @@ export class CaseService implements CaseServiceSetup {
271274
subCaseOptions,
272275
}: {
273276
client: SavedObjectsClientContract;
274-
caseOptions: SavedObjectFindOptions;
277+
caseOptions: FindCaseOptions;
275278
subCaseOptions?: SavedObjectFindOptions;
276279
}): Promise<CasesMapWithPageInfo> {
277280
const cases = await this.findCases({
@@ -291,10 +294,20 @@ export class CaseService implements CaseServiceSetup {
291294
const subCasesForCase = subCasesResp.subCasesMap.get(caseInfo.id);
292295

293296
/**
294-
* This will include empty collections unless the query explicitly requested type === CaseType.individual, in which
295-
* case we'd not have any collections anyway.
297+
* If this case is an individual add it to the return map
298+
* If it is a collection and it has sub cases add it to the return map
299+
* If it is a collection and it does not have sub cases, check and see if we're filtering on a status,
300+
* if we're filtering on a status then exclude the empty collection from the results
301+
* if we're not filtering on a status then include the empty collection (that way we can display all the collections
302+
* when the UI isn't doing any filtering)
296303
*/
297-
accMap.set(caseInfo.id, { case: caseInfo, subCases: subCasesForCase });
304+
if (
305+
caseInfo.attributes.type === CaseType.individual ||
306+
subCasesForCase !== undefined ||
307+
!caseOptions.status
308+
) {
309+
accMap.set(caseInfo.id, { case: caseInfo, subCases: subCasesForCase });
310+
}
298311
return accMap;
299312
}, new Map<string, Collection>());
300313

x-pack/test/case_api_integration/basic/tests/cases/find_cases.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,9 @@ export default ({ getService }: FtrProviderContext): void => {
304304
.get(`${CASES_URL}/_find?sortOrder=asc&status=open`)
305305
.expect(200);
306306

307-
expect(body.total).to.eql(2);
307+
// since we're filtering on status and the collection only has an in-progress case, it should only return the
308+
// individual case that has the open status and no collections
309+
expect(body.total).to.eql(1);
308310
expect(body.count_closed_cases).to.eql(1);
309311
expect(body.count_open_cases).to.eql(1);
310312
expect(body.count_in_progress_cases).to.eql(1);
@@ -353,7 +355,7 @@ export default ({ getService }: FtrProviderContext): void => {
353355
expect(body.count_in_progress_cases).to.eql(0);
354356
});
355357

356-
it('correctly counts stats including a collection without sub cases', async () => {
358+
it('correctly counts stats including a collection without sub cases when not filtering on status', async () => {
357359
// delete the sub case on the collection so that it doesn't have any sub cases
358360
await supertest
359361
.delete(`${SUB_CASES_PATCH_DEL_URL}?ids=["${collection.newSubCaseInfo.subCases![0].id}"]`)
@@ -365,11 +367,62 @@ export default ({ getService }: FtrProviderContext): void => {
365367
.get(`${CASES_URL}/_find?sortOrder=asc`)
366368
.expect(200);
367369

370+
// it should include the collection without sub cases because we did not pass in a filter on status
371+
expect(body.total).to.eql(3);
372+
expect(body.count_closed_cases).to.eql(1);
373+
expect(body.count_open_cases).to.eql(1);
374+
expect(body.count_in_progress_cases).to.eql(0);
375+
});
376+
377+
it('correctly counts stats including a collection without sub cases when filtering on tags', async () => {
378+
// delete the sub case on the collection so that it doesn't have any sub cases
379+
await supertest
380+
.delete(`${SUB_CASES_PATCH_DEL_URL}?ids=["${collection.newSubCaseInfo.subCases![0].id}"]`)
381+
.set('kbn-xsrf', 'true')
382+
.send()
383+
.expect(204);
384+
385+
const { body }: { body: CasesFindResponse } = await supertest
386+
.get(`${CASES_URL}/_find?sortOrder=asc&tags=defacement`)
387+
.expect(200);
388+
389+
// it should include the collection without sub cases because we did not pass in a filter on status
368390
expect(body.total).to.eql(3);
369391
expect(body.count_closed_cases).to.eql(1);
370392
expect(body.count_open_cases).to.eql(1);
371393
expect(body.count_in_progress_cases).to.eql(0);
372394
});
395+
396+
it('does not return collections without sub cases matching the requested status', async () => {
397+
const { body }: { body: CasesFindResponse } = await supertest
398+
.get(`${CASES_URL}/_find?sortOrder=asc&status=closed`)
399+
.expect(200);
400+
401+
// it should not include the collection that has a sub case as in-progress
402+
expect(body.total).to.eql(1);
403+
expect(body.count_closed_cases).to.eql(1);
404+
expect(body.count_open_cases).to.eql(1);
405+
expect(body.count_in_progress_cases).to.eql(1);
406+
});
407+
408+
it('does not return empty collections when filtering on status', async () => {
409+
// delete the sub case on the collection so that it doesn't have any sub cases
410+
await supertest
411+
.delete(`${SUB_CASES_PATCH_DEL_URL}?ids=["${collection.newSubCaseInfo.subCases![0].id}"]`)
412+
.set('kbn-xsrf', 'true')
413+
.send()
414+
.expect(204);
415+
416+
const { body }: { body: CasesFindResponse } = await supertest
417+
.get(`${CASES_URL}/_find?sortOrder=asc&status=closed`)
418+
.expect(200);
419+
420+
// it should not include the collection that has a sub case as in-progress
421+
expect(body.total).to.eql(1);
422+
expect(body.count_closed_cases).to.eql(1);
423+
expect(body.count_open_cases).to.eql(1);
424+
expect(body.count_in_progress_cases).to.eql(0);
425+
});
373426
});
374427

375428
it('unhappy path - 400s when bad query supplied', async () => {

0 commit comments

Comments
 (0)