Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Security Solution] Update preview navigation in entity details flyout (#204513) #204961

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import React from 'react';
import { render } from '@testing-library/react';
import { AlertsPreview } from './alerts_preview';
import { TestProviders } from '../../../common/mock/test_providers';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import type { ParsedAlertsData } from '../../../overview/components/detection_response/alerts_by_status/types';
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';

const mockAlertsData: ParsedAlertsData = {
open: {
Expand All @@ -35,18 +33,14 @@ const mockAlertsData: ParsedAlertsData = {
// Mock hooks
jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview');
jest.mock('@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview');
jest.mock('../../../entity_analytics/api/hooks/use_risk_score');
jest.mock('@kbn/expandable-flyout');

describe('AlertsPreview', () => {
const mockOpenLeftPanel = jest.fn();

beforeEach(() => {
(useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel });
(useVulnerabilitiesPreview as jest.Mock).mockReturnValue({
data: { count: { CRITICAL: 0, HIGH: 1, MEDIUM: 1, LOW: 0, UNKNOWN: 0 } },
});
(useRiskScore as jest.Mock).mockReturnValue({ data: [{ host: { risk: 75 } }] });
(useMisconfigurationPreview as jest.Mock).mockReturnValue({
data: { count: { passed: 1, failed: 1 } },
});
Expand All @@ -58,7 +52,11 @@ describe('AlertsPreview', () => {
it('renders', () => {
const { getByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
<AlertsPreview
alertsData={mockAlertsData}
isLinkEnabled={true}
openDetailsPanel={mockOpenLeftPanel}
/>
</TestProviders>
);

Expand All @@ -68,7 +66,11 @@ describe('AlertsPreview', () => {
it('renders correct alerts number', () => {
const { getByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
<AlertsPreview
alertsData={mockAlertsData}
isLinkEnabled={true}
openDetailsPanel={mockOpenLeftPanel}
/>
</TestProviders>
);

Expand All @@ -78,7 +80,11 @@ describe('AlertsPreview', () => {
it('should render the correct number of distribution bar section based on the number of severities', () => {
const { queryAllByTestId } = render(
<TestProviders>
<AlertsPreview alertsData={mockAlertsData} value="host1" field="host.name" />
<AlertsPreview
alertsData={mockAlertsData}
isLinkEnabled={true}
openDetailsPanel={mockOpenLeftPanel}
/>
</TestProviders>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';
import { capitalize } from 'lodash';
import type { EuiThemeComputed } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle, useEuiTheme } from '@elastic/eui';
Expand All @@ -18,8 +18,11 @@ import type {
} from '../../../overview/components/detection_response/alerts_by_status/types';
import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel';
import { getSeverityColor } from '../../../detections/components/alerts_kpis/severity_level_panel/helpers';
import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
import { useNavigateEntityInsight } from '../../hooks/use_entity_insight';
import type { EntityDetailsPath } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
import {
CspInsightLeftPanelSubTab,
EntityDetailsLeftPanelTab,
} from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';

const AlertsCount = ({
alertsTotal,
Expand Down Expand Up @@ -58,14 +61,14 @@ const AlertsCount = ({

export const AlertsPreview = ({
alertsData,
field,
value,
isPreviewMode,
openDetailsPanel,
isLinkEnabled,
}: {
alertsData: ParsedAlertsData;
field: 'host.name' | 'user.name';
value: string;
isPreviewMode?: boolean;
openDetailsPanel: (path: EntityDetailsPath) => void;
isLinkEnabled: boolean;
}) => {
const { euiTheme } = useEuiTheme();

Expand All @@ -90,15 +93,16 @@ export const AlertsPreview = ({

const hasNonClosedAlerts = totalAlertsCount > 0;

const { goToEntityInsightTab } = useNavigateEntityInsight({
field,
value,
queryIdExtension: isPreviewMode ? 'ALERTS_PREVIEW_TRUE' : 'ALERTS_PREVIEW_FALSE',
subTab: CspInsightLeftPanelSubTab.ALERTS,
});
const goToEntityInsightTab = useCallback(() => {
openDetailsPanel({
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
subTab: CspInsightLeftPanelSubTab.ALERTS,
});
}, [openDetailsPanel]);

const link = useMemo(
() =>
!isPreviewMode
isLinkEnabled
? {
callback: goToEntityInsightTab,
tooltip: (
Expand All @@ -109,7 +113,7 @@ export const AlertsPreview = ({
),
}
: undefined,
[isPreviewMode, goToEntityInsightTab]
[isLinkEnabled, goToEntityInsightTab]
);
return (
<ExpandablePanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@ import { AlertsPreview } from './alerts/alerts_preview';
import { useGlobalTime } from '../../common/containers/use_global_time';
import { DETECTION_RESPONSE_ALERTS_BY_STATUS_ID } from '../../overview/components/detection_response/alerts_by_status/types';
import { useNonClosedAlerts } from '../hooks/use_non_closed_alerts';
import type { EntityDetailsPath } from '../../flyout/entity_details/shared/components/left_panel/left_panel_header';

export const EntityInsight = <T,>({
value,
field,
isPreviewMode,
isLinkEnabled,
openDetailsPanel,
}: {
value: string;
field: 'host.name' | 'user.name';
isPreviewMode?: boolean;
isLinkEnabled: boolean;
openDetailsPanel: (path: EntityDetailsPath) => void;
}) => {
const { euiTheme } = useEuiTheme();
const insightContent: React.ReactElement[] = [];
Expand Down Expand Up @@ -55,9 +60,9 @@ export const EntityInsight = <T,>({
<>
<AlertsPreview
alertsData={filteredAlertsData}
field={field}
value={value}
isPreviewMode={isPreviewMode}
isLinkEnabled={isLinkEnabled}
openDetailsPanel={openDetailsPanel}
/>
<EuiSpacer size="s" />
</>
Expand All @@ -67,14 +72,26 @@ export const EntityInsight = <T,>({
if (showMisconfigurationsPreview)
insightContent.push(
<>
<MisconfigurationsPreview value={value} field={field} isPreviewMode={isPreviewMode} />
<MisconfigurationsPreview
value={value}
field={field}
isPreviewMode={isPreviewMode}
isLinkEnabled={isLinkEnabled}
openDetailsPanel={openDetailsPanel}
/>
<EuiSpacer size="s" />
</>
);
if (showVulnerabilitiesPreview)
insightContent.push(
<>
<VulnerabilitiesPreview value={value} field={field} isPreviewMode={isPreviewMode} />
<VulnerabilitiesPreview
value={value}
field={field}
isPreviewMode={isPreviewMode}
isLinkEnabled={isLinkEnabled}
openDetailsPanel={openDetailsPanel}
/>
<EuiSpacer size="s" />
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,19 @@ import { render } from '@testing-library/react';
import { MisconfigurationsPreview } from './misconfiguration_preview';
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { TestProviders } from '../../../common/mock/test_providers';

// Mock hooks
jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview');
jest.mock('@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview');
jest.mock('../../../entity_analytics/api/hooks/use_risk_score');
jest.mock('@kbn/expandable-flyout');

describe('MisconfigurationsPreview', () => {
const mockOpenLeftPanel = jest.fn();

beforeEach(() => {
(useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel });
(useVulnerabilitiesPreview as jest.Mock).mockReturnValue({
data: { count: { CRITICAL: 0, HIGH: 1, MEDIUM: 1, LOW: 0, UNKNOWN: 0 } },
});
(useRiskScore as jest.Mock).mockReturnValue({ data: [{ host: { risk: 75 } }] });
(useMisconfigurationPreview as jest.Mock).mockReturnValue({
data: { count: { passed: 1, failed: 1 } },
});
Expand All @@ -37,7 +31,12 @@ describe('MisconfigurationsPreview', () => {
it('renders', () => {
const { getByTestId } = render(
<TestProviders>
<MisconfigurationsPreview value="host1" field="host.name" />
<MisconfigurationsPreview
value="host1"
field="host.name"
isLinkEnabled={true}
openDetailsPanel={mockOpenLeftPanel}
/>
</TestProviders>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useEffect, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { css } from '@emotion/react';
import type { EuiThemeComputed } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme, EuiTitle } from '@elastic/eui';
Expand All @@ -20,8 +20,11 @@ import {
uiMetricService,
} from '@kbn/cloud-security-posture-common/utils/ui_metrics';
import { ExpandablePanel } from '../../../flyout/shared/components/expandable_panel';
import { CspInsightLeftPanelSubTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
import { useNavigateEntityInsight } from '../../hooks/use_entity_insight';
import type { EntityDetailsPath } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';
import {
CspInsightLeftPanelSubTab,
EntityDetailsLeftPanelTab,
} from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header';

export const getFindingsStats = (passedFindingsStats: number, failedFindingsStats: number) => {
if (passedFindingsStats === 0 && failedFindingsStats === 0) return [];
Expand Down Expand Up @@ -88,10 +91,14 @@ export const MisconfigurationsPreview = ({
value,
field,
isPreviewMode,
isLinkEnabled,
openDetailsPanel,
}: {
value: string;
field: 'host.name' | 'user.name';
isPreviewMode?: boolean;
isLinkEnabled: boolean;
openDetailsPanel: (path: EntityDetailsPath) => void;
}) => {
const { hasMisconfigurationFindings, passedFindings, failedFindings } = useHasMisconfigurations(
field,
Expand All @@ -103,15 +110,16 @@ export const MisconfigurationsPreview = ({
}, []);
const { euiTheme } = useEuiTheme();

const { goToEntityInsightTab } = useNavigateEntityInsight({
field,
value,
queryIdExtension: 'MISCONFIGURATION_PREVIEW',
subTab: CspInsightLeftPanelSubTab.MISCONFIGURATIONS,
});
const goToEntityInsightTab = useCallback(() => {
openDetailsPanel({
tab: EntityDetailsLeftPanelTab.CSP_INSIGHTS,
subTab: CspInsightLeftPanelSubTab.MISCONFIGURATIONS,
});
}, [openDetailsPanel]);

const link = useMemo(
() =>
!isPreviewMode
isLinkEnabled
? {
callback: goToEntityInsightTab,
tooltip: (
Expand All @@ -122,7 +130,7 @@ export const MisconfigurationsPreview = ({
),
}
: undefined,
[isPreviewMode, goToEntityInsightTab]
[isLinkEnabled, goToEntityInsightTab]
);
return (
<ExpandablePanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,19 @@ import { render } from '@testing-library/react';
import { VulnerabilitiesPreview } from './vulnerabilities_preview';
import { useMisconfigurationPreview } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview';
import { useVulnerabilitiesPreview } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview';
import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { TestProviders } from '../../../common/mock/test_providers';

// Mock hooks
jest.mock('@kbn/cloud-security-posture/src/hooks/use_misconfiguration_preview');
jest.mock('@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_preview');
jest.mock('../../../entity_analytics/api/hooks/use_risk_score');
jest.mock('@kbn/expandable-flyout');

describe('VulnerabilitiesPreview', () => {
const mockOpenLeftPanel = jest.fn();

beforeEach(() => {
(useExpandableFlyoutApi as jest.Mock).mockReturnValue({ openLeftPanel: mockOpenLeftPanel });
(useVulnerabilitiesPreview as jest.Mock).mockReturnValue({
data: { count: { CRITICAL: 0, HIGH: 1, MEDIUM: 1, LOW: 0, UNKNOWN: 0 } },
});
(useRiskScore as jest.Mock).mockReturnValue({ data: [{ host: { risk: 75 } }] });
(useMisconfigurationPreview as jest.Mock).mockReturnValue({
data: { count: { passed: 1, failed: 1 } },
});
Expand All @@ -37,7 +31,12 @@ describe('VulnerabilitiesPreview', () => {
it('renders', () => {
const { getByTestId } = render(
<TestProviders>
<VulnerabilitiesPreview value="host1" field="host.name" />
<VulnerabilitiesPreview
value="host1"
field="host.name"
isLinkEnabled={true}
openDetailsPanel={mockOpenLeftPanel}
/>
</TestProviders>
);

Expand Down
Loading
Loading