[Security Solution] remove unused detections code (#222458)

## Summary

This PR only removes a few unused components I found while doing a
bigger refactor.
This commit is contained in:
Philippe Oberti 2025-06-03 17:01:48 -05:00 committed by GitHub
parent d914f1114c
commit e7c62f3ce2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 0 additions and 521 deletions

View file

@ -306,8 +306,6 @@ module.exports = {
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]alerts_table[\/\\]additional_filters_action[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]alerts_table[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]osquery[\/\\]osquery_flyout.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]severity[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]status[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]value_lists_management_flyout[\/\\]reference_error_modal[\/\\]reference_error_modal.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]components[\/\\]value_lists_management_flyout[\/\\]table_helpers.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]asset_criticality[\/\\]asset_criticality_selector.stories.tsx/,

View file

@ -1,82 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { mount } from 'enzyme';
import React from 'react';
// Necessary until components being tested are migrated of styled-components https://github.com/elastic/kibana/issues/219037
import 'jest-styled-components';
import { Severity } from '.';
interface Expected {
color: string;
severity: 'low' | 'medium' | 'high' | 'critical' | 'any-other-severity';
textColor: string;
}
describe('Severity', () => {
const expected: Expected[] = [
{
color: '#C5CFD8',
severity: 'low',
textColor: 'default',
},
{
color: '#EFC44C',
severity: 'medium',
textColor: 'default',
},
{
color: '#FF7E62',
severity: 'high',
textColor: 'ghost',
},
{
color: '#C3505E',
severity: 'critical',
textColor: 'ghost',
},
{
color: 'hollow',
severity: 'any-other-severity',
textColor: 'default',
},
];
test('it capitalizes the provided `severity`', () => {
const wrapper = mount(<Severity severity={'critical'} />);
expect(wrapper.find('[data-test-subj="severity-badge"]').first()).toHaveStyleRule(
'text-transform',
'capitalize'
);
});
test('it renders the provided `severity`', () => {
const wrapper = mount(<Severity severity={'critical'} />);
expect(wrapper.text()).toBe('critical');
});
expected.forEach(({ severity, color, textColor }) => {
test(`it renders the expected badge color when severity is ${severity}`, () => {
const wrapper = mount(<Severity severity={severity} />);
expect(wrapper.find('[data-test-subj="severity-badge"]').first().props().color).toEqual(
color
);
});
test(`it renders the expected text color when severity is ${severity}`, () => {
const wrapper = mount(<Severity severity={severity} />);
expect(wrapper.find('[data-test-subj="severity-text"]').first().props().color).toEqual(
textColor
);
});
});
});

View file

@ -1,56 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { EuiBadge, EuiText } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
const SeverityBadge = styled(EuiBadge)`
align-items: center;
display: inline-flex;
height: 40px;
text-transform: capitalize;
`;
const getBadgeColorFromSeverity = (severity: string) => {
switch (`${severity}`.toLowerCase()) {
case 'low':
return '#C5CFD8';
case 'medium':
return '#EFC44C';
case 'high':
return '#FF7E62';
case 'critical':
return '#C3505E';
default:
return 'hollow';
}
};
const getTextColorFromSeverity = (severity: string) => {
switch (`${severity}`.toLowerCase()) {
case 'critical': // fall through
case 'high':
return 'ghost';
default:
return 'default';
}
};
interface Props {
severity: string;
}
const SeverityComponent: React.FC<Props> = ({ severity }) => (
<SeverityBadge color={getBadgeColorFromSeverity(severity)} data-test-subj="severity-badge">
<EuiText color={getTextColorFromSeverity(severity)} data-test-subj="severity-text" size="xs">
{severity}
</EuiText>
</SeverityBadge>
);
export const Severity = React.memo(SeverityComponent);

View file

@ -1,53 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { mount } from 'enzyme';
import React from 'react';
import { Status } from '.';
interface Expected {
badgeColor: string;
iconType: 'check' | 'warning';
status: 'active' | 'recovered' | 'any-other-status';
}
describe('Status', () => {
const expected: Expected[] = [
{
badgeColor: 'danger',
iconType: 'warning',
status: 'active',
},
{
badgeColor: 'hollow',
iconType: 'check',
status: 'recovered',
},
{
badgeColor: 'danger',
iconType: 'warning',
status: 'any-other-status',
},
];
expected.forEach(({ status, badgeColor, iconType }) => {
test(`it renders the expected badge color when status is ${status}`, () => {
const wrapper = mount(<Status status={status} />);
expect(wrapper.find('[data-test-subj="status-icon"]').first().props().color).toEqual(
badgeColor
);
});
test(`it renders the expected icon type when status is ${status}`, () => {
const wrapper = mount(<Status status={status} />);
expect(wrapper.find('[data-test-subj="status-icon"]').first().props().type).toEqual(iconType);
});
});
});

