mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Cases] Limit category filter in find cases API (#159989)
## Summary This PR limits the number of categories by which we can filter calls to the find cases API. The limit is now 100. --------- Co-authored-by: lcawl <lcawley@elastic.co>
This commit is contained in:
parent
d475b12a1f
commit
599e2311a6
8 changed files with 76 additions and 4 deletions
|
@ -724,7 +724,9 @@ Any modifications made to this file will be overwritten.
|
|||
<div class="field-items">
|
||||
<div class="param">assignees (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Query Parameter</span> — Filters the returned cases by assignees. Valid values are <code>none</code> or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null </div><div class="param">defaultSearchOperator (optional)</div>
|
||||
<div class="param-desc"><span class="param-type">Query Parameter</span> — Filters the returned cases by assignees. Valid values are <code>none</code> or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null </div><div class="param">category (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Query Parameter</span> — Filters the returned cases by category. Limited to 100 categories. default: null </div><div class="param">defaultSearchOperator (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Query Parameter</span> — The default operator to use for the simple_query_string. default: OR </div><div class="param">from (optional)</div>
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ export const MAX_DOCS_PER_PAGE = 10000 as const;
|
|||
export const MAX_BULK_GET_ATTACHMENTS = MAX_DOCS_PER_PAGE;
|
||||
export const MAX_CONCURRENT_SEARCHES = 10 as const;
|
||||
export const MAX_BULK_GET_CASES = 1000 as const;
|
||||
export const MAX_CATEGORY_FILTER_LENGTH = 100 as const;
|
||||
|
||||
/**
|
||||
* Validation
|
||||
|
|
|
@ -236,6 +236,25 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "category",
|
||||
"in": "query",
|
||||
"description": "Filters the returned cases by category. Limited to 100 categories.",
|
||||
"schema": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"example": "my-category"
|
||||
},
|
||||
{
|
||||
"name": "defaultSearchOperator",
|
||||
"in": "query",
|
||||
|
|
|
@ -140,6 +140,16 @@ paths:
|
|||
- type: array
|
||||
items:
|
||||
type: string
|
||||
- name: category
|
||||
in: query
|
||||
description: Filters the returned cases by category. Limited to 100 categories.
|
||||
schema:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
example: my-category
|
||||
- name: defaultSearchOperator
|
||||
in: query
|
||||
description: The default operator to use for the simple_query_string.
|
||||
|
|
|
@ -18,6 +18,16 @@ get:
|
|||
- type: array
|
||||
items:
|
||||
type: string
|
||||
- name: category
|
||||
in: query
|
||||
description: Filters the returned cases by category. Limited to 100 categories.
|
||||
schema:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
example: my-category
|
||||
- name: defaultSearchOperator
|
||||
in: query
|
||||
description: The default operator to use for the simple_query_string.
|
||||
|
|
|
@ -8,6 +8,7 @@ import { v1 as uuidv1 } from 'uuid';
|
|||
|
||||
import type { Case } from '../../../common/api';
|
||||
|
||||
import { MAX_CATEGORY_FILTER_LENGTH } from '../../../common/constants';
|
||||
import { flattenCaseSavedObject } from '../../common/utils';
|
||||
import { mockCases } from '../../mocks';
|
||||
import { createCasesClientMockArgs, createCasesClientMockFindRequest } from '../mocks';
|
||||
|
@ -103,5 +104,15 @@ describe('find', () => {
|
|||
'Error: Invalid value "foobar" supplied to "searchFields"'
|
||||
);
|
||||
});
|
||||
|
||||
it(`throws an error when the category array has ${MAX_CATEGORY_FILTER_LENGTH} items`, async () => {
|
||||
const category = Array(MAX_CATEGORY_FILTER_LENGTH + 1).fill('foobar');
|
||||
|
||||
const findRequest = createCasesClientMockFindRequest({ category });
|
||||
|
||||
await expect(find(findRequest, clientArgs)).rejects.toThrow(
|
||||
`Error: Too many categories provided. The maximum allowed is ${MAX_CATEGORY_FILTER_LENGTH}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { isEmpty } from 'lodash';
|
||||
import Boom from '@hapi/boom';
|
||||
|
||||
import { MAX_CATEGORY_FILTER_LENGTH } from '../../../common/constants';
|
||||
import type { CasesFindResponse, CasesFindRequest } from '../../../common/api';
|
||||
import {
|
||||
CasesFindRequestRt,
|
||||
|
@ -24,6 +25,16 @@ import { LICENSING_CASE_ASSIGNMENT_FEATURE } from '../../common/constants';
|
|||
import type { CasesFindQueryParams } from '../types';
|
||||
import { decodeOrThrow } from '../../../common/api/runtime_types';
|
||||
|
||||
/**
|
||||
* Throws an error if the user tries to filter by more than MAX_CATEGORY_FILTER_LENGTH categories.
|
||||
*/
|
||||
function throwIfCategoryParamTooLong(category?: string[] | string) {
|
||||
if (Array.isArray(category) && category.length > MAX_CATEGORY_FILTER_LENGTH)
|
||||
throw Boom.badRequest(
|
||||
`Too many categories provided. The maximum allowed is ${MAX_CATEGORY_FILTER_LENGTH}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a case and optionally its comments.
|
||||
*
|
||||
|
@ -44,8 +55,7 @@ export const find = async (
|
|||
try {
|
||||
const queryParams = decodeWithExcessOrThrow(CasesFindRequestRt)(params);
|
||||
|
||||
const { filter: authorizationFilter, ensureSavedObjectsAreAuthorized } =
|
||||
await authorization.getAuthorizationFilter(Operations.findCases);
|
||||
throwIfCategoryParamTooLong(queryParams.category);
|
||||
|
||||
/**
|
||||
* Assign users to a case is only available to Platinum+
|
||||
|
@ -63,6 +73,9 @@ export const find = async (
|
|||
licensingService.notifyUsage(LICENSING_CASE_ASSIGNMENT_FEATURE);
|
||||
}
|
||||
|
||||
const { filter: authorizationFilter, ensureSavedObjectsAreAuthorized } =
|
||||
await authorization.getAuthorizationFilter(Operations.findCases);
|
||||
|
||||
const queryArgs: CasesFindQueryParams = {
|
||||
tags: queryParams.tags,
|
||||
reporters: queryParams.reporters,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { v1 as uuidv1 } from 'uuid';
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { CASES_URL } from '@kbn/cases-plugin/common/constants';
|
||||
import { CASES_URL, MAX_CATEGORY_FILTER_LENGTH } from '@kbn/cases-plugin/common/constants';
|
||||
import { Case, CaseSeverity, CaseStatuses, CommentType } from '@kbn/cases-plugin/common/api';
|
||||
import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
|
||||
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
|
||||
|
@ -349,6 +349,12 @@ export default ({ getService }: FtrProviderContext): void => {
|
|||
});
|
||||
});
|
||||
|
||||
it('unhappy path - 400s when more than the maximum category fields are supplied', async () => {
|
||||
const category = Array(MAX_CATEGORY_FILTER_LENGTH + 1).fill('foobar');
|
||||
|
||||
await findCases({ supertest, query: { category }, expectedHttpCode: 400 });
|
||||
});
|
||||
|
||||
describe('search and searchField', () => {
|
||||
beforeEach(async () => {
|
||||
await createCase(supertest, postCaseReq);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue