Skip to content

Commit

Permalink
[Cases] Add the ability to filter cases by date in the find and statu…
Browse files Browse the repository at this point in the history
…s endpoints (#128652)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
cnasikas and kibanamachine authored Mar 31, 2022
1 parent e22deff commit 4246f3e
Show file tree
Hide file tree
Showing 15 changed files with 589 additions and 19 deletions.
6 changes: 6 additions & 0 deletions docs/api/cases/cases-api-find-cases.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Defaults to `OR`.
`fields`::
(Optional, array of strings) The fields in the entity to return in the response.

`from`::
(Optional, string) Returns only cases that were created after a specific date. The date must be specified as a <<kuery-query,KQL>> data range or date match expression. preview:[]

`owner`::
(Optional, string or array of strings) A filter to limit the retrieved cases to
a specific set of applications. Valid values are: `cases`, `observability`,
Expand Down Expand Up @@ -78,6 +81,9 @@ Defaults to `desc`.
`tags`::
(Optional, string or array of strings) Filters the returned cases by tags.

`to`::
(Optional, string) Returns only cases that were created before a specific date. The date must be specified as a <<kuery-query,KQL>> data range or date match expression. preview:[]

=== Response code

`200`::
Expand Down
10 changes: 10 additions & 0 deletions x-pack/plugins/cases/common/api/cases/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ export const CasesFindRequestRt = rt.partial({
* The fields in the entity to return in the response
*/
fields: rt.union([rt.array(rt.string), rt.string]),
/**
* A KQL date. If used all cases created after (gte) the from date will be returned
*/
from: rt.string,
/**
* The page of objects to return
*/
Expand All @@ -180,11 +184,17 @@ export const CasesFindRequestRt = rt.partial({
* The order to sort by
*/
sortOrder: rt.union([rt.literal('desc'), rt.literal('asc')]),

/**
* A KQL date. If used all cases created before (lte) the to date will be returned.
*/
to: rt.string,
/**
* The owner(s) to filter by. The user making the request must have privileges to retrieve cases of that
* ownership or they will be ignored. If no owner is included, then all ownership types will be included in the response
* that the user has access to.
*/

owner: rt.union([rt.array(rt.string), rt.string]),
});

Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/cases/common/api/cases/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ export const CasesStatusResponseRt = rt.type({
});

export const CasesStatusRequestRt = rt.partial({
/**
* A KQL date. If used all cases created after (gte) the from date will be returned
*/
from: rt.string,
/**
* A KQL date. If used all cases created before (lte) the to date will be returned.
*/
to: rt.string,
/**
* The owner of the cases to retrieve the status stats from. If no owner is provided the stats for all cases
* that the user has access to will be returned.
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const SAVED_OBJECT_TYPES = [
*/

export const CASES_URL = '/api/cases' as const;
export const CASE_FIND_URL = `${CASES_URL}/_find` as const;
export const CASE_DETAILS_URL = `${CASES_URL}/{case_id}` as const;
export const CASE_CONFIGURE_URL = `${CASES_URL}/configure` as const;
export const CASE_CONFIGURE_DETAILS_URL = `${CASES_URL}/configure/{configuration_id}` as const;
Expand Down
42 changes: 39 additions & 3 deletions x-pack/plugins/cases/public/client/api/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@

import { httpServiceMock } from '../../../../../../src/core/public/mocks';
import { createClientAPI } from '.';
import { allCases, casesStatus } from '../../containers/mock';

describe('createClientAPI', () => {
const http = httpServiceMock.createStartContract({ basePath: '' });
const api = createClientAPI({ http });

beforeEach(() => {
jest.clearAllMocks();
});

describe('getRelatedCases', () => {
const http = httpServiceMock.createStartContract({ basePath: '' });
const api = createClientAPI({ http });
const res = [
{
id: 'test-id',
Expand All @@ -43,4 +43,40 @@ describe('createClientAPI', () => {
});
});
});

describe('cases', () => {
describe('find', () => {
const http = httpServiceMock.createStartContract({ basePath: '' });
const api = createClientAPI({ http });
http.get.mockResolvedValue(allCases);

it('should return the correct response', async () => {
expect(await api.cases.find({ from: 'now-1d' })).toEqual(allCases);
});

it('should have been called with the correct path', async () => {
await api.cases.find({ perPage: 10 });
expect(http.get).toHaveBeenCalledWith('/api/cases/_find', {
query: { perPage: 10 },
});
});
});

describe('getAllCasesMetrics', () => {
const http = httpServiceMock.createStartContract({ basePath: '' });
const api = createClientAPI({ http });
http.get.mockResolvedValue(casesStatus);

it('should return the correct response', async () => {
expect(await api.cases.getAllCasesMetrics({ from: 'now-1d' })).toEqual(casesStatus);
});

it('should have been called with the correct path', async () => {
await api.cases.getAllCasesMetrics({ from: 'now-1d' });
expect(http.get).toHaveBeenCalledWith('/api/cases/status', {
query: { from: 'now-1d' },
});
});
});
});
});
17 changes: 16 additions & 1 deletion x-pack/plugins/cases/public/client/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@
*/

import { HttpStart } from 'kibana/public';
import { CasesByAlertId, CasesByAlertIDRequest, getCasesFromAlertsUrl } from '../../../common/api';
import {
CasesByAlertId,
CasesByAlertIDRequest,
CasesFindRequest,
getCasesFromAlertsUrl,
CasesResponse,
CasesStatusRequest,
CasesStatusResponse,
} from '../../../common/api';
import { CASE_FIND_URL, CASE_STATUS_URL } from '../../../common/constants';
import { CasesUiStart } from '../../types';

export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['api'] => {
Expand All @@ -16,5 +25,11 @@ export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['ap
query: CasesByAlertIDRequest
): Promise<CasesByAlertId> =>
http.get<CasesByAlertId>(getCasesFromAlertsUrl(alertId), { query }),
cases: {
find: (query: CasesFindRequest): Promise<CasesResponse> =>
http.get<CasesResponse>(CASE_FIND_URL, { query }),
getAllCasesMetrics: (query: CasesStatusRequest): Promise<CasesStatusResponse> =>
http.get<CasesStatusResponse>(CASE_STATUS_URL, { query }),
},
};
};
1 change: 1 addition & 0 deletions x-pack/plugins/cases/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CasesUiStart } from './types';

const apiMock: jest.Mocked<CasesUiStart['api']> = {
getRelatedCases: jest.fn(),
cases: { find: jest.fn(), getAllCasesMetrics: jest.fn() },
};

const uiMock: jest.Mocked<CasesUiStart['ui']> = {
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/cases/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import type { TriggersAndActionsUIPublicPluginStart as TriggersActionsStart } fr
import {
CasesByAlertId,
CasesByAlertIDRequest,
CasesFindRequest,
CasesResponse,
CasesStatusRequest,
CasesStatusResponse,
CommentRequestAlertType,
CommentRequestUserType,
} from '../common/api';
Expand Down Expand Up @@ -74,6 +78,10 @@ export interface RenderAppProps {
export interface CasesUiStart {
api: {
getRelatedCases: (alertId: string, query: CasesByAlertIDRequest) => Promise<CasesByAlertId>;
cases: {
find: (query: CasesFindRequest) => Promise<CasesResponse>;
getAllCasesMetrics: (query: CasesStatusRequest) => Promise<CasesStatusResponse>;
};
};
ui: {
/**
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/cases/server/client/cases/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export const find = async (
sortByField: queryParams.sortField,
status: queryParams.status,
owner: queryParams.owner,
from: queryParams.from,
to: queryParams.to,
};

const statusStatsOptions = constructQueryOptions({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export async function getStatusTotalsByType(

const options = constructQueryOptions({
owner: queryParams.owner,
from: queryParams.from,
to: queryParams.to,
authorizationFilter,
});

Expand Down
Loading

0 comments on commit 4246f3e

Please sign in to comment.