View file

@ -1,53 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { EuiIcon } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
export const STATUS_CLASS_NAME = 'alert-status-icon';
const StatusContainer = styled.span`
display: inline-flex;
justify-content: center;
width: 100%;
`;
export const getBadgeColorFromStatus = (status: string) => {
switch (`${status}`.toLowerCase()) {
case 'recovered':
return 'hollow';
default:
return 'danger';
}
};
export const getIconTypeFromStatus = (status: string) => {
switch (`${status}`.toLowerCase()) {
case 'recovered':
return 'check';
default:
return 'warning';
}
};
interface Props {
status: string;
}
const StatusComponent: React.FC<Props> = ({ status }) => (
<StatusContainer>
<EuiIcon
className={STATUS_CLASS_NAME}
color={getBadgeColorFromStatus(status)}
data-test-subj="status-icon"
type={getIconTypeFromStatus(status)}
/>
</StatusContainer>
);
export const Status = React.memo(StatusComponent);

View file

@ -1,53 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { EuiDataGridColumn } from '@elastic/eui';
import { ALERT_DURATION, ALERT_REASON, ALERT_STATUS } from '@kbn/rule-data-utils';
import type { ColumnHeaderOptions } from '../../../../../common/types';
import { defaultColumnHeaderType } from '../../../../timelines/components/timeline/body/column_headers/default_headers';
import { DEFAULT_DATE_COLUMN_MIN_WIDTH } from '../../../../timelines/components/timeline/body/constants';
import * as i18n from '../../../components/alerts_table/translations';
/**
* columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
* plus additional TGrid column properties
*/
export const columns: Array<
Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.STATUS,
id: ALERT_STATUS,
initialWidth: 74,
},
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.TRIGGERED,
id: '@timestamp',
initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
},
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.ALERT_DURATION,
id: ALERT_DURATION,
initialWidth: 116,
},
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
id: 'signal.rule.severity',
initialWidth: 102,
},
{
columnHeaderType: defaultColumnHeaderType,
displayAsText: i18n.ALERTS_HEADERS_REASON,
id: ALERT_REASON,
},
];

View file

@ -1,11 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { columns } from './columns';
import { RenderCellValue } from './render_cell_value';
export { columns, RenderCellValue };

View file

