Skip to content

Commit

Permalink
Add investigation_fields
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitaindik committed Oct 16, 2024
1 parent 96bee4f commit cfacec3
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ import React from 'react';
import { FieldFormWrapper } from './field_form_wrapper';
import type { UpgradeableCommonFields } from '../../../../model/prebuilt_rule_upgrade/fields';
import { DescriptionEdit, descriptionSchema } from './fields/description';
import { NameEdit, nameSchema } from './fields/name';
import { TagsEdit, tagsSchema } from './fields/tags';
import { ReferencesEdit, referencesSchema, referencesSerializer } from './fields/references';
import {
FalsePositivesEdit,
falsePositivesSchema,
falsePositivesSerializer,
falsePositivesDeserializer,
} from './fields/false_positives';
import {
InvestigationFieldsEdit,
investigationFieldsSchema,
investigationFieldsDeserializer,
investigationFieldsSerializer,
} from './fields/investigation_fields';
import { NameEdit, nameSchema } from './fields/name';
import { ReferencesEdit, referencesSchema, referencesSerializer } from './fields/references';
import { TagsEdit, tagsSchema } from './fields/tags';

interface CommonRuleFieldEditProps {
fieldName: UpgradeableCommonFields;
Expand All @@ -36,6 +42,15 @@ export function CommonRuleFieldEdit({ fieldName }: CommonRuleFieldEditProps) {
deserializer={falsePositivesDeserializer}
/>
);
case 'investigation_fields':
return (
<FieldFormWrapper
component={InvestigationFieldsEdit}
fieldFormSchema={investigationFieldsSchema}
serializer={investigationFieldsSerializer}
deserializer={investigationFieldsDeserializer}
/>
);
case 'name':
return <FieldFormWrapper component={NameEdit} fieldFormSchema={nameSchema} />;
case 'references':
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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 React from 'react';
import type { FormSchema, FormData } from '../../../../../../../shared_imports';
import { UseField } from '../../../../../../../shared_imports';
import { schema } from '../../../../../../rule_creation_ui/components/step_about_rule/schema';
import type {
DiffableRule,
InvestigationFields,
RuleFalsePositiveArray,
} from '../../../../../../../../common/api/detection_engine';
import { MultiSelectFieldsAutocomplete } from '../../../../../../rule_creation_ui/components/multi_select_fields';
import { useAllEsqlRuleFields } from '../../../../../../rule_creation_ui/hooks';
import { useDefaultIndexPattern } from '../../../use_default_index_pattern';
import { useRuleIndexPattern } from '../../../../../../rule_creation_ui/pages/form';
import { getUseRuleIndexPatternParameters } from '../utils';

export const investigationFieldsSchema = {
investigationFields: schema.investigationFields,
} as FormSchema<{
investigationFields: RuleFalsePositiveArray;
}>;

interface InvestigationFieldsEditProps {
finalDiffableRule: DiffableRule;
}

export function InvestigationFieldsEdit({
finalDiffableRule,
}: InvestigationFieldsEditProps): JSX.Element {
const { type } = finalDiffableRule;

const defaultIndexPattern = useDefaultIndexPattern();
const indexPatternParameters = getUseRuleIndexPatternParameters(
finalDiffableRule,
defaultIndexPattern
);
const { indexPattern, isIndexPatternLoading } = useRuleIndexPattern(indexPatternParameters);

const { fields: investigationFields, isLoading: isInvestigationFieldsLoading } =
useAllEsqlRuleFields({
esqlQuery: type === 'esql' ? finalDiffableRule.esql_query.query : undefined,
indexPatternsFields: indexPattern.fields,
});

return (
<UseField
path="investigationFields"
component={MultiSelectFieldsAutocomplete}
componentProps={{
browserFields: investigationFields,
isDisabled: isIndexPatternLoading || isInvestigationFieldsLoading,
fullWidth: true,
}}
/>
);
}

export function investigationFieldsDeserializer(defaultValue: FormData) {
/* Set initial form value with camelCase "investigationFields" key instead of "investigation_fields" */
return {
investigationFields: defaultValue?.field_names ?? [],
};
}

export function investigationFieldsSerializer(formData: FormData): {
investigation_fields: InvestigationFields | undefined;
} {
const hasInvestigationFields = formData.investigationFields.length > 0;

return {
investigation_fields: hasInvestigationFields
? {
field_names: formData.investigationFields,
}
: undefined,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import type { FieldValueQueryBar } from '../../../../../../rule_creation_ui/comp
import * as stepDefineRuleI18n from '../../../../../../rule_creation_ui/components/step_define_rule/translations';
import { useRuleIndexPattern } from '../../../../../../rule_creation_ui/pages/form';
import {
DataSourceType as DataSourceTypeSnakeCase,
KqlQueryLanguage,
KqlQueryType,
RuleQuery,
Expand All @@ -32,11 +31,11 @@ import type {
SavedKqlQuery,
} from '../../../../../../../../common/api/detection_engine';
import { useDefaultIndexPattern } from '../../../use_default_index_pattern';
import { DataSourceType } from '../../../../../../../detections/pages/detection_engine/rules/types';
import { isFilters } from '../../../helpers';
import type { SetRuleQuery } from '../../../../../../../detections/containers/detection_engine/rules/use_rule_from_timeline';
import { useRuleFromTimeline } from '../../../../../../../detections/containers/detection_engine/rules/use_rule_from_timeline';
import { useGetSavedQuery } from '../../../../../../../detections/pages/detection_engine/rules/use_get_saved_query';
import { getUseRuleIndexPatternParameters } from '../utils';

export const kqlQuerySchema = {
ruleType: schema.ruleType,
Expand Down Expand Up @@ -199,37 +198,6 @@ export function kqlQueryDeserializer(
return returnValue;
}

interface UseRuleIndexPatternParameters {
dataSourceType: DataSourceType;
index: string[];
dataViewId: string | undefined;
}

function getUseRuleIndexPatternParameters(
finalDiffableRule: DiffableRule,
defaultIndexPattern: string[]
): UseRuleIndexPatternParameters {
if (!('data_source' in finalDiffableRule) || !finalDiffableRule.data_source) {
return {
dataSourceType: DataSourceType.IndexPatterns,
index: defaultIndexPattern,
dataViewId: undefined,
};
}
if (finalDiffableRule.data_source.type === DataSourceTypeSnakeCase.data_view) {
return {
dataSourceType: DataSourceType.DataView,
index: [],
dataViewId: finalDiffableRule.data_source.data_view_id,
};
}
return {
dataSourceType: DataSourceType.IndexPatterns,
index: finalDiffableRule.data_source.index_patterns,
dataViewId: undefined,
};
}

function getSavedQueryId(diffableRule: DiffableRule): string | undefined {
if (diffableRule.type === 'saved_query' && 'saved_query_id' in diffableRule.kql_query) {
return diffableRule.kql_query.saved_query_id;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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 { DataSourceType } from '../../../../../../detections/pages/detection_engine/rules/types';
import { DataSourceType as DataSourceTypeSnakeCase } from '../../../../../../../common/api/detection_engine';
import type { DiffableRule } from '../../../../../../../common/api/detection_engine';

interface UseRuleIndexPatternParameters {
dataSourceType: DataSourceType;
index: string[];
dataViewId: string | undefined;
}

export function getUseRuleIndexPatternParameters(
finalDiffableRule: DiffableRule,
defaultIndexPattern: string[]
): UseRuleIndexPatternParameters {
if (!('data_source' in finalDiffableRule) || !finalDiffableRule.data_source) {
return {
dataSourceType: DataSourceType.IndexPatterns,
index: defaultIndexPattern,
dataViewId: undefined,
};
}
if (finalDiffableRule.data_source.type === DataSourceTypeSnakeCase.data_view) {
return {
dataSourceType: DataSourceType.DataView,
index: [],
dataViewId: finalDiffableRule.data_source.data_view_id,
};
}
return {
dataSourceType: DataSourceType.IndexPatterns,
index: finalDiffableRule.data_source.index_patterns,
dataViewId: undefined,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ interface FalsePositivesReadOnlyProps {
}

export function FalsePositivesReadOnly({ falsePositives }: FalsePositivesReadOnlyProps) {
if (falsePositives.length === 0) {
return null;
}

return (
<EuiDescriptionList
listItems={[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ interface ReferencesReadOnlyProps {
}

export function ReferencesReadOnly({ references }: ReferencesReadOnlyProps) {
if (references.length === 0) {
return null;
}

return (
<EuiDescriptionList
listItems={[
Expand Down

0 comments on commit cfacec3

Please sign in to comment.