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] ThreeWayDiff UI: Add remaining field components for `FieldReadOnly` (#193261) #193825

Merged
merged 1 commit into from
Sep 24, 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 @@ -19,7 +19,7 @@ import { COLORS } from './constants';

/*
Finds an element with a text content that exactly matches the passed argument.
Handly because React Testing Library's doesn't provide an easy way to search by
Handy because React Testing Library's doesn't provide an easy way to search by
text if the text is split into multiple DOM elements.
*/
function findChildByTextContent(parent: Element, textContent: string): HTMLElement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ interface AuthorProps {
author: string[];
}

const Author = ({ author }: AuthorProps) => (
export const Author = ({ author }: AuthorProps) => (
<BadgeList badges={author} data-test-subj="authorPropertyValue" />
);

const BuildingBlock = () => (
export const BuildingBlock = () => (
<EuiText size="s" data-test-subj="buildingBlockPropertyValue">
{i18n.BUILDING_BLOCK_FIELD_DESCRIPTION}
</EuiText>
Expand Down Expand Up @@ -124,7 +124,7 @@ interface RiskScoreProps {
riskScore: number;
}

const RiskScore = ({ riskScore }: RiskScoreProps) => (
export const RiskScore = ({ riskScore }: RiskScoreProps) => (
<EuiText size="s" data-test-subj="riskScorePropertyValue">
{riskScore}
</EuiText>
Expand Down Expand Up @@ -157,7 +157,7 @@ interface ReferencesProps {
references: string[];
}

const References = ({ references }: ReferencesProps) => (
export const References = ({ references }: ReferencesProps) => (
<EuiText size="s">
<ul>
{references
Expand All @@ -173,7 +173,7 @@ const References = ({ references }: ReferencesProps) => (
</EuiText>
);

const FalsePositives = ({ falsePositives }: { falsePositives: string[] }) => (
export const FalsePositives = ({ falsePositives }: { falsePositives: string[] }) => (
<EuiText size="s">
<ul>
{falsePositives.map((falsePositivesItem) => (
Expand All @@ -192,15 +192,15 @@ interface InvestigationFieldsProps {
investigationFields: string[];
}

const InvestigationFields = ({ investigationFields }: InvestigationFieldsProps) => (
export const InvestigationFields = ({ investigationFields }: InvestigationFieldsProps) => (
<BadgeList badges={investigationFields} data-test-subj="investigationFieldsPropertyValue" />
);

interface LicenseProps {
license: string;
}

const License = ({ license }: LicenseProps) => (
export const License = ({ license }: LicenseProps) => (
<EuiText size="s" data-test-subj="licensePropertyValue">
{license}
</EuiText>
Expand All @@ -210,7 +210,7 @@ interface RuleNameOverrideProps {
ruleNameOverride: string;
}

const RuleNameOverride = ({ ruleNameOverride }: RuleNameOverrideProps) => (
export const RuleNameOverride = ({ ruleNameOverride }: RuleNameOverrideProps) => (
<EuiText size="s" data-test-subj="ruleNameOverridePropertyValue">
{ruleNameOverride}
</EuiText>
Expand All @@ -236,7 +236,7 @@ interface TimestampOverrideProps {
timestampOverride: string;
}

const TimestampOverride = ({ timestampOverride }: TimestampOverrideProps) => (
export const TimestampOverride = ({ timestampOverride }: TimestampOverrideProps) => (
<EuiText size="s" data-test-subj="timestampOverridePropertyValue">
{timestampOverride}
</EuiText>
Expand All @@ -246,7 +246,7 @@ interface MaxSignalsProps {
maxSignals: number;
}

const MaxSignals = ({ maxSignals }: MaxSignalsProps) => (
export const MaxSignals = ({ maxSignals }: MaxSignalsProps) => (
<EuiText size="s" data-test-subj="maxSignalsPropertyValue">
{maxSignals}
</EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ interface ThresholdProps {
threshold: ThresholdType;
}

const Threshold = ({ threshold }: ThresholdProps) => (
export const Threshold = ({ threshold }: ThresholdProps) => (
<div data-test-subj="thresholdPropertyValue">
{isEmpty(threshold.field[0])
? `${descriptionStepI18n.THRESHOLD_RESULTS_ALL} >= ${threshold.value}`
Expand All @@ -193,7 +193,7 @@ interface AnomalyThresholdProps {
anomalyThreshold: number;
}

const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => (
export const AnomalyThreshold = ({ anomalyThreshold }: AnomalyThresholdProps) => (
<EuiText size="s" data-test-subj="anomalyThresholdPropertyValue">
{anomalyThreshold}
</EuiText>
Expand Down Expand Up @@ -258,7 +258,7 @@ interface RuleTypeProps {
type: Type;
}

const RuleType = ({ type }: RuleTypeProps) => (
export const RuleType = ({ type }: RuleTypeProps) => (
<EuiText size="s">{getRuleTypeDescription(type)}</EuiText>
);

Expand Down Expand Up @@ -298,7 +298,7 @@ interface TimelineTitleProps {
timelineTitle: string;
}

const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => (
export const TimelineTitle = ({ timelineTitle }: TimelineTitleProps) => (
<EuiText size="s" data-test-subj="timelineTemplatePropertyValue">
{timelineTitle}
</EuiText>
Expand Down Expand Up @@ -354,15 +354,15 @@ interface SuppressAlertsByFieldProps {
fields: string[];
}

const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => (
export const SuppressAlertsByField = ({ fields }: SuppressAlertsByFieldProps) => (
<BadgeList badges={fields} data-test-subj="alertSuppressionGroupByPropertyValue" />
);

interface SuppressAlertsDurationProps {
duration?: Duration;
}

const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => {
export const SuppressAlertsDuration = ({ duration }: SuppressAlertsDurationProps) => {
const durationDescription = duration
? `${duration.value}${duration.unit}`
: descriptionStepI18n.ALERT_SUPPRESSION_PER_RULE_EXECUTION;
Expand All @@ -378,7 +378,7 @@ interface MissingFieldsStrategyProps {
missingFieldsStrategy?: AlertSuppressionMissingFieldsStrategy;
}

const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => {
export const MissingFieldsStrategy = ({ missingFieldsStrategy }: MissingFieldsStrategyProps) => {
const missingFieldsDescription =
missingFieldsStrategy === AlertSuppressionMissingFieldsStrategyEnum.suppress
? descriptionStepI18n.ALERT_SUPPRESSION_SUPPRESS_ON_MISSING_FIELDS
Expand All @@ -395,15 +395,15 @@ interface NewTermsFieldsProps {
newTermsFields: string[];
}

const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => (
export const NewTermsFields = ({ newTermsFields }: NewTermsFieldsProps) => (
<BadgeList badges={newTermsFields} data-test-subj="newTermsFieldsPropertyValue" />
);

interface HistoryWindowSizeProps {
historyWindowStart?: string;
}

const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => {
export const HistoryWindowSize = ({ historyWindowStart }: HistoryWindowSizeProps) => {
const size = historyWindowStart ? convertHistoryStartToSize(historyWindowStart) : '7d';

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,26 @@ import { getHumanizedDuration } from '../../../../detections/pages/detection_eng
import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants';
import * as i18n from './translations';

interface AccessibleTimeValueProps {
timeValue: string;
'data-test-subj'?: string;
}

export const AccessibleTimeValue = ({
timeValue,
'data-test-subj': dataTestSubj,
}: AccessibleTimeValueProps) => (
<EuiText size="s" data-test-subj={dataTestSubj}>
<IntervalAbbrScreenReader interval={timeValue} />
</EuiText>
);

interface IntervalProps {
interval: string;
}

const Interval = ({ interval }: IntervalProps) => (
<EuiText size="s" data-test-subj="intervalPropertyValue">
<IntervalAbbrScreenReader interval={interval} />
</EuiText>
<AccessibleTimeValue timeValue={interval} data-test-subj="intervalPropertyValue" />
);

interface FromProps {
Expand All @@ -30,9 +42,10 @@ interface FromProps {
}

const From = ({ from, interval }: FromProps) => (
<EuiText size="s" data-test-subj={`fromPropertyValue-${from}`}>
<IntervalAbbrScreenReader interval={getHumanizedDuration(from, interval)} />
</EuiText>
<AccessibleTimeValue
timeValue={getHumanizedDuration(from, interval)}
data-test-subj={`fromPropertyValue-${from}`}
/>
);

export interface RuleScheduleSectionProps extends React.ComponentProps<typeof EuiDescriptionList> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ import { NameReadOnly } from './fields/name/name';
import { TagsReadOnly } from './fields/tags/tags';
import { DescriptionReadOnly } from './fields/description/description';
import { assertUnreachable } from '../../../../../../../common/utility_types';
import { AuthorReadOnly } from './fields/author/author';
import { BuildingBlockReadOnly } from './fields/building_block/building_block';
import { InvestigationFieldsReadOnly } from './fields/investigation_fields/investigation_fields';
import { FalsePositivesReadOnly } from './fields/false_positives/false_positives';
import { LicenseReadOnly } from './fields/license/license';
import { MaxSignalsReadOnly } from './fields/max_signals/max_signals';
import { NoteReadOnly } from './fields/note/note';
import { RuleScheduleReadOnly } from './fields/rule_schedule/rule_schedule';
import { ReferencesReadOnly } from './fields/references/references';
import { RiskScoreReadOnly } from './fields/risk_score/risk_score';
import { RuleNameOverrideReadOnly } from './fields/rule_name_override/rule_name_override';
import { SetupReadOnly } from './fields/setup/setup';
import { SeverityReadOnly } from './fields/severity/severity';
import { TimestampOverrideReadOnly } from './fields/timestamp_override/timestamp_override';
import { TimelineTemplateReadOnly } from './fields/timeline_template/timeline_template';

interface CommonRuleFieldReadOnlyProps {
fieldName: keyof DiffableCommonFields;
Expand All @@ -32,25 +47,28 @@ export function CommonRuleFieldReadOnly({
}: CommonRuleFieldReadOnlyProps) {
switch (fieldName) {
case 'author':
return null;
return <AuthorReadOnly author={finalDiffableRule.author} />;
case 'building_block':
return null;
return <BuildingBlockReadOnly />;
case 'description':
return <DescriptionReadOnly description={finalDiffableRule.description} />;
case 'exceptions_list':
/* Exceptions are not used in prebuilt rules */
return null;
case 'investigation_fields':
return null;
return (
<InvestigationFieldsReadOnly investigationFields={finalDiffableRule.investigation_fields} />
);
case 'false_positives':
return null;
return <FalsePositivesReadOnly falsePositives={finalDiffableRule.false_positives} />;
case 'license':
return null;
return <LicenseReadOnly license={finalDiffableRule.license} />;
case 'max_signals':
return null;
return <MaxSignalsReadOnly maxSignals={finalDiffableRule.max_signals} />;
case 'name':
return <NameReadOnly name={finalDiffableRule.name} />;
case 'note':
return null;
return <NoteReadOnly note={finalDiffableRule.note} />;
case 'related_integrations':
return (
<RelatedIntegrationsReadOnly relatedIntegrations={finalDiffableRule.related_integrations} />
Expand All @@ -60,30 +78,32 @@ export function CommonRuleFieldReadOnly({
case 'risk_score_mapping':
return <RiskScoreMappingReadOnly riskScoreMapping={finalDiffableRule.risk_score_mapping} />;
case 'rule_schedule':
return null;
return <RuleScheduleReadOnly ruleSchedule={finalDiffableRule.rule_schedule} />;
case 'severity_mapping':
return <SeverityMappingReadOnly severityMapping={finalDiffableRule.severity_mapping} />;
case 'tags':
return <TagsReadOnly tags={finalDiffableRule.tags} />;
case 'threat':
return <ThreatReadOnly threat={finalDiffableRule.threat} />;
case 'references':
return null;
return <ReferencesReadOnly references={finalDiffableRule.references} />;
case 'risk_score':
return null;
return <RiskScoreReadOnly riskScore={finalDiffableRule.risk_score} />;
case 'rule_id':
/* Rule ID is not displayed in the UI */
return null;
case 'rule_name_override':
return null;
return <RuleNameOverrideReadOnly ruleNameOverride={finalDiffableRule.rule_name_override} />;
case 'setup':
return null;
return <SetupReadOnly setup={finalDiffableRule.setup} />;
case 'severity':
return null;
return <SeverityReadOnly severity={finalDiffableRule.severity} />;
case 'timestamp_override':
return null;
return <TimestampOverrideReadOnly timestampOverride={finalDiffableRule.timestamp_override} />;
case 'timeline_template':
return null;
return <TimelineTemplateReadOnly timelineTemplate={finalDiffableRule.timeline_template} />;
case 'version':
/* Version is not displayed in the UI */
return null;
default:
return assertUnreachable(fieldName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import React from 'react';
import type { DiffableCustomQueryFields } from '../../../../../../../common/api/detection_engine';
import { DataSourceReadOnly } from './fields/data_source/data_source';
import { KqlQueryReadOnly } from './fields/kql_query';
import { assertUnreachable } from '../../../../../../../common/utility_types';
import { TypeReadOnly } from './fields/type/type';
import { AlertSuppressionReadOnly } from './fields/alert_suppression/alert_suppression';

interface CustomQueryRuleFieldReadOnlyProps {
fieldName: keyof DiffableCustomQueryFields;
Expand All @@ -20,6 +23,13 @@ export function CustomQueryRuleFieldReadOnly({
finalDiffableRule,
}: CustomQueryRuleFieldReadOnlyProps) {
switch (fieldName) {
case 'alert_suppression':
return (
<AlertSuppressionReadOnly
alertSuppression={finalDiffableRule.alert_suppression}
ruleType={finalDiffableRule.type}
/>
);
case 'data_source':
return <DataSourceReadOnly dataSource={finalDiffableRule.data_source} />;
case 'kql_query':
Expand All @@ -30,7 +40,9 @@ export function CustomQueryRuleFieldReadOnly({
ruleType={finalDiffableRule.type}
/>
);
case 'type':
return <TypeReadOnly type={finalDiffableRule.type} />;
default:
return null; // Will replace with `assertUnreachable(fieldName)` once all fields are implemented
return assertUnreachable(fieldName);
}
}
Loading