@ -1,119 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { mount } from 'enzyme';
import { cloneDeep } from 'lodash/fp';
import React from 'react';
import { ALERT_DURATION, ALERT_STATUS } from '@kbn/rule-data-utils';
import { mockBrowserFields } from '../../../../common/containers/source/mock';
import { DragDropContextWrapper } from '../../../../common/components/drag_and_drop/drag_drop_context_wrapper';
import { defaultHeaders, mockTimelineData, TestProviders } from '../../../../common/mock';
import type { TimelineNonEcsData } from '../../../../../common/search_strategy/timeline';
import type { CellValueElementProps } from '../../../../timelines/components/timeline/cell_rendering';
import { DefaultCellRenderer } from '../../../../timelines/components/timeline/cell_rendering/default_cell_renderer';
import type { ColumnHeaderOptions } from '../../../../../common/types';
import { RenderCellValue } from '.';
jest.mock('../../../../common/lib/kibana');
describe('RenderCellValue', () => {
const columnId = '@timestamp';
const eventId = '_id-123';
const linkValues = ['foo', 'bar', '@baz'];
const rowIndex = 5;
const scopeId = 'table-test';
let data: TimelineNonEcsData[];
let header: ColumnHeaderOptions;
let props: CellValueElementProps;
beforeEach(() => {
data = cloneDeep(mockTimelineData[0].data);
header = cloneDeep(defaultHeaders[0]);
props = {
columnId,
data,
eventId,
header,
isDetails: false,
isExpandable: false,
isExpanded: false,
linkValues,
rowIndex,
colIndex: 0,
setCellProps: jest.fn(),
scopeId,
};
});
test('it renders a custom alert status', () => {
const wrapper = mount(
<TestProviders>
<DragDropContextWrapper browserFields={mockBrowserFields}>
<RenderCellValue {...props} columnId={ALERT_STATUS} />
</DragDropContextWrapper>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="alert-status"]').exists()).toBe(true);
});
test('it renders a custom alert duration', () => {
const wrapper = mount(
<TestProviders>
<DragDropContextWrapper browserFields={mockBrowserFields}>
<RenderCellValue {...props} columnId={ALERT_DURATION} />
</DragDropContextWrapper>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="alert-duration"]').exists()).toBe(true);
});
test('it renders a custom rule severity', () => {
const wrapper = mount(
<TestProviders>
<DragDropContextWrapper browserFields={mockBrowserFields}>
<RenderCellValue {...props} columnId="signal.rule.severity" />
</DragDropContextWrapper>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="rule-severity"]').exists()).toBe(true);
});
test('it renders a custom reason', () => {
const wrapper = mount(
<TestProviders>
<DragDropContextWrapper browserFields={mockBrowserFields}>
<RenderCellValue {...props} columnId="signal.reason" />
</DragDropContextWrapper>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="reason"]').exists()).toBe(true);
});
test('it forwards the `CellValueElementProps` to the `DefaultCellRenderer` for any other field', () => {
const aRandomFieldName = 'a.random.field.name';
const wrapper = mount(
<TestProviders>
<DragDropContextWrapper browserFields={mockBrowserFields}>
<RenderCellValue {...props} columnId={aRandomFieldName} />
</DragDropContextWrapper>
</TestProviders>
);
expect(wrapper.find(DefaultCellRenderer).first().props()).toEqual({
...props,
columnId: aRandomFieldName,
});
});
});

View file

@ -1,92 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { random } from 'lodash/fp';
import moment from 'moment';
import React from 'react';
import type { EuiDataGridCellValueElementProps } from '@elastic/eui';
import { EuiLink } from '@elastic/eui';
import { ALERT_DURATION, ALERT_REASON, ALERT_SEVERITY, ALERT_STATUS } from '@kbn/rule-data-utils';
import { useGetMappedNonEcsValue } from '../../../../common/utils/get_mapped_non_ecs_value';
import { TruncatableText } from '../../../../common/components/truncatable_text';
import { Severity } from '../../../components/severity';
import type { CellValueElementProps } from '../../../../timelines/components/timeline/cell_rendering';
import { DefaultCellRenderer } from '../../../../timelines/components/timeline/cell_rendering/default_cell_renderer';
import { Status } from '../../../components/status';
const reason =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.';
/**
* This implementation of `EuiDataGrid`'s `renderCellValue`
* accepts `EuiDataGridCellValueElementProps`, plus `data`
* from the TGrid
*/
export const RenderCellValue: React.FC<
EuiDataGridCellValueElementProps & CellValueElementProps
> = ({
columnId,
data,
eventId,
header,
isDetails,
isExpandable,
isExpanded,
linkValues,
rowIndex,
colIndex,
setCellProps,
scopeId,
key,
}) => {
const value =
useGetMappedNonEcsValue({
data,
fieldName: columnId,
})?.reduce((x) => x[0]) ?? '';
switch (columnId) {
case ALERT_STATUS:
return (
<Status data-test-subj="alert-status" status={random(0, 1) ? 'recovered' : 'active'} />
);
case ALERT_DURATION:
case 'signal.duration.us':
return <span data-test-subj="alert-duration">{moment().fromNow(true)}</span>;
case ALERT_SEVERITY:
case 'signal.rule.severity':
return <Severity data-test-subj="rule-severity" severity={value} />;
case ALERT_REASON:
case 'signal.reason':
return (
<EuiLink data-test-subj="reason">
<TruncatableText>{reason}</TruncatableText>
</EuiLink>
);
default:
// NOTE: we're using `DefaultCellRenderer` in this example configuration as a fallback, but
// using `DefaultCellRenderer` here is entirely optional
return (
<DefaultCellRenderer
columnId={columnId}
data={data}
eventId={eventId}
header={header}
isDetails={isDetails}
isExpandable={isExpandable}
isExpanded={isExpanded}
linkValues={linkValues}
rowIndex={rowIndex}
colIndex={colIndex}
setCellProps={setCellProps}
scopeId={scopeId}
key={key}
/>
);
}
};