diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts index bd777f0eaaa2096..2cb381e901b4ed2 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/middleware.ts @@ -20,9 +20,9 @@ export const alertMiddlewareFactory: MiddlewareFactory = coreSta api.dispatch({ type: 'serverReturnedAlertsData', payload: response }); } if (action.type === 'userChangedUrl' && isOnAlertPage(state) && hasSelectedAlert(state)) { - const { selected_alert } = uiQueryParams(state); + const uiParams = uiQueryParams(state); const response: AlertData = await coreStart.http.get( - `/api/endpoint/alerts/${selected_alert}` + `/api/endpoint/alerts/${uiParams.selected_alert}` ); api.dispatch({ type: 'serverReturnedAlertDetailsData', payload: response }); } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts index 969a7b653614a5d..ee172fa80f1fed7 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/reducer.ts @@ -11,7 +11,7 @@ import { AppAction } from '../action'; const initialState = (): AlertListState => { return { alerts: [], - alert_details: undefined, + alertDetails: undefined, pageSize: 10, pageIndex: 0, total: 0, @@ -47,7 +47,7 @@ export const alertListReducer: Reducer = ( } else if (action.type === 'serverReturnedAlertDetailsData') { return { ...state, - alert_details: action.payload, + alertDetails: action.payload, }; } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts index 91bcf832036b0ed..8ad86c96b9eb59b 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/selectors.ts @@ -23,7 +23,7 @@ const createStructuredSelector: CreateStructuredSelector = createStructuredSelec */ export const alertListData = (state: AlertListState) => state.alerts; -export const selectedAlertDetailsData = (state: AlertListState) => state.alert_details; +export const selectedAlertDetailsData = (state: AlertListState) => state.alertDetails; /** * Returns the alert list pagination data from state diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index 1af5bd09c3ddbe3..b46785d3190e584 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -93,22 +93,22 @@ export type AlertListData = AlertResultList; export interface AlertListState { /** Array of alert items. */ - alerts: ImmutableArray; + readonly alerts: ImmutableArray; /** The total number of alerts on the page. */ - total: number; + readonly total: number; /** Number of alerts per page. */ - pageSize: number; + readonly pageSize: number; /** Page number, starting at 0. */ - pageIndex: number; + readonly pageIndex: number; /** Current location object from React Router history. */ readonly location?: Immutable; /** Specific Alert data to be shown in the details view */ - readonly alert_details?: Immutable; + readonly alertDetails?: Immutable; } /** diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details_overview.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details_overview.tsx index 3c031676a8142d5..36d99080a2ed821 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details_overview.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details_overview.tsx @@ -40,6 +40,15 @@ export const AlertDetailsOverview = memo(() => { ); }, [alertDetailsData]); + const dateFormatter = new Intl.DateTimeFormat(i18n.getLocale(), { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }); + // TODO fix this style const TokenPrivileges = useMemo(() => { const privileges: Array<{ title: string; description: string }> = []; @@ -49,21 +58,12 @@ export const AlertDetailsOverview = memo(() => { return ( <> - + ); }, [alertDetailsData.process.token.privileges]); - const dateFormatter = new Intl.DateTimeFormat(i18n.getLocale(), { - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - }); - const alertDetailsColumns = useMemo(() => { return [ { @@ -282,56 +282,25 @@ export const AlertDetailsOverview = memo(() => { paddingSize="l" initialIsOpen={true} > - + - - + + - - + + - - + + @@ -340,13 +309,8 @@ export const AlertDetailsOverview = memo(() => { id="alertDetailsSourceProcessAccordion" buttonContent="Source Process" paddingSize="l" - initialIsOpen={true} > - + @@ -355,13 +319,8 @@ export const AlertDetailsOverview = memo(() => { id="alertDetailsSourceProcessTokenAccordion" buttonContent="Source Process Token" paddingSize="l" - initialIsOpen={true} > - + ); diff --git a/x-pack/plugins/endpoint/server/routes/alerts.ts b/x-pack/plugins/endpoint/server/routes/alerts.ts deleted file mode 100644 index b62f8c9ce8c31de..000000000000000 --- a/x-pack/plugins/endpoint/server/routes/alerts.ts +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { IRouter, KibanaRequest, RequestHandler } from 'kibana/server'; -import { SearchResponse } from 'elasticsearch'; -import { schema } from '@kbn/config-schema'; - -import { - getPagingProperties, - buildAlertListESQuery, -} from '../services/endpoint/alert_query_builders'; - -import { AlertData, AlertResultList } from '../../common/types'; -import { AlertRequestParams, EndpointAppContext, AlertDetailsRequestParams } from '../types'; - -const ALERTS_ROUTE = '/api/endpoint/alerts'; - -export const reqSchema = schema.object({ - page_size: schema.number({ defaultValue: 10, min: 1, max: 10000 }), - page_index: schema.number({ defaultValue: 0, min: 0 }), -}); - -export function registerAlertRoutes(router: IRouter, endpointAppContext: EndpointAppContext) { - const alertsHandler: RequestHandler = async (ctx, req, res) => { - try { - const queryParams = await getPagingProperties( - req as KibanaRequest, - endpointAppContext - ); - const reqBody = await buildAlertListESQuery(queryParams); - const response = (await ctx.core.elasticsearch.dataClient.callAsCurrentUser( - 'search', - reqBody - )) as SearchResponse; - return res.ok({ body: mapToAlertResultList(endpointAppContext, queryParams, response) }); - } catch (err) { - return res.internalError({ body: err }); - } - }; - - const alertDetailHandler: RequestHandler = async (ctx, req, res) => { - try { - function mapHit(entry: AlertDataWrapper): AlertData { - return { - id: entry._id, - ...entry._source, - }; - } - const alertId = req.params.id; - const response = (await ctx.core.elasticsearch.dataClient.callAsCurrentUser('get', { - index: 'my-index', - id: alertId, - })) as SearchResponse; - - return res.ok({ body: mapHit(response) }); - } catch (err) { - return res.internalError({ body: err }); - } - }; - - router.get( - { - path: ALERTS_ROUTE, - validate: { - query: reqSchema, - }, - options: { authRequired: true }, - }, - alertsHandler - ); - - router.post( - { - path: ALERTS_ROUTE, - validate: { - body: reqSchema, - }, - options: { authRequired: true }, - }, - alertsHandler - ); - - router.get( - { - path: ALERTS_ROUTE + '/{id}', - validate: { - params: schema.object({ - id: schema.string(), - }), - }, - options: { authRequired: true }, - }, - alertDetailHandler - ); -} - -interface AlertDataWrapper { - _id: string; - _source: AlertData; -} - -function mapToAlertResultList( - endpointAppContext: EndpointAppContext, - queryParams: Record, - searchResponse: SearchResponse -): AlertResultList { - interface Total { - value: number; - relation: string; - } - - let totalNumberOfAlerts: number = 0; - let totalIsLowerBound: boolean = false; - - // We handle 2 separate schemas for the response below, due to: https://github.com/elastic/kibana/issues/56694 - if (typeof searchResponse?.hits?.total === 'object') { - const total: Total = searchResponse?.hits?.total as Total; - totalNumberOfAlerts = total?.value || 0; - totalIsLowerBound = total?.relation === 'gte' || false; - } else { - totalNumberOfAlerts = searchResponse?.hits?.total || 0; - } - - if (totalIsLowerBound) { - // This shouldn't happen, as we always try to fetch enough hits to satisfy the current request and the next page. - endpointAppContext.logFactory - .get('endpoint') - .warn('Total hits not counted accurately. Pagination numbers may be inaccurate.'); - } - - const hits: AlertDataWrapper[] = searchResponse?.hits?.hits; - - function mapHit(entry: AlertDataWrapper): AlertData { - return { - id: entry._id, - ...entry._source, - }; - } - - return { - request_page_size: queryParams.pageSize, - request_page_index: queryParams.pageIndex, - result_from_index: queryParams.fromIndex, - alerts: hits.map(mapHit), - total: totalNumberOfAlerts, - }; -}