From 4ad185d27b8530f2d45c0de78d683af9663bc582 Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Fri, 8 May 2020 15:18:34 -0400 Subject: [PATCH] fix middleware types --- .../embeddables/resolver/store/actions.ts | 2 +- .../embeddables/resolver/store/data/action.ts | 10 ++- .../resolver/store/data/reducer.ts | 21 ++++-- .../embeddables/resolver/store/middleware.ts | 71 +++++++++++-------- .../public/embeddables/resolver/types.ts | 14 ++-- 5 files changed, 72 insertions(+), 46 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts index 76bac7c1fbc0..498fd008ead6 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/actions.ts @@ -50,7 +50,7 @@ interface AppRequestedResolverData { */ interface AppRequestedRelatedEventData { readonly type: 'appRequestedRelatedEventData'; - readonly payload: [ResolverEvent, string]; + readonly payload: ResolverEvent; } /** diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts index 33f63ec32786..b50dfb28cafd 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/action.ts @@ -24,7 +24,15 @@ interface ServerReturnedRelatedEventData { readonly payload: Map; } +/** + * Will occur when a request for related event data is unsuccessful. + */ +interface ServerFailedToReturnRelatedEventData { + readonly type: 'serverFailedToReturnRelatedEventData'; +} + export type DataAction = | ServerReturnedResolverData | ServerFailedToReturnResolverData - | ServerReturnedRelatedEventData; + | ServerReturnedRelatedEventData + | ServerFailedToReturnRelatedEventData; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts index dcd14c06e96a..07500cbf8c19 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/data/reducer.ts @@ -32,24 +32,22 @@ export const dataReducer: Reducer = (state = initialS isLoading: false, hasError: false, }; - } - else if (action.type === 'appRequestedRelatedEventData') { + } else if (action.type === 'appRequestedRelatedEventData') { const evt = action.payload; const statsMap = state[resultsEnrichedWithRelatedEventInfo]; - if(statsMap){ + if (statsMap) { const currentStatsMap = new Map(statsMap); currentStatsMap.set(evt, waitingForRelatedEventData); return { ...state, [resultsEnrichedWithRelatedEventInfo]: currentStatsMap }; } return state; - } - else if (action.type === 'serverReturnedRelatedEventData') { + } else if (action.type === 'serverReturnedRelatedEventData') { /** * REMOVE: pending resolution of https://github.com/elastic/endpoint-app-team/issues/379 * When this data is inlined with results, there won't be a need for this. */ const statsMap = state[resultsEnrichedWithRelatedEventInfo]; - + if (statsMap && typeof statsMap?.set === 'function') { const currentStatsMap: RelatedEventData = new Map(statsMap); for (const updatedEvent of action.payload.keys()) { @@ -57,7 +55,16 @@ export const dataReducer: Reducer = (state = initialS if (newStatsEntry) { // do stats - const statsForEntry = newStatsEntry?.related_events.reduce((a: Partial>,v: {related_event_type: RelatedEventType})=>{ a[v.related_event_type] = (a[v.related_event_type]||0)+1; return a; },{}) + const statsForEntry = newStatsEntry?.relatedEvents.reduce( + ( + a: Partial>, + v: { relatedEventType: RelatedEventType } + ) => { + a[v.relatedEventType] = (a[v.relatedEventType] || 0) + 1; + return a; + }, + {} + ); const newRelatedEventStats: RelatedEventDataEntryWithStats = Object.assign( newStatsEntry, { stats: statsForEntry } diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts index 2657a4583aa5..b4685a07f5e7 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/store/middleware.ts @@ -5,12 +5,12 @@ */ import { Dispatch, MiddlewareAPI } from 'redux'; +import { HttpHandler } from 'kibana/public'; import { KibanaReactContextValue } from '../../../../../../../src/plugins/kibana_react/public'; import { EndpointPluginServices } from '../../../plugin'; import { ResolverState, ResolverAction, RelatedEventDataEntry, RelatedEventType } from '../types'; import { ResolverEvent, ResolverNode } from '../../../../common/types'; import * as event from '../../../../common/models/event'; -import { HttpHandler } from 'kibana/public'; type MiddlewareFactory = ( context?: KibanaReactContextValue @@ -31,15 +31,23 @@ function flattenEvents(children: ResolverNode[], events: ResolverEvent[] = []): }, events); } -async function* getEachRelatedEventsResult(eventsToFetch: ResolverEvent[], httpGetter: HttpHandler) { - for (const eventToQueryForRelateds of eventsToFetch){ +type RelatedEventAPIResponse = Error | { events: ResolverEvent[] }; +async function* getEachRelatedEventsResult( + eventsToFetch: ResolverEvent[], + httpGetter: HttpHandler +): AsyncGenerator<[ResolverEvent, RelatedEventAPIResponse], any, any> { + for (const eventToQueryForRelateds of eventsToFetch) { const id = event.entityId(eventToQueryForRelateds); - yield [eventToQueryForRelateds, await Promise.all([ - httpGetter(`/api/endpoint/resolver/${id}/events`, { - query: {events: 100}, - }), - ]) - ] + const relatedEventError = new Error(`Error fetching related events for entity=${id}`); + let result: RelatedEventAPIResponse = relatedEventError; + try { + result = await httpGetter(`/api/endpoint/resolver/${id}/events`, { + query: { events: 100 }, + }); + } catch (e) { + result = relatedEventError; + } + yield [eventToQueryForRelateds, result]; } } @@ -96,28 +104,35 @@ export const resolverMiddlewareFactory: MiddlewareFactory = context => { * When this data is inlined with results, there won't be a need for this. */ if (action.type === 'appRequestedRelatedEventData') { - if(typeof context !== 'undefined') { - for await (const results of getEachRelatedEventsResult([action.payload], context.services.http.get)){ - const response: Map = new Map(); - const baseEvent = results[0] as unknown as ResolverEvent; - const fetchedResults = (results[1] as unknown as {events: ResolverEvent[]}[]) - //pack up the results into response - for (const relatedEventResult of fetchedResults) { - //help figure out how to type the Async Generator above - const relatedEventsFromResult = relatedEventResult.events; - const relatedEventEntry = relatedEventsFromResult.map(related_event => { - return { - related_event, - related_event_type: event.eventCategoryDisplayName(related_event) as RelatedEventType - } - }) - response.set(baseEvent, {related_events: relatedEventEntry}); - } + if (typeof context !== 'undefined') { + for await (const results of getEachRelatedEventsResult( + [action.payload], + context.services.http.get + )) { + const apiResults = results[1]; + if (apiResults instanceof Error) { api.dispatch({ - type: 'serverReturnedRelatedEventData', - payload: response, + type: 'serverFailedToReturnRelatedEventData', }); } + const response: Map = new Map(); + const baseEvent = results[0]; + const fetchedResults = (results[1] as { events: ResolverEvent[] }).events; + // pack up the results into response + const relatedEventEntry = fetchedResults.map(relatedEvent => { + return { + relatedEvent, + relatedEventType: event.eventCategoryDisplayName(relatedEvent) as RelatedEventType, + }; + }); + + response.set(baseEvent, { relatedEvents: relatedEventEntry }); + + api.dispatch({ + type: 'serverReturnedRelatedEventData', + payload: response, + }); + } } } }; diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts index 59015c992afb..e88fd8861f6e 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/types.ts @@ -146,18 +146,14 @@ export type RelatedEventType = | 'Image Load' | 'User'; - export type EventCategory = RelatedEventType | - ( | 'Alert' - | 'Process' - | 'Security' - ) +export type EventCategory = RelatedEventType | ('Alert' | 'Process' | 'Security'); /** * This symbol is used to tag results with Related event info * REMOVE: pending resolution of https://github.com/elastic/endpoint-app-team/issues/379 * When this data is inlined with results, there won't be a need for this. */ -export const resultsEnrichedWithRelatedEventInfo = `resultsEnrichedWithRelatedEventInfo` +export const resultsEnrichedWithRelatedEventInfo = `resultsEnrichedWithRelatedEventInfo`; /** * This symbol indicates that the app is waiting for related event data for the subject * of any particular request. @@ -170,9 +166,9 @@ export const waitingForRelatedEventData = Symbol( * about a particular subject's related events */ export interface RelatedEventDataEntry { - related_events: Array<{ - related_event: ResolverEvent; - related_event_type: RelatedEventType; + relatedEvents: Array<{ + relatedEvent: ResolverEvent; + relatedEventType: RelatedEventType; }>; } /**