[Security Solution][Alert details] - move useBasicDataFromDetailsData hook to flyout folder (#190106)

This commit is contained in:
Philippe Oberti 2024-08-19 12:10:25 +02:00 committed by GitHub
parent d971c6a10e
commit ac5d6921d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 313 additions and 148 deletions

View file

@ -8,12 +8,12 @@
import React from 'react';
import { render } from '@testing-library/react';
import { InvestigationGuideView } from './investigation_guide_view';
import type { GetBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import type { UseBasicDataFromDetailsDataResult } from '../../../flyout/document_details/shared/hooks/use_basic_data_from_details_data';
const defaultProps = {
basicData: {
ruleId: 'rule-id',
} as unknown as GetBasicDataFromDetailsData,
} as unknown as UseBasicDataFromDetailsDataResult,
ruleNote: 'test note',
};

View file

@ -8,7 +8,7 @@
import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui';
import React, { createContext } from 'react';
import styled from 'styled-components';
import type { GetBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import type { UseBasicDataFromDetailsDataResult } from '../../../flyout/document_details/shared/hooks/use_basic_data_from_details_data';
import * as i18n from './translations';
import { MarkdownRenderer } from '../markdown_editor';
import { LineClamp } from '../line_clamp';
@ -18,13 +18,13 @@ export const Indent = styled.div`
word-break: break-word;
`;
export const BasicAlertDataContext = createContext<Partial<GetBasicDataFromDetailsData>>({});
export const BasicAlertDataContext = createContext<Partial<UseBasicDataFromDetailsDataResult>>({});
interface InvestigationGuideViewProps {
/**
* An object of basic fields from the event details data
*/
basicData: GetBasicDataFromDetailsData;
basicData: UseBasicDataFromDetailsDataResult;
/**
* The markdown text of rule.note
*/

View file

@ -9,7 +9,7 @@ import type { FC } from 'react';
import React, { useCallback } from 'react';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { DocumentDetailsRightPanelKey } from '../shared/constants/panel_keys';
import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../shared/hooks/use_basic_data_from_details_data';
import {
EndpointIsolateSuccess,
HostIsolationPanel,

View file

@ -9,7 +9,7 @@ import type { FC } from 'react';
import React, { useMemo } from 'react';
import { useDocumentDetailsContext } from '../../shared/context';
import { getSourcererScopeId } from '../../../../helpers';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { SecurityCellActionType } from '../../../../app/actions/constants';
import {
CellActionsMode,

View file

@ -15,9 +15,9 @@ import { useDocumentDetailsContext } from '../../shared/context';
import { useInvestigationTimeEnrichment } from '../../shared/hooks/use_investigation_enrichment';
import type { RouteSpyState } from '../../../../common/utils/route/types';
import {
type GetBasicDataFromDetailsData,
type UseBasicDataFromDetailsDataResult,
useBasicDataFromDetailsData,
} from '../../../../timelines/components/side_panel/event_details/helpers';
} from '../../shared/hooks/use_basic_data_from_details_data';
import { mockContextValue } from '../../shared/mocks/mock_context';
jest.mock('../../../../timelines/containers/details');
@ -25,7 +25,7 @@ jest.mock('../../../../sourcerer/containers');
jest.mock('../../../../common/utils/route/use_route_spy');
jest.mock('../../shared/context');
jest.mock('../../shared/hooks/use_investigation_enrichment');
jest.mock('../../../../timelines/components/side_panel/event_details/helpers');
jest.mock('../../shared/hooks/use_basic_data_from_details_data');
describe('useThreatIntelligenceDetails', () => {
beforeEach(() => {
@ -42,7 +42,7 @@ describe('useThreatIntelligenceDetails', () => {
jest
.mocked(useBasicDataFromDetailsData)
.mockReturnValue({ isAlert: true } as unknown as GetBasicDataFromDetailsData);
.mockReturnValue({ isAlert: true } as unknown as UseBasicDataFromDetailsDataResult);
jest.mocked(useSourcererDataView).mockReturnValue({
browserFields: {},

View file

@ -9,7 +9,7 @@ import { useMemo } from 'react';
import { SecurityPageName } from '@kbn/deeplinks-security';
import type { RunTimeMappings } from '../../../../../common/api/search_strategy';
import type { CtiEnrichment, EventFields } from '../../../../../common/search_strategy';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import {
filterDuplicateEnrichments,
getEnrichmentFields,

View file

@ -15,7 +15,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { useKibana } from '../../../../common/lib/kibana';
import { useDocumentDetailsContext } from '../../shared/context';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import {
ALERT_DESCRIPTION_DETAILS_TEST_ID,
ALERT_DESCRIPTION_TITLE_TEST_ID,

View file

@ -15,7 +15,7 @@ import { DocumentStatus } from './status';
import { DocumentSeverity } from './severity';
import { RiskScore } from './risk_score';
import { useRefetchByScope } from '../hooks/use_refetch_by_scope';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { useDocumentDetailsContext } from '../../shared/context';
import { PreferenceFormattedDate } from '../../../../common/components/formatted_date';
import { FLYOUT_ALERT_HEADER_TITLE_TEST_ID, ALERT_SUMMARY_PANEL_TEST_ID } from './test_ids';

View file

@ -11,7 +11,7 @@ import { EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FlyoutTitle } from '../../../shared/components/flyout_title';
import { DocumentSeverity } from './severity';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { useDocumentDetailsContext } from '../../shared/context';
import { PreferenceFormattedDate } from '../../../../common/components/formatted_date';
import { FLYOUT_EVENT_HEADER_TITLE_TEST_ID } from './test_ids';

View file

@ -11,7 +11,7 @@ import { EuiButtonIcon, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@
import { i18n } from '@kbn/i18n';
import { NewChatByTitle } from '@kbn/elastic-assistant';
import { useGetAlertDetailsFlyoutLink } from '../../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { useAssistant } from '../hooks/use_assistant';
import {
ALERT_SUMMARY_CONVERSATION_ID,

View file

@ -12,7 +12,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiInMemoryTable, EuiPanel, EuiTitle } from
import { FormattedMessage } from '@kbn/i18n-react';
import { convertHighlightedFieldsToTableRow } from '../../shared/utils/highlighted_fields_helpers';
import { useRuleWithFallback } from '../../../../detection_engine/rule_management/logic/use_rule_with_fallback';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { HighlightedFieldsCell } from './highlighted_fields_cell';
import { CellActions } from './cell_actions';
import { HIGHLIGHTED_FIELDS_DETAILS_TEST_ID, HIGHLIGHTED_FIELDS_TITLE_TEST_ID } from './test_ids';

View file

@ -21,9 +21,11 @@ import { mockDataFormattedForFieldBrowser } from '../../shared/mocks/mock_data_f
import { TestProvider } from '@kbn/expandable-flyout/src/test/provider';
import { mockContextValue } from '../../shared/mocks/mock_context';
import { useExpandSection } from '../hooks/use_expand_section';
import { useHighlightedFields } from '../../shared/hooks/use_highlighted_fields';
jest.mock('../../../../detection_engine/rule_management/logic/use_rule_with_fallback');
jest.mock('../hooks/use_expand_section');
jest.mock('../../shared/hooks/use_highlighted_fields');
const panelContextValue = {
...mockContextValue,
@ -65,6 +67,7 @@ describe('<InvestigationSection />', () => {
it('should render the component expanded if value is true in local storage', () => {
(useExpandSection as jest.Mock).mockReturnValue(true);
(useHighlightedFields as jest.Mock).mockReturnValue([]);
const { getByTestId } = renderInvestigationSection();
expect(getByTestId(INVESTIGATION_SECTION_CONTENT_TEST_ID)).toBeVisible();
@ -72,6 +75,7 @@ describe('<InvestigationSection />', () => {
it('should render investigation guide and highlighted fields when document is signal', () => {
(useExpandSection as jest.Mock).mockReturnValue(true);
(useHighlightedFields as jest.Mock).mockReturnValue([]);
const { getByTestId } = renderInvestigationSection();
expect(getByTestId(INVESTIGATION_GUIDE_TEST_ID)).toBeInTheDocument();
@ -80,6 +84,7 @@ describe('<InvestigationSection />', () => {
it('should not render investigation guide when document is not signal', () => {
(useExpandSection as jest.Mock).mockReturnValue(true);
(useHighlightedFields as jest.Mock).mockReturnValue([]);
const mockGetFieldsData = (field: string) => {
switch (field) {

View file

@ -20,7 +20,7 @@ import {
REASON_DETAILS_TEST_ID,
REASON_TITLE_TEST_ID,
} from './test_ids';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import { useDocumentDetailsContext } from '../../shared/context';
export const ALERT_REASON_BANNER = {

View file

@ -11,12 +11,12 @@ import { renderReactTestingLibraryWithI18n as render } from '@kbn/test-jest-help
import { PanelHeader } from './header';
import { allThreeTabs } from './hooks/use_tabs';
import { GuidedOnboardingTourStep } from '../../../common/components/guided_onboarding_tour/tour_step';
import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../shared/hooks/use_basic_data_from_details_data';
jest.mock('../shared/context', () => ({
useDocumentDetailsContext: jest.fn().mockReturnValue({ dataFormattedForFieldBrowser: [] }),
}));
jest.mock('../../../timelines/components/side_panel/event_details/helpers', () => ({
jest.mock('../shared/hooks/use_basic_data_from_details_data', () => ({
useBasicDataFromDetailsData: jest.fn(),
}));
jest.mock('../../../common/components/guided_onboarding_tour/tour_step', () => ({

View file

@ -16,7 +16,7 @@ import { FlyoutHeaderTabs } from '../../shared/components/flyout_header_tabs';
import { AlertHeaderTitle } from './components/alert_header_title';
import { EventHeaderTitle } from './components/event_header_title';
import { useDocumentDetailsContext } from '../shared/context';
import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../shared/hooks/use_basic_data_from_details_data';
import {
AlertsCasesTourSteps,
getTourAnchor,

View file

@ -81,7 +81,11 @@ describe('useAssistant', () => {
expect(await getPromptContext()).toEqual({
'@timestamp': ['2023-01-01T01:01:01.000Z'],
_id: ['_id'],
_index: ['index'],
'agent.id': ['agent.id'],
'event.category': ['registry'],
'host.name': ['host-name'],
'kibana.alert.ancestors.id': ['ancestors-id'],
'kibana.alert.rule.description': ['rule-description'],
'kibana.alert.rule.indices': ['rule-indices'],
@ -89,8 +93,10 @@ describe('useAssistant', () => {
'kibana.alert.rule.parameters.index': ['rule-parameters-index'],
'kibana.alert.rule.type': ['query'],
'kibana.alert.rule.uuid': ['rule-uuid'],
'kibana.alert.url': ['alert-url'],
'kibana.alert.workflow_status': ['open'],
'process.entity_id': ['process-entity_id'],
'user.name': ['user-name'],
});
});
});

View file

@ -9,7 +9,7 @@ import { useMemo } from 'react';
import { groupBy } from 'lodash';
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import type { CtiEnrichment } from '../../../../../common/search_strategy';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
import {
filterDuplicateEnrichments,
getEnrichmentFields,

View file

@ -45,7 +45,7 @@ describe('useSessionPreview', () => {
expect(hookResult.result.current).toEqual({
index: 'kibana.alert.ancestors.index',
investigatedAlertId: 'id',
investigatedAlertId: '_id',
jumpToCursor: '2023-01-01T00:00:00.000Z',
jumpToEntityId: 'process.entity_id',
sessionEntityId: 'process.entry_leader.entity_id',
@ -79,8 +79,8 @@ describe('useSessionPreview', () => {
});
expect(hookResult.result.current).toEqual({
index: '.some-index',
investigatedAlertId: 'id',
index: 'index',
investigatedAlertId: '_id',
jumpToCursor: '2023-01-01T00:00:00.000Z',
jumpToEntityId: 'process.entity_id',
sessionEntityId: 'process.entry_leader.entity_id',

View file

@ -9,7 +9,7 @@ import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import type { SessionViewConfig } from '@kbn/securitysolution-data-table/common/types';
import type { GetFieldsData } from '../../../../common/hooks/use_get_fields_data';
import { getField } from '../../shared/utils';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../shared/hooks/use_basic_data_from_details_data';
export interface UseSessionPreviewParams {
/**

View file

@ -13,7 +13,7 @@ import { useEventDetails } from './hooks/use_event_details';
import { FlyoutError } from '../../shared/components/flyout_error';
import { FlyoutLoading } from '../../shared/components/flyout_loading';
import type { SearchHit } from '../../../../common/search_strategy';
import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from './hooks/use_basic_data_from_details_data';
import type { DocumentDetailsProps } from './types';
import type { GetFieldsData } from '../../../common/hooks/use_get_fields_data';
import { useRuleWithFallback } from '../../../detection_engine/rule_management/logic/use_rule_with_fallback';

View file

@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { renderHook } from '@testing-library/react-hooks';
import { useBasicDataFromDetailsData } from './use_basic_data_from_details_data';
import { mockDataFormattedForFieldBrowser } from '../mocks/mock_data_formatted_for_field_browser';
describe('useBasicDataFromDetailsData', () => {
it('should return all empty properties', () => {
const hookResult = renderHook(() => useBasicDataFromDetailsData(null));
expect(hookResult.result.current.agentId).toEqual('');
expect(hookResult.result.current.alertId).toEqual('');
expect(hookResult.result.current.alertUrl).toEqual('');
expect(hookResult.result.current.data).toEqual(null);
expect(hookResult.result.current.hostName).toEqual('');
expect(hookResult.result.current.indexName).toEqual('');
expect(hookResult.result.current.isAlert).toEqual(false);
expect(hookResult.result.current.ruleDescription).toEqual('');
expect(hookResult.result.current.ruleId).toEqual('');
expect(hookResult.result.current.ruleName).toEqual('');
expect(hookResult.result.current.timestamp).toEqual('');
expect(hookResult.result.current.userName).toEqual('');
});
it('should return all properties', () => {
const hookResult = renderHook(() =>
useBasicDataFromDetailsData(mockDataFormattedForFieldBrowser)
);
expect(hookResult.result.current.agentId).toEqual('agent.id');
expect(hookResult.result.current.alertId).toEqual('_id');
expect(hookResult.result.current.alertUrl).toEqual('alert-url');
expect(hookResult.result.current.data).toEqual(mockDataFormattedForFieldBrowser);
expect(hookResult.result.current.hostName).toEqual('host-name');
expect(hookResult.result.current.indexName).toEqual('index');
expect(hookResult.result.current.isAlert).toEqual(true);
expect(hookResult.result.current.ruleDescription).toEqual('rule-description');
expect(hookResult.result.current.ruleId).toEqual('rule-uuid');
expect(hookResult.result.current.ruleName).toEqual('rule-name');
expect(hookResult.result.current.timestamp).toEqual('2023-01-01T01:01:01.000Z');
expect(hookResult.result.current.userName).toEqual('user-name');
});
});

View file

@ -0,0 +1,120 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { some } from 'lodash/fp';
import { useMemo } from 'react';
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import { getAlertDetailsFieldValue } from '../../../../common/lib/endpoint/utils/get_event_details_field_values';
export interface UseBasicDataFromDetailsDataResult {
agentId: string;
alertId: string;
alertUrl: string;
data: TimelineEventsDetailsItem[] | null;
hostName: string;
indexName: string;
isAlert: boolean;
ruleDescription: string;
ruleId: string;
ruleName: string;
timestamp: string;
userName: string;
}
export const useBasicDataFromDetailsData = (
data: TimelineEventsDetailsItem[] | null
): UseBasicDataFromDetailsDataResult => {
const agentId = useMemo(
() => getAlertDetailsFieldValue({ category: 'agent', field: 'agent.id' }, data),
[data]
);
const alertId = useMemo(
() => getAlertDetailsFieldValue({ category: '_id', field: '_id' }, data),
[data]
);
const alertUrl = useMemo(
() => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.url' }, data),
[data]
);
const hostName = useMemo(
() => getAlertDetailsFieldValue({ category: 'host', field: 'host.name' }, data),
[data]
);
const indexName = useMemo(
() => getAlertDetailsFieldValue({ category: '_index', field: '_index' }, data),
[data]
);
const isAlert = some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data);
const ruleDescription = useMemo(
() =>
getAlertDetailsFieldValue(
{ category: 'kibana', field: 'kibana.alert.rule.description' },
data
),
[data]
);
const ruleId = useMemo(
() =>
isAlert
? getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data)
: getAlertDetailsFieldValue({ category: 'signal', field: 'signal.rule.id' }, data),
[isAlert, data]
);
const ruleName = useMemo(
() => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.name' }, data),
[data]
);
const timestamp = useMemo(
() => getAlertDetailsFieldValue({ category: 'base', field: '@timestamp' }, data),
[data]
);
const userName = useMemo(
() => getAlertDetailsFieldValue({ category: 'user', field: 'user.name' }, data),
[data]
);
return useMemo(
() => ({
agentId,
alertId,
alertUrl,
data,
hostName,
indexName,
isAlert,
ruleDescription,
ruleId,
ruleName,
timestamp,
userName,
}),
[
agentId,
alertId,
alertUrl,
data,
hostName,
indexName,
isAlert,
ruleDescription,
ruleId,
ruleName,
timestamp,
userName,
]
);
};

View file

@ -23,9 +23,15 @@ describe('useHighlightedFields', () => {
it('should return data', () => {
const hookResult = renderHook(() => useHighlightedFields({ dataFormattedForFieldBrowser }));
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'user.name': {
values: ['user-name'],
},
});
});
@ -63,9 +69,15 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'user.name': {
values: ['user-name'],
},
});
});
@ -93,11 +105,17 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'agent.id': {
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
values: ['agent.id'],
},
'user.name': {
values: ['user-name'],
},
});
});
@ -121,9 +139,15 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'user.name': {
values: ['user-name'],
},
});
});
@ -143,9 +167,15 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'user.name': {
values: ['user-name'],
},
});
});
@ -175,12 +205,18 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
[agentIdField]: {
values: ['deb35a20-70f8-458e-a64a-c9e6f7575893'],
},
'user.name': {
values: ['user-name'],
},
});
}
);
@ -209,12 +245,18 @@ describe('useHighlightedFields', () => {
);
expect(hookResult.result.current).toEqual({
'host.name': {
values: ['host-name'],
},
'kibana.alert.rule.type': {
values: ['query'],
},
'device.id': {
values: ['expectedCrowdstrikeAgentId'],
},
'user.name': {
values: ['user-name'],
},
});
});
});

View file

@ -11,12 +11,12 @@ import type {
UseInvestigationGuideParams,
UseInvestigationGuideResult,
} from './use_investigation_guide';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from './use_basic_data_from_details_data';
import { useRuleWithFallback } from '../../../../detection_engine/rule_management/logic/use_rule_with_fallback';
import { mockDataFormattedForFieldBrowser } from '../mocks/mock_data_formatted_for_field_browser';
import { useInvestigationGuide } from './use_investigation_guide';
jest.mock('../../../../timelines/components/side_panel/event_details/helpers');
jest.mock('./use_basic_data_from_details_data');
jest.mock('../../../../detection_engine/rule_management/logic/use_rule_with_fallback');
const dataFormattedForFieldBrowser = mockDataFormattedForFieldBrowser;

View file

@ -6,8 +6,8 @@
*/
import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import type { GetBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers';
import type { UseBasicDataFromDetailsDataResult } from './use_basic_data_from_details_data';
import { useBasicDataFromDetailsData } from './use_basic_data_from_details_data';
import { useRuleWithFallback } from '../../../../detection_engine/rule_management/logic/use_rule_with_fallback';
export interface UseInvestigationGuideParams {
@ -27,11 +27,11 @@ export interface UseInvestigationGuideResult {
*/
error: unknown;
/**
*
* The basic alert fields and their value
*/
basicAlertData: GetBasicDataFromDetailsData;
basicAlertData: UseBasicDataFromDetailsDataResult;
/**
*
* The note from the rule
*/
ruleNote: string | undefined;
}

View file

@ -16,6 +16,20 @@ export const ruleTypeField: TimelineEventsDetailsItem = {
};
export const baseFields: TimelineEventsDetailsItem[] = [
{
category: 'agent',
field: 'agent.id',
values: ['agent.id'],
originalValue: ['agent.id'],
isObjectArray: false,
},
{
category: '_id',
field: '_id',
values: ['_id'],
originalValue: ['_id'],
isObjectArray: false,
},
{
category: 'base',
field: '@timestamp',
@ -65,6 +79,13 @@ export const baseFields: TimelineEventsDetailsItem[] = [
originalValue: ['rule-parameters-index'],
isObjectArray: false,
},
{
category: 'kibana',
field: 'kibana.alert.url',
values: ['alert-url'],
originalValue: ['alert-url'],
isObjectArray: false,
},
{
category: 'kibana',
field: 'kibana.alert.rule.uuid',
@ -86,6 +107,27 @@ export const baseFields: TimelineEventsDetailsItem[] = [
originalValue: ['process-entity_id'],
isObjectArray: false,
},
{
category: 'host',
field: 'host.name',
values: ['host-name'],
originalValue: ['host-name'],
isObjectArray: false,
},
{
category: 'user',
field: 'user.name',
values: ['user-name'],
originalValue: ['user-name'],
isObjectArray: false,
},
{
category: '_index',
field: '_index',
values: ['index'],
originalValue: ['index'],
isObjectArray: false,
},
];
/**

View file

@ -5,121 +5,8 @@
* 2.0.
*/
import { some } from 'lodash/fp';
import { useMemo } from 'react';
import { getAlertDetailsFieldValue } from '../../../../common/lib/endpoint/utils/get_event_details_field_values';
import type { TimelineEventsDetailsItem } from '../../../../../common/search_strategy';
import { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants';
export interface GetBasicDataFromDetailsData {
agentId?: string;
alertId: string;
alertUrl?: string;
data: TimelineEventsDetailsItem[] | null;
hostName: string;
indexName?: string;
isAlert: boolean;
ruleDescription: string;
ruleId: string;
ruleName: string;
timestamp: string;
userName: string;
}
export const useBasicDataFromDetailsData = (
data: TimelineEventsDetailsItem[] | null
): GetBasicDataFromDetailsData => {
const isAlert = some({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data);
const ruleId = useMemo(
() =>
isAlert
? getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.uuid' }, data)
: getAlertDetailsFieldValue({ category: 'signal', field: 'signal.rule.id' }, data),
[isAlert, data]
);
const ruleName = useMemo(
() => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.rule.name' }, data),
[data]
);
const ruleDescription = useMemo(
() =>
getAlertDetailsFieldValue(
{ category: 'kibana', field: 'kibana.alert.rule.description' },
data
),
[data]
);
const alertId = useMemo(
() => getAlertDetailsFieldValue({ category: '_id', field: '_id' }, data),
[data]
);
const indexName = useMemo(
() => getAlertDetailsFieldValue({ category: '_index', field: '_index' }, data),
[data]
);
const alertUrl = useMemo(
() => getAlertDetailsFieldValue({ category: 'kibana', field: 'kibana.alert.url' }, data),
[data]
);
const agentId = useMemo(
() => getAlertDetailsFieldValue({ category: 'agent', field: 'agent.id' }, data),
[data]
);
const hostName = useMemo(
() => getAlertDetailsFieldValue({ category: 'host', field: 'host.name' }, data),
[data]
);
const userName = useMemo(
() => getAlertDetailsFieldValue({ category: 'user', field: 'user.name' }, data),
[data]
);
const timestamp = useMemo(
() => getAlertDetailsFieldValue({ category: 'base', field: '@timestamp' }, data),
[data]
);
return useMemo(
() => ({
agentId,
alertId,
alertUrl,
data,
hostName,
indexName,
isAlert,
ruleDescription,
ruleId,
ruleName,
timestamp,
userName,
}),
[
agentId,
alertId,
alertUrl,
data,
hostName,
indexName,
isAlert,
ruleDescription,
ruleId,
ruleName,
timestamp,
userName,
]
);
};
/*
The referenced alert _index in the flyout uses the `.internal.` such as
`.internal.alerts-security.alerts-spaceId` in the alert page flyout and

View file

@ -2544,6 +2544,11 @@
"discover.embeddable.search.displayName": "rechercher",
"discover.errorCalloutShowErrorMessage": "Afficher les détails",
"discover.esqlMode.selectedColumnsCallout": "Affichage de {selectedColumnsNumber} champs sur {esqlQueryColumnsNumber}. Ajoutez-en dautres depuis la liste des champs disponibles.",
"discover.esqlToDataViewTransitionModal.closeButtonLabel": "Basculer sans sauvegarder",
"discover.esqlToDataViewTransitionModal.dismissButtonLabel": "Ne plus afficher cet avertissement",
"discover.esqlToDataViewTransitionModal.saveButtonLabel": "Sauvegarder et basculer",
"discover.esqlToDataViewTransitionModal.title": "Votre requête sera supprimée",
"discover.esqlToDataviewTransitionModalBody": "Modifier la vue de données supprime la requête ES|QL en cours. Sauvegardez cette recherche pour ne pas perdre de travail.",
"discover.fieldChooser.availableFieldsTooltip": "Champs disponibles pour l'affichage dans le tableau.",
"discover.fieldChooser.discoverField.addFieldTooltip": "Ajouter le champ en tant que colonne",
"discover.fieldChooser.discoverField.removeFieldTooltip": "Supprimer le champ du tableau",

View file

@ -2544,6 +2544,11 @@
"discover.embeddable.search.displayName": "検索",
"discover.errorCalloutShowErrorMessage": "詳細を表示",
"discover.esqlMode.selectedColumnsCallout": "{esqlQueryColumnsNumber}フィールド中{selectedColumnsNumber}フィールドを表示中です。利用可能なフィールドリストからさらに追加します。",
"discover.esqlToDataViewTransitionModal.closeButtonLabel": "保存せずに切り替え",
"discover.esqlToDataViewTransitionModal.dismissButtonLabel": "次回以降この警告を表示しない",
"discover.esqlToDataViewTransitionModal.saveButtonLabel": "保存して切り替え",
"discover.esqlToDataViewTransitionModal.title": "クエリは削除されます",
"discover.esqlToDataviewTransitionModalBody": "データビューを切り替えると、現在のES|QLクエリが削除されます。この検索を保存すると、作業内容が失われないことが保証されます。",
"discover.fieldChooser.availableFieldsTooltip": "フィールドをテーブルに表示できます。",
"discover.fieldChooser.discoverField.addFieldTooltip": "フィールドを列として追加",
"discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除",

View file

@ -2546,6 +2546,11 @@
"discover.embeddable.search.displayName": "搜索",
"discover.errorCalloutShowErrorMessage": "查看详情",
"discover.esqlMode.selectedColumnsCallout": "正在显示 {selectedColumnsNumber} 个字段,共 {esqlQueryColumnsNumber} 个。从可用字段列表中添加更多字段。",
"discover.esqlToDataViewTransitionModal.closeButtonLabel": "切换而不保存",
"discover.esqlToDataViewTransitionModal.dismissButtonLabel": "不再显示此警告",
"discover.esqlToDataViewTransitionModal.saveButtonLabel": "保存并切换",
"discover.esqlToDataViewTransitionModal.title": "将移除您的查询",
"discover.esqlToDataviewTransitionModalBody": "切换数据视图会移除当前的 ES|QL 查询。保存此搜索以确保不会丢失工作。",
"discover.fieldChooser.availableFieldsTooltip": "适用于在表中显示的字段。",
"discover.fieldChooser.discoverField.addFieldTooltip": "将字段添加为列",
"discover.fieldChooser.discoverField.removeFieldTooltip": "从表中移除字段",