Skip to content

Commit

Permalink
[Session View] jumpToEntityId / investigatedAlertId behavior fixed. (#…
Browse files Browse the repository at this point in the history
…129275) (#129543)

* Fix for process event pagination in session view

* plumbing work to get a few more props to session view when loaded via timeline

* session config plumbing work done

* jump to event kinks worked out.

* tests fixed

* test fix

* build error fixes

* addressed PR comments. cleanup

* addressed PR comments. cleanup

* post merge fixes

* pr comments addressed

Co-authored-by: mitodrummer <[email protected]>
(cherry picked from commit 772205f)

Co-authored-by: Karl Godard <[email protected]>
  • Loading branch information
kibanamachine and mitodrummer authored Apr 6, 2022
1 parent 9bec00d commit 71ba0af
Show file tree
Hide file tree
Showing 41 changed files with 360 additions and 239 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
itemsPerPage,
itemsPerPageOptions,
kqlMode,
sessionViewId,
sessionViewConfig,
showCheckboxes,
sort,
} = defaultModel,
Expand Down Expand Up @@ -164,11 +164,11 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({

const graphOverlay = useMemo(() => {
const shouldShowOverlay =
(graphEventId != null && graphEventId.length > 0) || sessionViewId !== null;
(graphEventId != null && graphEventId.length > 0) || sessionViewConfig != null;
return shouldShowOverlay ? (
<GraphOverlay timelineId={id} SessionView={SessionView} Navigation={Navigation} />
) : null;
}, [graphEventId, id, sessionViewId, SessionView, Navigation]);
}, [graphEventId, id, sessionViewConfig, SessionView, Navigation]);
const setQuery = useCallback(
(inspect, loading, refetch) => {
dispatch(inputsActions.setQuery({ id, inputId: 'global', inspect, loading, refetch }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export const mockGlobalState: State = {
end: '2020-07-08T08:20:18.966Z',
},
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: false,
showCheckboxes: false,
pinnedEventIds: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2011,7 +2011,7 @@ export const mockTimelineModel: TimelineModel = {
savedObjectId: 'ef579e40-jibber-jabber',
selectAll: false,
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: false,
showCheckboxes: false,
sort: [
Expand Down Expand Up @@ -2133,7 +2133,7 @@ export const defaultTimelineProps: CreateTimelineProps = {
savedObjectId: null,
selectAll: false,
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: false,
showCheckboxes: false,
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: Direction.desc }],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ describe('alert actions', () => {
savedObjectId: null,
selectAll: false,
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: true,
showCheckboxes: false,
sort: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ describe('GraphOverlay', () => {
timelineById: {
[timelineId]: {
...mockGlobalState.timeline.timelineById[timelineId],
sessionViewId: 'testId',
sessionViewConfig: {
sessionEntityId: 'testId',
},
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const GraphOverlayComponent: React.FC<GraphOverlayProps> = ({
const graphEventId = useDeepEqualSelector(
(state) => (getTimeline(state, timelineId) ?? timelineDefaults).graphEventId
);
const sessionViewId = useDeepEqualSelector(
(state) => (getTimeline(state, timelineId) ?? timelineDefaults).sessionViewId
const sessionViewConfig = useDeepEqualSelector(
(state) => (getTimeline(state, timelineId) ?? timelineDefaults).sessionViewConfig
);

const getStartSelector = useMemo(() => startSelector(), []);
Expand Down Expand Up @@ -134,7 +134,7 @@ const GraphOverlayComponent: React.FC<GraphOverlayProps> = ({
[defaultDataView.patternList, isInTimeline, timelinePatterns]
);

if (!isInTimeline && sessionViewId !== null) {
if (!isInTimeline && sessionViewConfig !== null) {
if (fullScreen) {
return (
<FullScreenOverlayContainer data-test-subj="overlayContainer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useShallowEqualSelector } from '../../../../../common/hooks/use_selecto
import {
setActiveTabTimeline,
updateTimelineGraphEventId,
updateTimelineSessionViewSessionId,
updateTimelineSessionViewConfig,
} from '../../../../store/timeline/actions';
import {
useGlobalFullScreen,
Expand Down Expand Up @@ -129,34 +129,45 @@ const ActionsComponent: React.FC<ActionProps> = ({
}
}, [dispatch, ecsData._id, timelineId, setGlobalFullScreen, setTimelineFullScreen]);

const entryLeader = useMemo(() => {
const { process } = ecsData;
const entryLeaderIds = process?.entry_leader?.entity_id;
if (entryLeaderIds !== undefined && entryLeaderIds.length > 0) {
return entryLeaderIds[0];
} else {
const sessionViewConfig = useMemo(() => {
const { process, _id, timestamp } = ecsData;
const sessionEntityId = process?.entry_leader?.entity_id?.[0];

if (sessionEntityId === undefined) {
return null;
}
}, [ecsData]);

const jumpToEntityId = process?.entity_id?.[0];
const investigatedAlertId = eventType === 'signal' || eventType === 'eql' ? _id : undefined;
const jumpToCursor =
(investigatedAlertId && ecsData.kibana?.alert.original_time?.[0]) || timestamp;

return {
sessionEntityId,
jumpToEntityId,
jumpToCursor,
investigatedAlertId,
};
}, [ecsData, eventType]);

const openSessionView = useCallback(() => {
const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen');
if (timelineId === TimelineId.active) {
if (dataGridIsFullScreen) {
setTimelineFullScreen(true);
}
if (entryLeader !== null) {
if (sessionViewConfig !== null) {
dispatch(setActiveTabTimeline({ id: timelineId, activeTab: TimelineTabs.session }));
}
} else {
if (dataGridIsFullScreen) {
setGlobalFullScreen(true);
}
}
if (entryLeader !== null) {
dispatch(updateTimelineSessionViewSessionId({ id: timelineId, eventId: entryLeader }));
if (sessionViewConfig !== null) {
dispatch(updateTimelineSessionViewConfig({ id: timelineId, sessionViewConfig }));
}
}, [dispatch, timelineId, entryLeader, setGlobalFullScreen, setTimelineFullScreen]);
}, [dispatch, timelineId, sessionViewConfig, setGlobalFullScreen, setTimelineFullScreen]);

return (
<ActionsContainer>
Expand Down Expand Up @@ -250,7 +261,7 @@ const ActionsComponent: React.FC<ActionProps> = ({
</EventsTdContent>
</div>
) : null}
{entryLeader !== null ? (
{sessionViewConfig !== null ? (
<div>
<EventsTdContent textAlign="center" width={DEFAULT_ACTION_BUTTON_WIDTH}>
<EuiToolTip data-test-subj="expand-event-tool-tip" content={i18n.OPEN_SESSION_VIEW}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const StatefulTimelineComponent: React.FC<Props> = ({
savedObjectId,
timelineType,
description,
sessionViewId,
sessionViewConfig,
} = useDeepEqualSelector((state) =>
pick(
[
Expand All @@ -84,7 +84,7 @@ const StatefulTimelineComponent: React.FC<Props> = ({
'savedObjectId',
'timelineType',
'description',
'sessionViewId',
'sessionViewConfig',
],
getTimeline(state, timelineId) ?? timelineDefaults
)
Expand Down Expand Up @@ -202,7 +202,7 @@ const StatefulTimelineComponent: React.FC<Props> = ({

<TabsContent
graphEventId={graphEventId}
sessionViewId={sessionViewId}
sessionViewConfig={sessionViewConfig}
renderCellValue={renderCellValue}
rowRenderers={rowRenderers}
timelineId={timelineId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,19 @@ import {
} from '../../../../common/containers/use_full_screen';
import {
updateTimelineGraphEventId,
updateTimelineSessionViewSessionId,
updateTimelineSessionViewConfig,
setActiveTabTimeline,
} from '../../../../timelines/store/timeline/actions';
import { detectionsTimelineIds } from '../../../containers/helpers';
import * as i18n from './translations';

export interface SessionViewConfig {
sessionEntityId: string;
jumpToEntityId?: string;
jumpToCursor?: string;
investigatedAlertId?: string;
}

const FullScreenButtonIcon = styled(EuiButtonIcon)`
margin: 4px 0 4px 0;
`;
Expand Down Expand Up @@ -102,12 +109,14 @@ export const useSessionView = ({
const { sessionView } = useKibana().services;
const dispatch = useDispatch();
const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []);

const { globalFullScreen, setGlobalFullScreen } = useGlobalFullScreen();
const { timelineFullScreen, setTimelineFullScreen } = useTimelineFullScreen();

const { graphEventId, sessionViewId, activeTab, prevActiveTab } = useDeepEqualSelector(
const { graphEventId, sessionViewConfig, activeTab, prevActiveTab } = useDeepEqualSelector(
(state) => getTimeline(state, timelineId) ?? timelineDefaults
);

const onCloseOverlay = useCallback(() => {
const isDataGridFullScreen = document.querySelector('.euiDataGrid--fullScreen') !== null;
// Since EUI changes these values directly as a side effect, need to add them back on close.
Expand All @@ -126,15 +135,15 @@ export const useSessionView = ({
}
if (timelineId !== TimelineId.active) {
dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: '' }));
dispatch(updateTimelineSessionViewSessionId({ id: timelineId, eventId: null }));
dispatch(updateTimelineSessionViewConfig({ id: timelineId, sessionViewConfig: null }));
} else {
if (activeTab === TimelineTabs.graph) {
dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: '' }));
if (prevActiveTab === TimelineTabs.session && !sessionViewId) {
if (prevActiveTab === TimelineTabs.session && !sessionViewConfig) {
dispatch(setActiveTabTimeline({ id: timelineId, activeTab: TimelineTabs.query }));
}
} else if (activeTab === TimelineTabs.session) {
dispatch(updateTimelineSessionViewSessionId({ id: timelineId, eventId: null }));
dispatch(updateTimelineSessionViewConfig({ id: timelineId, sessionViewConfig: null }));
if (prevActiveTab === TimelineTabs.graph && !graphEventId) {
dispatch(setActiveTabTimeline({ id: timelineId, activeTab: TimelineTabs.query }));
} else {
Expand All @@ -150,7 +159,7 @@ export const useSessionView = ({
activeTab,
prevActiveTab,
graphEventId,
sessionViewId,
sessionViewConfig,
]);
const fullScreen = useMemo(
() => isFullScreen({ globalFullScreen, timelineId, timelineFullScreen }),
Expand Down Expand Up @@ -187,13 +196,13 @@ export const useSessionView = ({
});

const sessionViewComponent = useMemo(() => {
return sessionViewId !== null
return sessionViewConfig !== null
? sessionView.getSessionView({
sessionEntityId: sessionViewId,
...sessionViewConfig,
loadAlertDetails: openDetailsPanel,
})
: null;
}, [openDetailsPanel, sessionView, sessionViewId]);
}, [openDetailsPanel, sessionView, sessionViewConfig]);

const navigation = useMemo(() => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
} from '../../../../common/hooks/use_timeline_events_count';
import { timelineActions } from '../../../store/timeline';
import { CellValueElementProps } from '../cell_rendering';
import { SessionViewConfig } from '../session_tab_content/use_session_view';
import {
getActiveTabSelector,
getNoteIdsSelector,
Expand Down Expand Up @@ -60,7 +61,7 @@ interface BasicTimelineTab {
timelineId: TimelineId;
timelineType: TimelineType;
graphEventId?: string;
sessionViewId?: string | null;
sessionViewConfig?: SessionViewConfig | null;
timelineDescription: string;
}

Expand Down Expand Up @@ -235,7 +236,7 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
timelineFullScreen,
timelineType,
graphEventId,
sessionViewId,
sessionViewConfig,
timelineDescription,
}) => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -351,7 +352,7 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
data-test-subj={`timelineTabs-${TimelineTabs.session}`}
onClick={setSessionAsActiveTab}
isSelected={activeTab === TimelineTabs.session}
disabled={sessionViewId === null}
disabled={sessionViewConfig === null}
key={TimelineTabs.session}
>
{i18n.SESSION_TAB}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export {
upsertColumn,
} from '../../../../../timelines/public';
import { ResolveTimelineConfig } from '../../components/open_timeline/types';
import { SessionViewConfig } from '../../components/timeline/session_tab_content/use_session_view';

const actionCreator = actionCreatorFactory('x-pack/security_solution/local/timeline');

Expand Down Expand Up @@ -81,10 +82,10 @@ export const updateTimelineGraphEventId = actionCreator<{ id: string; graphEvent
'UPDATE_TIMELINE_GRAPH_EVENT_ID'
);

export const updateTimelineSessionViewSessionId = actionCreator<{
export const updateTimelineSessionViewConfig = actionCreator<{
id: string;
eventId: string | null;
}>('UPDATE_TIMELINE_SESSION_VIEW_SESSION_ID');
sessionViewConfig: SessionViewConfig | null;
}>('UPDATE_TIMELINE_SESSION_VIEW_CONFIG');

export const unPinEvent = actionCreator<{ id: string; eventId: string }>('UN_PIN_EVENT');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const timelineDefaults: SubsetTimelineModel &
savedObjectId: null,
selectAll: false,
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: false,
showCheckboxes: false,
sort: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('Epic Timeline', () => {
dateRange: { start: '2019-10-30T21:06:27.644Z', end: '2019-10-31T21:06:27.644Z' },
savedObjectId: '11169110-fc22-11e9-8ca9-072f15ce2685',
selectedEventIds: {},
sessionViewId: null,
sessionViewConfig: null,
show: true,
showCheckboxes: false,
sort: [{ columnId: '@timestamp', columnType: 'number', sortDirection: Direction.desc }],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import {
} from '../../components/timeline/body/constants';
import { activeTimeline } from '../../containers/active_timeline_context';
import { ResolveTimelineConfig } from '../../components/open_timeline/types';

import { SessionViewConfig } from '../../components/timeline/session_tab_content/use_session_view';
export const isNotNull = <T>(value: T | null): value is T => value !== null;

interface AddTimelineHistoryParams {
Expand Down Expand Up @@ -287,13 +287,13 @@ export const updateGraphEventId = ({
};
};

export const updateSessionViewSessionId = ({
export const updateSessionViewConfig = ({
id,
eventId,
sessionViewConfig,
timelineById,
}: {
id: string;
eventId: string | null;
sessionViewConfig: SessionViewConfig | null;
timelineById: TimelineById;
}): TimelineById => {
const timeline = timelineById[id];
Expand All @@ -302,7 +302,7 @@ export const updateSessionViewSessionId = ({
...timelineById,
[id]: {
...timeline,
sessionViewId: eventId,
sessionViewConfig,
},
};
};
Expand Down
Loading

0 comments on commit 71ba0af

Please sign in to comment.