Skip to content

Commit

Permalink
Fix filters
Browse files Browse the repository at this point in the history
  • Loading branch information
cnasikas committed Mar 29, 2021
1 parent 000dc84 commit 7c5fc8e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 46 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/cases/server/routes/api/cases/find_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function initFindCasesApi({ caseService, router, logger }: RouteDeps) {
return response.badRequest({ body: 'RouteHandlerContext is not registered for cases' });
}
const casesClient = await context.cases.getCasesClient();
const options = request.body as CasesFindRequest;
const options = request.query as CasesFindRequest;

return response.ok({
body: await casesClient.find({ ...options }),
Expand Down
76 changes: 52 additions & 24 deletions x-pack/plugins/cases/server/routes/api/cases/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,18 @@ export const addStatusFilter = ({
appendFilter,
type = CASE_SAVED_OBJECT,
}: {
status?: CaseStatuses;
status: CaseStatuses;
appendFilter?: KueryNode;
type?: string;
}): KueryNode => {
const filters: KueryNode[] = [];
if (status) {
filters.push(nodeBuilder.is(`${type}.attributes.status`, status));
}
filters.push(nodeBuilder.is(`${type}.attributes.status`, status));

if (appendFilter) {
filters.push(appendFilter);
}

return nodeBuilder.and(filters);
return filters.length > 1 ? nodeBuilder.and(filters) : filters[0];
};

export const buildFilter = ({
Expand All @@ -53,12 +51,17 @@ export const buildFilter = ({
operator,
type = CASE_SAVED_OBJECT,
}: {
filters: string | string[] | undefined;
filters: string | string[];
field: string;
operator: 'or' | 'and';
type?: string;
}): KueryNode => {
const filtersAsArray = Array.isArray(filters) ? filters : filters != null ? [filters] : [];
}): KueryNode | null => {
const filtersAsArray = Array.isArray(filters) ? filters : [filters];

if (filtersAsArray.length === 0) {
return null;
}

return nodeBuilder[operator](
filtersAsArray.map((filter) => nodeBuilder.is(`${type}.attributes.${field}`, filter))
);
Expand Down Expand Up @@ -105,9 +108,12 @@ export const constructQueryOptions = ({
caseType?: CaseType;
authorizationFilter?: KueryNode;
}): { case: SavedObjectFindOptionsKueryNode; subCase?: SavedObjectFindOptionsKueryNode } => {
const tagsFilter = buildFilter({ filters: tags, field: 'tags', operator: 'or' });
const kueryNodeExists = (filter: KueryNode | null | undefined): filter is KueryNode =>
filter != null;

const tagsFilter = buildFilter({ filters: tags ?? [], field: 'tags', operator: 'or' });
const reportersFilter = buildFilter({
filters: reporters,
filters: reporters ?? [],
field: 'created_by.username',
operator: 'or',
});
Expand All @@ -123,15 +129,23 @@ export const constructQueryOptions = ({
`${CASE_SAVED_OBJECT}.attributes.type`,
CaseType.individual
);
const caseFilters = addStatusFilter({
status,
appendFilter: nodeBuilder.and([tagsFilter, reportersFilter, typeFilter]),
});

const filters: KueryNode[] = [typeFilter, tagsFilter, reportersFilter].filter(
kueryNodeExists
);

const caseFilters =
status != null
? addStatusFilter({
status,
appendFilter: filters.length > 1 ? nodeBuilder.and(filters) : filters[0],
})
: undefined;

return {
case: {
filter:
authorizationFilter != null
authorizationFilter != null && caseFilters != null
? combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter)
: caseFilters,
sortField,
Expand All @@ -145,8 +159,13 @@ export const constructQueryOptions = ({
`${CASE_SAVED_OBJECT}.attributes.type`,
CaseType.collection
);
const caseFilters = nodeBuilder.and([tagsFilter, reportersFilter, typeFilter]);
const subCaseFilters = addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT });

const filters: KueryNode[] = [typeFilter, tagsFilter, reportersFilter].filter(
kueryNodeExists
);
const caseFilters = filters.length > 1 ? nodeBuilder.and(filters) : filters[0];
const subCaseFilters =
status != null ? addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT }) : undefined;

return {
case: {
Expand All @@ -158,8 +177,8 @@ export const constructQueryOptions = ({
},
subCase: {
filter:
authorizationFilter != null
? combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter)
authorizationFilter != null && subCaseFilters != null
? combineFilterWithAuthorizationFilter(subCaseFilters, authorizationFilter)
: subCaseFilters,
sortField,
},
Expand All @@ -185,10 +204,19 @@ export const constructQueryOptions = ({
CaseType.collection
);

const statusFilter = nodeBuilder.and([addStatusFilter({ status }), typeIndividual]);
const statusFilter =
status != null
? nodeBuilder.and([addStatusFilter({ status }), typeIndividual])
: typeIndividual;
const statusAndType = nodeBuilder.or([statusFilter, typeParent]);
const caseFilters = nodeBuilder.and([statusAndType, tagsFilter, reportersFilter]);
const subCaseFilters = addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT });

const filters: KueryNode[] = [statusAndType, tagsFilter, reportersFilter].filter(
kueryNodeExists
);

const caseFilters = filters.length > 1 ? nodeBuilder.and(filters) : filters[0];
const subCaseFilters =
status != null ? addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT }) : undefined;

return {
case: {
Expand All @@ -200,8 +228,8 @@ export const constructQueryOptions = ({
},
subCase: {
filter:
authorizationFilter != null
? combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter)
authorizationFilter != null && subCaseFilters != null
? combineFilterWithAuthorizationFilter(subCaseFilters, authorizationFilter)
: subCaseFilters,
sortField,
},
Expand Down
50 changes: 29 additions & 21 deletions x-pack/plugins/cases/server/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { cloneDeep } from 'lodash';
import {
KibanaRequest,
Logger,
Expand All @@ -25,7 +26,6 @@ import { AuthenticatedUser, SecurityPluginSetup } from '../../../security/server
import {
ESCaseAttributes,
CommentAttributes,
SavedObjectFindOptions,
User,
CommentPatchAttributes,
SubCaseAttributes,
Expand Down Expand Up @@ -82,20 +82,20 @@ interface GetSubCasesArgs extends ClientArgs {
interface FindCommentsArgs {
client: SavedObjectsClientContract;
id: string | string[];
options?: SavedObjectFindOptions;
options?: SavedObjectFindOptionsKueryNode;
}

interface FindCaseCommentsArgs {
client: SavedObjectsClientContract;
id: string | string[];
options?: SavedObjectFindOptions;
options?: SavedObjectFindOptionsKueryNode;
includeSubCaseComments?: boolean;
}

interface FindSubCaseCommentsArgs {
client: SavedObjectsClientContract;
id: string | string[];
options?: SavedObjectFindOptions;
options?: SavedObjectFindOptionsKueryNode;
}

interface FindCasesArgs extends ClientArgs {
Expand Down Expand Up @@ -186,7 +186,7 @@ interface FindCommentsByAssociationArgs {
client: SavedObjectsClientContract;
id: string | string[];
associationType: AssociationType;
options?: SavedObjectFindOptions;
options?: SavedObjectFindOptionsKueryNode;
}

interface Collection {
Expand Down Expand Up @@ -419,7 +419,7 @@ export class CaseService implements CaseServiceSetup {
if (ENABLE_CASE_CONNECTOR && subCaseOptions) {
subCasesTotal = await this.findSubCaseStatusStats({
client,
options: subCaseOptions,
options: cloneDeep(subCaseOptions),
ids: caseIds,
});
}
Expand Down Expand Up @@ -493,7 +493,13 @@ export class CaseService implements CaseServiceSetup {
associationType,
id: ids,
options: {
filter: `(${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.alert} OR ${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.generatedAlert})`,
filter: nodeBuilder.or([
nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert),
nodeBuilder.is(
`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`,
CommentType.generatedAlert
),
]),
},
});

Expand Down Expand Up @@ -768,7 +774,7 @@ export class CaseService implements CaseServiceSetup {
this.log.debug(`Attempting to find cases`);
return await client.find({
sortField: defaultSortField,
...options,
...cloneDeep(options),
type: CASE_SAVED_OBJECT,
});
} catch (error) {
Expand All @@ -788,7 +794,7 @@ export class CaseService implements CaseServiceSetup {
if (options?.page !== undefined || options?.perPage !== undefined) {
return client.find({
sortField: defaultSortField,
...options,
...cloneDeep(options),
type: SUB_CASE_SAVED_OBJECT,
});
}
Expand All @@ -798,14 +804,14 @@ export class CaseService implements CaseServiceSetup {
page: 1,
perPage: 1,
sortField: defaultSortField,
...options,
...cloneDeep(options),
type: SUB_CASE_SAVED_OBJECT,
});
return client.find({
page: 1,
perPage: stats.total,
sortField: defaultSortField,
...options,
...cloneDeep(options),
type: SUB_CASE_SAVED_OBJECT,
});
} catch (error) {
Expand Down Expand Up @@ -875,7 +881,7 @@ export class CaseService implements CaseServiceSetup {
return client.find({
type: CASE_COMMENT_SAVED_OBJECT,
sortField: defaultSortField,
...options,
...cloneDeep(options),
});
}
// get the total number of comments that are in ES then we'll grab them all in one go
Expand All @@ -886,15 +892,15 @@ export class CaseService implements CaseServiceSetup {
perPage: 1,
sortField: defaultSortField,
// spread the options after so the caller can override the default behavior if they want
...options,
...cloneDeep(options),
});

return client.find({
type: CASE_COMMENT_SAVED_OBJECT,
page: 1,
perPage: stats.total,
sortField: defaultSortField,
...options,
...cloneDeep(options),
});
} catch (error) {
this.log.error(`Error on GET all comments for ${JSON.stringify(id)}: ${error}`);
Expand Down Expand Up @@ -929,13 +935,15 @@ export class CaseService implements CaseServiceSetup {
let filter: KueryNode | undefined;
if (!includeSubCaseComments) {
// if other filters were passed in then combine them to filter out sub case comments
filter = nodeBuilder.and([
options?.filter,
nodeBuilder.is(
`${CASE_COMMENT_SAVED_OBJECT}.attributes.associationType`,
AssociationType.case
),
]);
const associationFilter = nodeBuilder.is(
`${CASE_COMMENT_SAVED_OBJECT}.attributes.associationType`,
AssociationType.case
);

filter =
options?.filter != null
? nodeBuilder.and([options?.filter, associationFilter])
: associationFilter;
}

this.log.debug(`Attempting to GET all comments for case caseID ${JSON.stringify(id)}`);
Expand Down

0 comments on commit 7c5fc8e

Please sign in to comment.