diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx
index ef08b6d03a7b7..0ff120ea110db 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx
@@ -5,56 +5,127 @@
* 2.0.
*/
-import React, { useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { i18n } from '@kbn/i18n';
import {
EuiFlexGroup,
EuiFlexItem,
EuiPopoverTitle,
EuiText,
- EuiSelectable,
+ EuiListGroupItem,
EuiSelectableOption,
+ EuiListGroup,
+ EuiHorizontalRule,
+ EuiSpacer,
} from '@elastic/eui';
import { Markdown } from '../../../../../../../../../src/plugins/kibana_react/public';
-import { GenericOperationDefinition, ParamEditorProps } from '../../index';
+import { GenericOperationDefinition } from '../../index';
import { IndexPattern } from '../../../../types';
import { tinymathFunctions } from '../util';
import { getPossibleFunctions } from './math_completion';
-import { FormulaIndexPatternColumn } from '../formula';
-
function FormulaHelp({
indexPattern,
operationDefinitionMap,
+ isFullscreen,
}: {
indexPattern: IndexPattern;
operationDefinitionMap: Record
;
+ isFullscreen: boolean;
}) {
const [selectedFunction, setSelectedFunction] = useState();
+ const scrollTargets = useRef>({});
+
+ useEffect(() => {
+ if (selectedFunction && scrollTargets.current[selectedFunction]) {
+ scrollTargets.current[selectedFunction].scrollIntoView();
+ }
+ }, [selectedFunction]);
const helpItems: Array = [];
- helpItems.push({ label: 'Math', isGroupLabel: true });
+ helpItems.push({
+ label: i18n.translate('xpack.lens.formulaDocumentation.mathSection', {
+ defaultMessage: 'Math',
+ }),
+ isGroupLabel: true,
+ description: (
+
+ {i18n.translate('xpack.lens.formulaDocumentation.mathSectionDescription', {
+ defaultMessage:
+ 'These functions will be executed for reach row of the resulting table using single values from the same row calculated using other functions.',
+ })}
+
+ ),
+ });
helpItems.push(
...getPossibleFunctions(indexPattern)
.filter((key) => key in tinymathFunctions)
+ .sort()
.map((key) => ({
label: `${key}`,
description: ,
- checked: selectedFunction === key ? ('on' as const) : undefined,
}))
);
- helpItems.push({ label: 'Elasticsearch', isGroupLabel: true });
+ helpItems.push({
+ label: i18n.translate('xpack.lens.formulaDocumentation.elasticsearchSection', {
+ defaultMessage: 'Elasticsearch',
+ }),
+ isGroupLabel: true,
+ description: (
+
+ {i18n.translate('xpack.lens.formulaDocumentation.elasticsearchSectionDescription', {
+ defaultMessage:
+ 'These functions will be executed on the raw documents for each row of the resulting table, aggregating all documents matching the break down dimensions into a single value.',
+ })}
+
+ ),
+ });
// Es aggs
helpItems.push(
...getPossibleFunctions(indexPattern)
- .filter((key) => key in operationDefinitionMap)
+ .filter(
+ (key) =>
+ key in operationDefinitionMap &&
+ operationDefinitionMap[key].documentation?.section === 'elasticsearch'
+ )
+ .sort()
.map((key) => ({
- label: `${key}: ${operationDefinitionMap[key].displayName}`,
- description: getHelpText(key, operationDefinitionMap),
+ label: key,
+ description: operationDefinitionMap[key].documentation?.description,
+ }))
+ );
+
+ helpItems.push({
+ label: i18n.translate('xpack.lens.formulaDocumentation.columnCalculationSection', {
+ defaultMessage: 'Column-wise calculation',
+ }),
+ isGroupLabel: true,
+ description: (
+
+ {i18n.translate('xpack.lens.formulaDocumentation.columnCalculationSectionDescription', {
+ defaultMessage:
+ 'These functions will be executed for reach row of the resulting table, using data from cells from other rows as well as the current value.',
+ })}
+
+ ),
+ });
+
+ // Calculations aggs
+ helpItems.push(
+ ...getPossibleFunctions(indexPattern)
+ .filter(
+ (key) =>
+ key in operationDefinitionMap &&
+ operationDefinitionMap[key].documentation?.section === 'calculation'
+ )
+ .sort()
+ .map((key) => ({
+ label: key,
+ description: operationDefinitionMap[key].documentation?.description,
checked:
selectedFunction === `${key}: ${operationDefinitionMap[key].displayName}`
? ('on' as const)
@@ -65,42 +136,49 @@ function FormulaHelp({
return (
<>
- Formula reference
+ {i18n.translate('xpack.lens.formulaDocumentation.header', {
+ defaultMessage: 'Formula reference',
+ })}
- {
- const chosenType = newOptions.find(({ checked }) => checked === 'on')!;
- if (!chosenType) {
- setSelectedFunction(undefined);
+
+ {helpItems.map((helpItem) => {
+ if (helpItem.isGroupLabel) {
+ return (
+ {
+ setSelectedFunction(helpItem.label);
+ }}
+ />
+ );
} else {
- setSelectedFunction(chosenType.label);
+ return (
+ {
+ setSelectedFunction(helpItem.label);
+ }}
+ />
+ );
}
- }}
- >
- {(list, search) => (
- <>
- {search}
- {list}
- >
- )}
-
+ })}
+
- {selectedFunction ? (
- helpItems.find(({ label }) => label === selectedFunction)?.description
- ) : (
-
- )}
+ description:
+ 'Text is in markdown. Do not translate function names or field names like sum(bytes)',
+ })}
+ />
+
+ {helpItems.map((item, index) => {
+ return (
+ {
+ if (el) {
+ scrollTargets.current[item.label] = el;
+ }
+ }}
+ >
+ {item.isGroupLabel ? (
+
+ {item.label}
+ {item.description}
+
+
+ ) : (
+
+ {item.description}
+ {helpItems.length - 1 !== index && }
+
+ )}
+
+ );
+ })}
@@ -148,37 +249,3 @@ Use the symbols +, -, /, and * to perform basic math.
}
export const MemoizedFormulaHelp = React.memo(FormulaHelp);
-
-// TODO: i18n this whole thing, or move examples into the operation definitions with i18n
-function getHelpText(
- type: string,
- operationDefinitionMap: ParamEditorProps['operationDefinitionMap']
-) {
- const definition = operationDefinitionMap[type];
-
- if (type === 'count') {
- return (
-
- Example: count()
-
- );
- }
-
- return (
-
- {definition.input === 'field' ? Example: {type}(bytes)
: null}
- {definition.input === 'fullReference' && !('operationParams' in definition) ? (
- Example: {type}(sum(bytes))
- ) : null}
-
- {'operationParams' in definition && definition.operationParams ? (
-
-
- Example: {type}(sum(bytes),{' '}
- {definition.operationParams.map((p) => `${p.name}=5`).join(', ')})
-
-
- ) : null}
-
- );
-}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
index 5d9a8647eb7ab..2f68522b1ef51 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts
@@ -85,9 +85,20 @@ export const tinymathFunctions: Record<
{ name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
],
help: `
+### add(summand1: number, summand2: number) \`+\`
+Adds up two numbers.
Also works with + symbol
-Example: ${'`count() + sum(bytes)`'}
-Example: ${'`add(count(), 5)`'}
+
+Example: Calculate the sum of two fields
+\`\`\`
+sum(price) + sum(tax)
+\`\`\`
+
+Example: Offset count by a static value
+
+\`\`\`
+add(count(), 5)
+\`\`\`
`,
},
subtract: {
@@ -96,8 +107,14 @@ Example: ${'`add(count(), 5)`'}
{ name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
],
help: `
+### subtract(minuend: number, subtrahend: number) \`-\`
+Subtracts the first number from the second number.
Also works with ${'`-`'} symbol
-Example: ${'`subtract(sum(bytes), avg(bytes))`'}
+
+Example: Calculate the range of a field
+\`\`\`
+subtract(max(bytes), min(bytes))
+\`\`\`
`,
},
multiply: {
@@ -106,8 +123,19 @@ Example: ${'`subtract(sum(bytes), avg(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
],
help: `
-Also works with ${'`*`'} symbol
-Example: ${'`multiply(sum(bytes), 2)`'}
+### multiply(factor1: number, factor2: number) \`*\`
+Multiplies two numbers.
+Also works with ${'`*`'} symbol.
+
+Example: Calculate price after current tax rate
+\`\`\`
+sum(bytes) * last_value(tax_rate)
+\`\`\`
+
+Example: Calculate price after constant tax rate
+\`\`\`
+multiply(sum(price), 1.2)
+\`\`\`
`,
},
divide: {
@@ -116,8 +144,14 @@ Example: ${'`multiply(sum(bytes), 2)`'}
{ name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }) },
],
help: `
+### divide(dividend: number, divisor: number) \`/\`
+Divides the first number by the second number.
Also works with ${'`/`'} symbol
-Example: ${'`ceil(sum(bytes))`'}
+
+Example: Calculate profit margin
+\`\`\`
+sum(profit) / sum(revenue)
+\`\`\`
`,
},
abs: {
@@ -125,8 +159,10 @@ Example: ${'`ceil(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
-Absolute value
-Example: ${'`abs(sum(bytes))`'}
+### abs(value: number)
+Calculates absolute value. A negative value is multiplied by -1, a positive value stays the same.
+
+Example: Calculate average distance to sea level ${'`abs(average(altitude))`'}
`,
},
cbrt: {
@@ -134,8 +170,13 @@ Example: ${'`abs(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
-Cube root of value
-Example: ${'`cbrt(sum(bytes))`'}
+### cbrt(value: number)
+Cube root of value.
+
+Example: Calculate side length from volume
+\`\`\`
+cbrt(last_value(volume))
+\`\`\`
`,
},
ceil: {
@@ -143,8 +184,13 @@ Example: ${'`cbrt(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
-Ceiling of value, rounds up
-Example: ${'`ceil(sum(bytes))`'}
+### ceil(value: number)
+Ceiling of value, rounds up.
+
+Example: Round up price to the next dollar
+\`\`\`
+ceil(sum(price))
+\`\`\`
`,
},
clamp: {
@@ -154,17 +200,31 @@ Example: ${'`ceil(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.max', { defaultMessage: 'max' }) },
],
help: `
-Limits the value from a minimum to maximum
-Example: ${'`ceil(sum(bytes))`'}
- `,
+### clamp(value: number, minimum: number, maximum: number)
+Limits the value from a minimum to maximum.
+
+Example: Make sure to catch outliers
+\`\`\`
+clamp(
+ average(bytes),
+ percentile(bytes, percentile=5),
+ percentile(bytes, percentile=95)
+)
+\`\`\`
+`,
},
cube: {
positionalArguments: [
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
-Limits the value from a minimum to maximum
-Example: ${'`ceil(sum(bytes))`'}
+### cube(value: number)
+Calculates the cube of a number.
+
+Example: Calculate volume from side length
+\`\`\`
+cube(last_value(length))
+\`\`\`
`,
},
exp: {
@@ -172,8 +232,13 @@ Example: ${'`ceil(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
+### exp(value: number)
Raises e to the nth power.
-Example: ${'`exp(sum(bytes))`'}
+
+Example: Calculate the natural expontential function
+\`\`\`
+exp(last_value(duration))
+\`\`\`
`,
},
fix: {
@@ -181,8 +246,13 @@ Example: ${'`exp(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
+### fix(value: number)
For positive values, takes the floor. For negative values, takes the ceiling.
-Example: ${'`fix(sum(bytes))`'}
+
+Example: Rounding towards zero
+\`\`\`
+fix(sum(profit))
+\`\`\`
`,
},
floor: {
@@ -190,8 +260,13 @@ Example: ${'`fix(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
+### floor(value: number)
Round down to nearest integer value
-Example: ${'`floor(sum(bytes))`'}
+
+Example: Round down a price
+\`\`\`
+floor(sum(price))
+\`\`\`
`,
},
log: {
@@ -203,9 +278,13 @@ Example: ${'`floor(sum(bytes))`'}
},
],
help: `
+### log(value: number, base?: number)
Logarithm with optional base. The natural base e is used as default.
-Example: ${'`log(sum(bytes))`'}
-Example: ${'`log(sum(bytes), 2)`'}
+
+Example: Calculate number of bits required to store values
+\`\`\`
+log(max(price), 2)
+\`\`\`
`,
},
// TODO: check if this is valid for Tinymath
@@ -227,20 +306,30 @@ Example: ${'`log(sum(bytes), 2)`'}
},
],
help: `
+### mod(value: number)
Remainder after dividing the function by a number
-Example: ${'`mod(sum(bytes), 2)`'}
+
+Example: Calculate last three digits of a value
+\`\`\`
+mod(sum(price), 1000)
+\`\`\`
`,
},
pow: {
positionalArguments: [
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
{
- name: i18n.translate('xpack.lens.formula.base', { defaultMessage: 'base' }),
+ name: i18n.translate('xpack.lens.\\formula.base', { defaultMessage: 'base' }),
},
],
help: `
+### pow(value: number, power: number)
Raises the value to a certain power. The second argument is required
-Example: ${'`pow(sum(bytes), 3)`'}
+
+Example: Calculate volume based on side length
+\`\`\`
+pow(last_value(length), 3)
+\`\`\`
`,
},
round: {
@@ -252,9 +341,13 @@ Example: ${'`pow(sum(bytes), 3)`'}
},
],
help: `
+### round(value: number, digits: number = 0)
Rounds to a specific number of decimal places, default of 0
-Example: ${'`round(sum(bytes))`'}
-Example: ${'`round(sum(bytes), 2)`'}
+
+Example: Round to the cent
+\`\`\`
+round(sum(price), 2)
+\`\`\`
`,
},
sqrt: {
@@ -262,8 +355,13 @@ Example: ${'`round(sum(bytes), 2)`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
+### sqrt(value: number)
Square root of a positive value only
-Example: ${'`sqrt(sum(bytes))`'}
+
+Example: Calculate side length based on area
+\`\`\`
+sqrt(last_value(area))
+\`\`\`
`,
},
square: {
@@ -271,8 +369,13 @@ Example: ${'`sqrt(sum(bytes))`'}
{ name: i18n.translate('xpack.lens.formula.expression', { defaultMessage: 'expression' }) },
],
help: `
+### square(value: number)
Raise the value to the 2nd power
-Example: ${'`square(sum(bytes))`'}
+
+Example: Calculate area based on side length
+\`\`\`
+square(last_value(length))
+\`\`\`
`,
},
};
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
index 27982243f8c2b..510a59b109d10 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts
@@ -262,6 +262,10 @@ interface BaseOperationDefinitionProps {
* Operations can be used as middleware for other operations, hence not shown in the panel UI
*/
hidden?: boolean;
+ documentation?: {
+ description: JSX.Element;
+ section: 'elasticsearch' | 'calculation';
+ };
}
interface BaseBuildColumnArgs {
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
index 4632d262c441d..5ec17b6ac3e6f 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx
@@ -21,6 +21,7 @@ import {
getSafeName,
getFilter,
} from './helpers';
+import { Markdown } from '../../../../../../../src/plugins/kibana_react/public';
function ofName(name: string) {
return i18n.translate('xpack.lens.indexPattern.lastValueOf', {
@@ -265,4 +266,25 @@ export const lastValueOperation: OperationDefinition
);
},
+ documentation: {
+ section: 'elasticsearch',
+ description: (
+
+ ),
+ },
};
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
index 725ef93203a43..2c5bda1d2870d 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx
@@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
+import React from 'react';
import { buildExpressionFunction } from '../../../../../../../src/plugins/expressions/public';
import { OperationDefinition } from './index';
import {
@@ -23,6 +24,7 @@ import {
adjustTimeScaleLabelSuffix,
adjustTimeScaleOnOtherColumnChange,
} from '../time_scale_utils';
+import { Markdown } from '../../../../../../../src/plugins/kibana_react/public';
type MetricColumn = FormattedIndexPatternColumn &
FieldBasedIndexPatternColumn & {
@@ -125,6 +127,33 @@ function buildMetricOperation>({
getErrorMessage: (layer, columnId, indexPattern) =>
getInvalidFieldMessage(layer.columns[columnId] as FieldBasedIndexPatternColumn, indexPattern),
filterable: true,
+ documentation: {
+ section: 'elasticsearch',
+ description: (
+
+ ),
+ },
} as OperationDefinition;
}
diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
index 705a1f7172fff..c98832c8516cb 100644
--- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
+++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx
@@ -20,6 +20,7 @@ import {
getFilter,
} from './helpers';
import { FieldBasedIndexPatternColumn } from './column_types';
+import { Markdown } from '../../../../../../../src/plugins/kibana_react/public';
export interface PercentileIndexPatternColumn extends FieldBasedIndexPatternColumn {
operationType: 'percentile';
@@ -193,4 +194,23 @@ export const percentileOperation: OperationDefinition
);
},
+ documentation: {
+ section: 'elasticsearch',
+ description: (
+
+ ),
+ },
};
diff --git a/x-pack/plugins/lists/common/shared_exports.ts b/x-pack/plugins/lists/common/shared_exports.ts
index bc9d0ca8d7b94..f00afb7ac810d 100644
--- a/x-pack/plugins/lists/common/shared_exports.ts
+++ b/x-pack/plugins/lists/common/shared_exports.ts
@@ -5,45 +5,6 @@
* 2.0.
*/
-// TODO: We should remove these and instead directly import them in the security_solution project. This is to get my PR across the line without too many conflicts.
-export {
- CommentsArray,
- Comment,
- CreateComment,
- CreateCommentsArray,
- Entry,
- EntryExists,
- EntryMatch,
- EntryMatchAny,
- EntryMatchWildcard,
- EntryNested,
- EntryList,
- EntriesArray,
- NamespaceType,
- NestedEntriesArray,
- ListOperator as Operator,
- ListOperatorEnum as OperatorEnum,
- ListOperatorTypeEnum as OperatorTypeEnum,
- listOperator as operator,
- ExceptionListTypeEnum,
- ExceptionListType,
- comment,
- exceptionListType,
- entry,
- entriesNested,
- nestedEntryItem,
- entriesMatch,
- entriesMatchAny,
- entriesMatchWildcard,
- entriesExists,
- entriesList,
- namespaceType,
- osType,
- osTypeArray,
- OsTypeArray,
- Type,
-} from '@kbn/securitysolution-io-ts-list-types';
-
export {
ListSchema,
ExceptionListSchema,
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match.tsx b/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match.tsx
index a0994871808d1..c1776280842c6 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match.tsx
@@ -14,8 +14,8 @@ import {
EuiSuperSelect,
} from '@elastic/eui';
import { uniq } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
-import { OperatorTypeEnum } from '../../../../common';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match_any.tsx b/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match_any.tsx
index 08958f6d99aab..82347f6212442 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match_any.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/field_value_match_any.tsx
@@ -8,8 +8,8 @@
import React, { useCallback, useMemo, useState } from 'react';
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
import { uniq } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
-import { OperatorTypeEnum } from '../../../../common';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/helpers.ts b/x-pack/plugins/lists/public/exceptions/components/autocomplete/helpers.ts
index 4f25bec3b38dc..b982193d1d349 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/helpers.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/helpers.ts
@@ -7,8 +7,9 @@
import dateMath from '@elastic/datemath';
import { EuiComboBoxOptionOption } from '@elastic/eui';
+import type { Type } from '@kbn/securitysolution-io-ts-list-types';
-import { ListSchema, Type } from '../../../../common';
+import type { ListSchema } from '../../../../common';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import {
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.test.ts b/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
index 4e3fb2179d786..0335ffa55d2a2 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
@@ -6,10 +6,10 @@
*/
import { act, renderHook } from '@testing-library/react-hooks';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { stubIndexPatternWithFields } from '../../../../../../../../src/plugins/data/common/index_patterns/index_pattern.stub';
import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
-import { OperatorTypeEnum } from '../../../../../common';
import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/mocks';
import {
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.ts b/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.ts
index 6c6198ac55a0f..674bb5e5537d9 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/hooks/use_field_value_autocomplete.ts
@@ -7,10 +7,10 @@
import { useEffect, useRef, useState } from 'react';
import { debounce } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { AutocompleteStart } from '../../../../../../../../src/plugins/data/public';
import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common';
-import { OperatorTypeEnum } from '../../../../../common';
interface FuncArgs {
fieldSelected: IFieldType | undefined;
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/operators.ts b/x-pack/plugins/lists/public/exceptions/components/autocomplete/operators.ts
index 551dfcb61e3ad..83a424d72ec5f 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/operators.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/operators.ts
@@ -6,8 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
-
-import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
+import {
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
import { OperatorOption } from './types';
diff --git a/x-pack/plugins/lists/public/exceptions/components/autocomplete/types.ts b/x-pack/plugins/lists/public/exceptions/components/autocomplete/types.ts
index 8ea3e8d927d68..76d5b7758007b 100644
--- a/x-pack/plugins/lists/public/exceptions/components/autocomplete/types.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/autocomplete/types.ts
@@ -6,8 +6,10 @@
*/
import { EuiComboBoxOptionOption } from '@elastic/eui';
-
-import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
+import type {
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
export interface GetGenericComboBoxPropsReturn {
comboOptions: EuiComboBoxOptionOption[];
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx
index 5b3730a6deb93..dd67381c30934 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.stories.tsx
@@ -9,8 +9,11 @@ import { Story } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React from 'react';
import { HttpStart } from 'kibana/public';
+import {
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
-import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
import { fields } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common';
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx
index 0ece28d409bd5..09863660e98af 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx
@@ -8,7 +8,11 @@
import React, { useCallback, useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import styled from 'styled-components';
-import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
+import {
+ ExceptionListType,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+ OsTypeArray,
+} from '@kbn/securitysolution-io-ts-list-types';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
@@ -21,7 +25,7 @@ import { AutocompleteFieldExistsComponent } from '../autocomplete/field_value_ex
import { AutocompleteFieldMatchComponent } from '../autocomplete/field_value_match';
import { AutocompleteFieldMatchAnyComponent } from '../autocomplete/field_value_match_any';
import { AutocompleteFieldListsComponent } from '../autocomplete/field_value_lists';
-import { ExceptionListType, ListSchema, OperatorTypeEnum } from '../../../../common';
+import { ListSchema } from '../../../../common';
import { getEmptyValue } from '../../../common/empty_value';
import {
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx
index 94c3bff8f4cf9..e10cd2934328f 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/exception_item_renderer.tsx
@@ -10,9 +10,8 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { HttpStart } from 'kibana/public';
import { AutocompleteStart } from 'src/plugins/data/public';
-import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
+import { ExceptionListType, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
-import { ExceptionListType } from '../../../../common';
import { IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { BuilderEntry, ExceptionsBuilderExceptionItem, FormattedBuilderEntry } from './types';
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx
index 4ec152e155e39..f771969a92025 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx
@@ -10,19 +10,21 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { HttpStart } from 'kibana/public';
import { addIdToItem } from '@kbn/securitysolution-utils';
-import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
-
-import { AutocompleteStart, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
- CreateExceptionListItemSchema,
- ExceptionListItemSchema,
ExceptionListType,
NamespaceType,
- OperatorEnum,
- OperatorTypeEnum,
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+ OsTypeArray,
entriesNested,
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import {
+ CreateExceptionListItemSchema,
+ ExceptionListItemSchema,
exceptionListItemSchema,
} from '../../../../common';
+import { AutocompleteStart, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import { AndOrBadge } from '../and_or_badge';
import { CreateExceptionListItemBuilderSchema, ExceptionsBuilderExceptionItem } from './types';
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts
index 1e74193299e56..dbfeaa4a258ca 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts
@@ -5,6 +5,18 @@
* 2.0.
*/
+import {
+ EntryExists,
+ EntryList,
+ EntryMatch,
+ EntryMatchAny,
+ EntryNested,
+ ExceptionListType,
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../../../../common';
import { ENTRIES_WITH_IDS } from '../../../../common/constants.mock';
import { getEntryExistsMock } from '../../../../common/schemas/types/entry_exists.mock';
import { getExceptionListItemSchemaMock } from '../../../../common/schemas/response/exception_list_item_schema.mock';
@@ -23,25 +35,23 @@ import {
doesNotExistOperator,
existsOperator,
isInListOperator,
+ isNotInListOperator,
isNotOneOfOperator,
isNotOperator,
isOneOfOperator,
isOperator,
} from '../autocomplete/operators';
-import {
- EntryExists,
- EntryList,
- EntryMatch,
- EntryMatchAny,
- EntryNested,
- ExceptionListType,
- OperatorEnum,
- OperatorTypeEnum,
-} from '../../../../common';
import { OperatorOption } from '../autocomplete/types';
+import { getEntryListMock } from '../../../../common/schemas/types/entry_list.mock';
-import { BuilderEntry, ExceptionsBuilderExceptionItem, FormattedBuilderEntry } from './types';
import {
+ BuilderEntry,
+ EmptyEntry,
+ ExceptionsBuilderExceptionItem,
+ FormattedBuilderEntry,
+} from './types';
+import {
+ filterExceptionItems,
getCorrespondingKeywordField,
getEntryFromOperator,
getEntryOnFieldChange,
@@ -49,10 +59,14 @@ import {
getEntryOnMatchAnyChange,
getEntryOnMatchChange,
getEntryOnOperatorChange,
+ getEntryValue,
+ getExceptionOperatorSelect,
getFilteredIndexPatterns,
getFormattedBuilderEntries,
getFormattedBuilderEntry,
+ getNewExceptionItem,
getOperatorOptions,
+ getOperatorType,
getUpdatedEntriesOnDelete,
isEntryNested,
} from './helpers';
@@ -1426,4 +1440,298 @@ describe('Exception builder helpers', () => {
expect(output).toEqual(undefined);
});
});
+
+ describe('#getOperatorType', () => {
+ test('returns operator type "match" if entry.type is "match"', () => {
+ const payload = getEntryMatchMock();
+ const operatorType = getOperatorType(payload);
+
+ expect(operatorType).toEqual(OperatorTypeEnum.MATCH);
+ });
+
+ test('returns operator type "match_any" if entry.type is "match_any"', () => {
+ const payload = getEntryMatchAnyMock();
+ const operatorType = getOperatorType(payload);
+
+ expect(operatorType).toEqual(OperatorTypeEnum.MATCH_ANY);
+ });
+
+ test('returns operator type "list" if entry.type is "list"', () => {
+ const payload = getEntryListMock();
+ const operatorType = getOperatorType(payload);
+
+ expect(operatorType).toEqual(OperatorTypeEnum.LIST);
+ });
+
+ test('returns operator type "exists" if entry.type is "exists"', () => {
+ const payload = getEntryExistsMock();
+ const operatorType = getOperatorType(payload);
+
+ expect(operatorType).toEqual(OperatorTypeEnum.EXISTS);
+ });
+ });
+
+ describe('#getExceptionOperatorSelect', () => {
+ test('it returns "isOperator" when "operator" is "included" and operator type is "match"', () => {
+ const payload = getEntryMatchMock();
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isOperator);
+ });
+
+ test('it returns "isNotOperator" when "operator" is "excluded" and operator type is "match"', () => {
+ const payload = getEntryMatchMock();
+ payload.operator = 'excluded';
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isNotOperator);
+ });
+
+ test('it returns "isOneOfOperator" when "operator" is "included" and operator type is "match_any"', () => {
+ const payload = getEntryMatchAnyMock();
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isOneOfOperator);
+ });
+
+ test('it returns "isNotOneOfOperator" when "operator" is "excluded" and operator type is "match_any"', () => {
+ const payload = getEntryMatchAnyMock();
+ payload.operator = 'excluded';
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isNotOneOfOperator);
+ });
+
+ test('it returns "existsOperator" when "operator" is "included" and no operator type is provided', () => {
+ const payload = getEntryExistsMock();
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(existsOperator);
+ });
+
+ test('it returns "doesNotExistsOperator" when "operator" is "excluded" and no operator type is provided', () => {
+ const payload = getEntryExistsMock();
+ payload.operator = 'excluded';
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(doesNotExistOperator);
+ });
+
+ test('it returns "isInList" when "operator" is "included" and operator type is "list"', () => {
+ const payload = getEntryListMock();
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isInListOperator);
+ });
+
+ test('it returns "isNotInList" when "operator" is "excluded" and operator type is "list"', () => {
+ const payload = getEntryListMock();
+ payload.operator = 'excluded';
+ const result = getExceptionOperatorSelect(payload);
+
+ expect(result).toEqual(isNotInListOperator);
+ });
+ });
+
+ describe('#filterExceptionItems', () => {
+ // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes
+ // for context around the temporary `id`
+ test('it correctly validates entries that include a temporary `id`', () => {
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ { ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }]);
+ });
+
+ test('it removes entry items with "value" of "undefined"', () => {
+ const { entries, ...rest } = getExceptionListItemSchemaMock();
+ const mockEmptyException: EmptyEntry = {
+ field: 'host.name',
+ id: '123',
+ operator: OperatorEnum.INCLUDED,
+ type: OperatorTypeEnum.MATCH,
+ value: undefined,
+ };
+ const exceptions = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(exceptions).toEqual([getExceptionListItemSchemaMock()]);
+ });
+
+ test('it removes "match" entry items with "value" of empty string', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EmptyEntry = {
+ field: 'host.name',
+ id: '123',
+ operator: OperatorEnum.INCLUDED,
+ type: OperatorTypeEnum.MATCH,
+ value: '',
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
+ });
+
+ test('it removes "match" entry items with "field" of empty string', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EmptyEntry = {
+ field: '',
+ id: '123',
+ operator: OperatorEnum.INCLUDED,
+ type: OperatorTypeEnum.MATCH,
+ value: 'some value',
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
+ });
+
+ test('it removes "match_any" entry items with "field" of empty string', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EmptyEntry = {
+ field: '',
+ id: '123',
+ operator: OperatorEnum.INCLUDED,
+ type: OperatorTypeEnum.MATCH_ANY,
+ value: ['some value'],
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
+ });
+
+ test('it removes "nested" entry items with "field" of empty string', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EntryNested = {
+ entries: [getEntryMatchMock()],
+ field: '',
+ type: OperatorTypeEnum.NESTED,
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
+ });
+
+ test('it removes the "nested" entry entries with "value" of empty string', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EntryNested = {
+ entries: [getEntryMatchMock(), { ...getEntryMatchMock(), value: '' }],
+ field: 'host.name',
+ type: OperatorTypeEnum.NESTED,
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([
+ {
+ ...getExceptionListItemSchemaMock(),
+ entries: [
+ ...getExceptionListItemSchemaMock().entries,
+ { ...mockEmptyException, entries: [getEntryMatchMock()] },
+ ],
+ },
+ ]);
+ });
+
+ test('it removes the "nested" entry item if all its entries are invalid', () => {
+ const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
+ const mockEmptyException: EntryNested = {
+ entries: [{ ...getEntryMatchMock(), value: '' }],
+ field: 'host.name',
+ type: OperatorTypeEnum.NESTED,
+ };
+ const output: Array<
+ ExceptionListItemSchema | CreateExceptionListItemSchema
+ > = filterExceptionItems([
+ {
+ ...rest,
+ entries: [...entries, mockEmptyException],
+ },
+ ]);
+
+ expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
+ });
+
+ test('it removes `temporaryId` from items', () => {
+ const { meta, ...rest } = getNewExceptionItem({
+ listId: '123',
+ namespaceType: 'single',
+ ruleName: 'rule name',
+ });
+ const exceptions = filterExceptionItems([{ ...rest, meta }]);
+
+ expect(exceptions).toEqual([{ ...rest, entries: [], meta: undefined }]);
+ });
+ });
+
+ describe('#getEntryValue', () => {
+ it('returns "match" entry value', () => {
+ const payload = getEntryMatchMock();
+ const result = getEntryValue(payload);
+ const expected = 'some host name';
+ expect(result).toEqual(expected);
+ });
+
+ it('returns "match any" entry values', () => {
+ const payload = getEntryMatchAnyMock();
+ const result = getEntryValue(payload);
+ const expected = ['some host name'];
+ expect(result).toEqual(expected);
+ });
+
+ it('returns "exists" entry value', () => {
+ const payload = getEntryExistsMock();
+ const result = getEntryValue(payload);
+ const expected = undefined;
+ expect(result).toEqual(expected);
+ });
+
+ it('returns "list" entry value', () => {
+ const payload = getEntryListMock();
+ const result = getEntryValue(payload);
+ const expected = 'some-list-id';
+ expect(result).toEqual(expected);
+ });
+ });
});
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.ts b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.ts
index 18d607d6807fc..6cd9dec0dc7a1 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/helpers.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/helpers.ts
@@ -8,27 +8,29 @@
import uuid from 'uuid';
import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils';
import { validate } from '@kbn/securitysolution-io-ts-utils';
-import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
-
-import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
- CreateExceptionListItemSchema,
EntriesArray,
Entry,
EntryNested,
- ExceptionListItemSchema,
ExceptionListType,
- ListSchema,
NamespaceType,
- OperatorEnum,
- OperatorTypeEnum,
- createExceptionListItemSchema,
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+ OsTypeArray,
entriesList,
entriesNested,
entry,
- exceptionListItemSchema,
nestedEntryItem,
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import {
+ CreateExceptionListItemSchema,
+ ExceptionListItemSchema,
+ ListSchema,
+ createExceptionListItemSchema,
+ exceptionListItemSchema,
} from '../../../../common';
+import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
EXCEPTION_OPERATORS,
EXCEPTION_OPERATORS_SANS_LISTS,
@@ -96,7 +98,7 @@ export const filterExceptionItems = (
return [...acc, item];
} else if (createExceptionListItemSchema.is(item)) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- const { meta: _, ...rest } = item;
+ const { meta, ...rest } = item;
const itemSansMetaId: CreateExceptionListItemSchema = { ...rest, meta: undefined };
return [...acc, itemSansMetaId];
} else {
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts b/x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts
index 92df2fd3793de..0e8a5fadd3b1a 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/reducer.ts
@@ -5,7 +5,9 @@
* 2.0.
*/
-import { ExceptionListItemSchema, OperatorTypeEnum } from '../../../../common';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
+
+import { ExceptionListItemSchema } from '../../../../common';
import { ExceptionsBuilderExceptionItem } from './types';
import { getDefaultEmptyEntry } from './helpers';
diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/types.ts b/x-pack/plugins/lists/public/exceptions/components/builder/types.ts
index 800f1445217b9..5cf4238ab5e0c 100644
--- a/x-pack/plugins/lists/public/exceptions/components/builder/types.ts
+++ b/x-pack/plugins/lists/public/exceptions/components/builder/types.ts
@@ -5,20 +5,20 @@
* 2.0.
*/
-import { IFieldType } from '../../../../../../../src/plugins/data/common';
-import { OperatorOption } from '../autocomplete/types';
-import {
- CreateExceptionListItemSchema,
+import type {
Entry,
EntryExists,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryNested,
- ExceptionListItemSchema,
- OperatorEnum,
- OperatorTypeEnum,
-} from '../../../../common';
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import type { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../../../../common';
+import { IFieldType } from '../../../../../../../src/plugins/data/common';
+import { OperatorOption } from '../autocomplete/types';
export interface FormattedBuilderEntry {
id: string;
diff --git a/x-pack/plugins/lists/public/exceptions/transforms.ts b/x-pack/plugins/lists/public/exceptions/transforms.ts
index 50ce1b6e33a4b..564ba1a699f98 100644
--- a/x-pack/plugins/lists/public/exceptions/transforms.ts
+++ b/x-pack/plugins/lists/public/exceptions/transforms.ts
@@ -7,11 +7,10 @@
import { flow } from 'fp-ts/lib/function';
import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils';
+import type { EntriesArray, Entry } from '@kbn/securitysolution-io-ts-list-types';
import type {
CreateExceptionListItemSchema,
- EntriesArray,
- Entry,
ExceptionListItemSchema,
UpdateExceptionListItemSchema,
} from '../../common';
diff --git a/x-pack/plugins/lists/public/shared_exports.ts b/x-pack/plugins/lists/public/shared_exports.ts
index 2032a44a8fd33..6d14c6b541904 100644
--- a/x-pack/plugins/lists/public/shared_exports.ts
+++ b/x-pack/plugins/lists/public/shared_exports.ts
@@ -7,11 +7,8 @@
// Exports to be shared with plugins
export { withOptionalSignal } from './common/with_optional_signal';
-export { useIsMounted } from './common/hooks/use_is_mounted';
export { useAsync } from './common/hooks/use_async';
export { useApi } from './exceptions/hooks/use_api';
-export { usePersistExceptionItem } from './exceptions/hooks/persist_exception_item';
-export { usePersistExceptionList } from './exceptions/hooks/persist_exception_list';
export { useExceptionListItems } from './exceptions/hooks/use_exception_list_items';
export { useExceptionLists } from './exceptions/hooks/use_exception_lists';
export { useFindLists } from './lists/hooks/use_find_lists';
@@ -24,13 +21,18 @@ export { useReadListIndex } from './lists/hooks/use_read_list_index';
export { useCreateListIndex } from './lists/hooks/use_create_list_index';
export { useReadListPrivileges } from './lists/hooks/use_read_list_privileges';
export {
- addExceptionListItem,
- updateExceptionListItem,
+ getEntryValue,
+ getExceptionOperatorSelect,
+ getOperatorType,
+ getNewExceptionItem,
+ addIdToEntries,
+} from './exceptions/components/builder/helpers';
+export {
fetchExceptionListById,
addExceptionList,
addEndpointExceptionList,
} from './exceptions/api';
-export {
+export type {
ExceptionList,
ExceptionListFilter,
ExceptionListIdentifiers,
diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.ts
index 79fd264808138..e2c3ee88f6a65 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.ts
+++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
-import { exceptionListType, namespaceType } from '../../../shared_imports';
+import { exceptionListType, namespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { NonEmptyString } from './non_empty_string';
diff --git a/x-pack/plugins/security_solution/common/detection_engine/utils.test.ts b/x-pack/plugins/security_solution/common/detection_engine/utils.test.ts
index c477036a07d85..1e0f7e087a5b3 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/utils.test.ts
+++ b/x-pack/plugins/security_solution/common/detection_engine/utils.test.ts
@@ -13,7 +13,8 @@ import {
normalizeMachineLearningJobIds,
normalizeThresholdField,
} from './utils';
-import { EntriesArray } from '../shared_imports';
+
+import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types';
describe('#hasLargeValueList', () => {
test('it returns false if empty array', () => {
diff --git a/x-pack/plugins/security_solution/common/detection_engine/utils.ts b/x-pack/plugins/security_solution/common/detection_engine/utils.ts
index a8e0ffcccef82..611d23fd1ce22 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/utils.ts
+++ b/x-pack/plugins/security_solution/common/detection_engine/utils.ts
@@ -7,11 +7,10 @@
import { isEmpty } from 'lodash';
-import {
- CreateExceptionListItemSchema,
- EntriesArray,
- ExceptionListItemSchema,
-} from '../shared_imports';
+import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types';
+
+import { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../shared_imports';
+
import { Type, JobStatus, Threshold, ThresholdNormalized } from './schemas/common/schemas';
export const hasLargeValueItem = (
diff --git a/x-pack/plugins/security_solution/common/shared_imports.ts b/x-pack/plugins/security_solution/common/shared_imports.ts
index e987775a8e768..a6bad0347e641 100644
--- a/x-pack/plugins/security_solution/common/shared_imports.ts
+++ b/x-pack/plugins/security_solution/common/shared_imports.ts
@@ -7,44 +7,14 @@
export {
ListSchema,
- CommentsArray,
- CreateCommentsArray,
- Comment,
- CreateComment,
ExceptionListSchema,
ExceptionListItemSchema,
CreateExceptionListSchema,
CreateExceptionListItemSchema,
UpdateExceptionListItemSchema,
- Entry,
- EntryExists,
- EntryMatch,
- EntryMatchAny,
- EntryMatchWildcard,
- EntryNested,
- EntryList,
- EntriesArray,
- NamespaceType,
- Operator,
- OperatorEnum,
- OperatorTypeEnum,
- ExceptionListTypeEnum,
exceptionListItemSchema,
- exceptionListType,
- comment,
createExceptionListItemSchema,
listSchema,
- entry,
- entriesNested,
- nestedEntryItem,
- entriesMatch,
- entriesMatchAny,
- entriesMatchWildcard,
- entriesExists,
- entriesList,
- namespaceType,
- ExceptionListType,
- Type,
ENDPOINT_LIST_ID,
ENDPOINT_TRUSTED_APPS_LIST_ID,
EXCEPTION_LIST_URL,
@@ -52,8 +22,5 @@ export {
ENDPOINT_EVENT_FILTERS_LIST_ID,
ENDPOINT_EVENT_FILTERS_LIST_NAME,
ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION,
- osType,
- osTypeArray,
- OsTypeArray,
buildExceptionFilter,
} from '../../lists/common';
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx
index c1efb4d7c4565..9cb219e7a8d45 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.tsx
@@ -15,10 +15,11 @@ import {
} from '@elastic/eui';
import { uniq } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { paramIsValid, getGenericComboBoxProps } from './helpers';
-import { OperatorTypeEnum } from '../../../lists_plugin_deps';
+
import { GetGenericComboBoxPropsReturn } from './types';
import * as i18n from './translations';
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.tsx
index e77bf570adc63..dbfdaf9749b6d 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.tsx
@@ -9,11 +9,12 @@ import React, { useState, useCallback, useMemo } from 'react';
import { EuiFormRow, EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui';
import { uniq } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { getGenericComboBoxProps, paramIsValid } from './helpers';
-import { OperatorTypeEnum } from '../../../lists_plugin_deps';
import { GetGenericComboBoxPropsReturn } from './types';
+
import * as i18n from './translations';
interface AutocompleteFieldMatchAnyProps {
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.ts
index b89f9525024c7..bd79bb0fcc8e8 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.ts
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.ts
@@ -8,6 +8,8 @@
import dateMath from '@elastic/datemath';
import { EuiComboBoxOptionOption } from '@elastic/eui';
+import type { Type } from '@kbn/securitysolution-io-ts-list-types';
+import type { ListSchema } from '../../../lists_plugin_deps';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import {
@@ -19,7 +21,6 @@ import {
} from './operators';
import { GetGenericComboBoxPropsReturn, OperatorOption } from './types';
import * as i18n from './translations';
-import { ListSchema, Type } from '../../../lists_plugin_deps';
/**
* Returns the appropriate operators given a field type
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
index 36e050c84f0b3..e0bdbf2603dc3 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts
@@ -15,7 +15,7 @@ import {
import { useKibana } from '../../../../common/lib/kibana';
import { stubIndexPatternWithFields } from '../../../../../../../../src/plugins/data/common/index_patterns/index_pattern.stub';
import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
-import { OperatorTypeEnum } from '../../../../lists_plugin_deps';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
jest.mock('../../../../common/lib/kibana');
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts
index b8440205e7d32..0f369fa01d01e 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.ts
@@ -8,9 +8,9 @@
import { useEffect, useState, useRef } from 'react';
import { debounce } from 'lodash';
+import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common';
import { useKibana } from '../../../../common/lib/kibana';
-import { OperatorTypeEnum } from '../../../../lists_plugin_deps';
interface FuncArgs {
fieldSelected: IFieldType | undefined;
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/operators.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/operators.ts
index 93eab41264bf7..53e2ddf84b3d3 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/operators.ts
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/operators.ts
@@ -6,8 +6,11 @@
*/
import { i18n } from '@kbn/i18n';
+import {
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
import { OperatorOption } from './types';
-import { OperatorEnum, OperatorTypeEnum } from '../../../lists_plugin_deps';
export const isOperator: OperatorOption = {
message: i18n.translate('xpack.securitySolution.exceptions.isOperatorLabel', {
diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/types.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/types.ts
index 903edc403ea25..1d8e3e9aee28e 100644
--- a/x-pack/plugins/security_solution/public/common/components/autocomplete/types.ts
+++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/types.ts
@@ -7,7 +7,10 @@
import { EuiComboBoxOptionOption } from '@elastic/eui';
-import { OperatorEnum, OperatorTypeEnum } from '../../../lists_plugin_deps';
+import type {
+ ListOperatorEnum as OperatorEnum,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
export interface GetGenericComboBoxPropsReturn {
comboOptions: EuiComboBoxOptionOption[];
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx
index c627363fc29ef..c13a1b011ccbd 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_comments.tsx
@@ -17,7 +17,7 @@ import {
EuiCommentProps,
EuiText,
} from '@elastic/eui';
-import { Comment } from '../../../shared_imports';
+import type { Comment } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from './translations';
import { useCurrentUser } from '../../lib/kibana';
import { getFormattedComments } from './helpers';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.test.tsx
index 5ec8999d20518..5fb527a821bac 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.test.tsx
@@ -49,7 +49,10 @@ jest.mock('../../../containers/source');
jest.mock('../../../../detections/containers/detection_engine/rules');
jest.mock('../use_add_exception');
jest.mock('../use_fetch_or_create_rule_exception_list');
-jest.mock('../../../../shared_imports');
+jest.mock('../../../../shared_imports', () => ({
+ ...jest.requireActual('../../../../shared_imports'),
+ useAsync: jest.fn(),
+}));
jest.mock('../../../../detections/containers/detection_engine/rules/use_rule_async');
describe('When the add exception modal is opened', () => {
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx
index 120c4ad8efc1b..6efbbcf64406b 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx
@@ -25,6 +25,7 @@ import {
EuiComboBox,
EuiComboBoxOptionOption,
} from '@elastic/eui';
+import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
hasEqlSequenceQuery,
isEqlRule,
@@ -34,9 +35,9 @@ import { Status } from '../../../../../common/detection_engine/schemas/common/sc
import {
ExceptionListItemSchema,
CreateExceptionListItemSchema,
- ExceptionListType,
ExceptionBuilder,
} from '../../../../../public/shared_imports';
+
import * as i18nCommon from '../../../translations';
import * as i18n from './translations';
import * as sharedI18n from '../translations';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx
index 5fb52994fb0f5..6c68dcf934b71 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx
@@ -22,6 +22,7 @@ import {
EuiCallOut,
} from '@elastic/eui';
+import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
hasEqlSequenceQuery,
isEqlRule,
@@ -33,9 +34,9 @@ import { useRuleAsync } from '../../../../detections/containers/detection_engine
import {
ExceptionListItemSchema,
CreateExceptionListItemSchema,
- ExceptionListType,
ExceptionBuilder,
} from '../../../../../public/shared_imports';
+
import * as i18n from './translations';
import * as sharedI18n from '../translations';
import { useKibana } from '../../../lib/kibana';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
index 907b30fcaa879..98c2b4db5676e 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
@@ -10,13 +10,8 @@ import { mount } from 'enzyme';
import moment from 'moment-timezone';
import {
- getOperatorType,
- getExceptionOperatorSelect,
getFormattedComments,
- filterExceptionItems,
- getNewExceptionItem,
formatOperatingSystems,
- getEntryValue,
formatExceptionItemForUpdate,
enrichNewExceptionItemsWithComments,
enrichExistingExceptionItemWithComments,
@@ -32,35 +27,19 @@ import {
retrieveAlertOsTypes,
filterIndexPatterns,
} from './helpers';
-import { AlertData, EmptyEntry } from './types';
+import { AlertData } from './types';
import {
- isOperator,
- isNotOperator,
- isOneOfOperator,
- isNotOneOfOperator,
- isInListOperator,
- isNotInListOperator,
- existsOperator,
- doesNotExistOperator,
-} from '../autocomplete/operators';
-import { OperatorTypeEnum, OperatorEnum, EntryNested } from '../../../shared_imports';
+ ListOperatorTypeEnum as OperatorTypeEnum,
+ EntriesArray,
+ OsTypeArray,
+} from '@kbn/securitysolution-io-ts-list-types';
+
import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
import { getEntryMatchMock } from '../../../../../lists/common/schemas/types/entry_match.mock';
-import { getEntryMatchAnyMock } from '../../../../../lists/common/schemas/types/entry_match_any.mock';
-import { getEntryExistsMock } from '../../../../../lists/common/schemas/types/entry_exists.mock';
-import { getEntryListMock } from '../../../../../lists/common/schemas/types/entry_list.mock';
import { getCommentsArrayMock } from '../../../../../lists/common/schemas/types/comment.mock';
import { fields } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
-import {
- ENTRIES,
- ENTRIES_WITH_IDS,
- OLD_DATE_RELATIVE_TO_DATE_NOW,
-} from '../../../../../lists/common/constants.mock';
-import { EntriesArray, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
-import {
- CreateExceptionListItemSchema,
- ExceptionListItemSchema,
-} from '../../../../../lists/common/schemas';
+import { ENTRIES, OLD_DATE_RELATIVE_TO_DATE_NOW } from '../../../../../lists/common/constants.mock';
+import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
import { IFieldType, IIndexPattern } from 'src/plugins/data/common';
jest.mock('uuid', () => ({
@@ -162,128 +141,6 @@ describe('Exception helpers', () => {
});
});
- describe('#getOperatorType', () => {
- test('returns operator type "match" if entry.type is "match"', () => {
- const payload = getEntryMatchMock();
- const operatorType = getOperatorType(payload);
-
- expect(operatorType).toEqual(OperatorTypeEnum.MATCH);
- });
-
- test('returns operator type "match_any" if entry.type is "match_any"', () => {
- const payload = getEntryMatchAnyMock();
- const operatorType = getOperatorType(payload);
-
- expect(operatorType).toEqual(OperatorTypeEnum.MATCH_ANY);
- });
-
- test('returns operator type "list" if entry.type is "list"', () => {
- const payload = getEntryListMock();
- const operatorType = getOperatorType(payload);
-
- expect(operatorType).toEqual(OperatorTypeEnum.LIST);
- });
-
- test('returns operator type "exists" if entry.type is "exists"', () => {
- const payload = getEntryExistsMock();
- const operatorType = getOperatorType(payload);
-
- expect(operatorType).toEqual(OperatorTypeEnum.EXISTS);
- });
- });
-
- describe('#getExceptionOperatorSelect', () => {
- test('it returns "isOperator" when "operator" is "included" and operator type is "match"', () => {
- const payload = getEntryMatchMock();
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isOperator);
- });
-
- test('it returns "isNotOperator" when "operator" is "excluded" and operator type is "match"', () => {
- const payload = getEntryMatchMock();
- payload.operator = 'excluded';
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isNotOperator);
- });
-
- test('it returns "isOneOfOperator" when "operator" is "included" and operator type is "match_any"', () => {
- const payload = getEntryMatchAnyMock();
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isOneOfOperator);
- });
-
- test('it returns "isNotOneOfOperator" when "operator" is "excluded" and operator type is "match_any"', () => {
- const payload = getEntryMatchAnyMock();
- payload.operator = 'excluded';
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isNotOneOfOperator);
- });
-
- test('it returns "existsOperator" when "operator" is "included" and no operator type is provided', () => {
- const payload = getEntryExistsMock();
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(existsOperator);
- });
-
- test('it returns "doesNotExistsOperator" when "operator" is "excluded" and no operator type is provided', () => {
- const payload = getEntryExistsMock();
- payload.operator = 'excluded';
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(doesNotExistOperator);
- });
-
- test('it returns "isInList" when "operator" is "included" and operator type is "list"', () => {
- const payload = getEntryListMock();
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isInListOperator);
- });
-
- test('it returns "isNotInList" when "operator" is "excluded" and operator type is "list"', () => {
- const payload = getEntryListMock();
- payload.operator = 'excluded';
- const result = getExceptionOperatorSelect(payload);
-
- expect(result).toEqual(isNotInListOperator);
- });
- });
-
- describe('#getEntryValue', () => {
- it('returns "match" entry value', () => {
- const payload = getEntryMatchMock();
- const result = getEntryValue(payload);
- const expected = 'some host name';
- expect(result).toEqual(expected);
- });
-
- it('returns "match any" entry values', () => {
- const payload = getEntryMatchAnyMock();
- const result = getEntryValue(payload);
- const expected = ['some host name'];
- expect(result).toEqual(expected);
- });
-
- it('returns "exists" entry value', () => {
- const payload = getEntryExistsMock();
- const result = getEntryValue(payload);
- const expected = undefined;
- expect(result).toEqual(expected);
- });
-
- it('returns "list" entry value', () => {
- const payload = getEntryListMock();
- const result = getEntryValue(payload);
- const expected = 'some-list-id';
- expect(result).toEqual(expected);
- });
- });
-
describe('#formatOperatingSystems', () => {
test('it returns null if no operating system tag specified', () => {
const result = formatOperatingSystems(['some os', 'some other os']);
@@ -324,178 +181,6 @@ describe('Exception helpers', () => {
});
});
- describe('#filterExceptionItems', () => {
- // Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes
- // for context around the temporary `id`
- test('it correctly validates entries that include a temporary `id`', () => {
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- { ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }]);
- });
-
- test('it removes entry items with "value" of "undefined"', () => {
- const { entries, ...rest } = getExceptionListItemSchemaMock();
- const mockEmptyException: EmptyEntry = {
- id: '123',
- field: 'host.name',
- type: OperatorTypeEnum.MATCH,
- operator: OperatorEnum.INCLUDED,
- value: undefined,
- };
- const exceptions = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(exceptions).toEqual([getExceptionListItemSchemaMock()]);
- });
-
- test('it removes "match" entry items with "value" of empty string', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EmptyEntry = {
- id: '123',
- field: 'host.name',
- type: OperatorTypeEnum.MATCH,
- operator: OperatorEnum.INCLUDED,
- value: '',
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
- });
-
- test('it removes "match" entry items with "field" of empty string', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EmptyEntry = {
- id: '123',
- field: '',
- type: OperatorTypeEnum.MATCH,
- operator: OperatorEnum.INCLUDED,
- value: 'some value',
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
- });
-
- test('it removes "match_any" entry items with "field" of empty string', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EmptyEntry = {
- id: '123',
- field: '',
- type: OperatorTypeEnum.MATCH_ANY,
- operator: OperatorEnum.INCLUDED,
- value: ['some value'],
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
- });
-
- test('it removes "nested" entry items with "field" of empty string', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EntryNested = {
- field: '',
- type: OperatorTypeEnum.NESTED,
- entries: [getEntryMatchMock()],
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
- });
-
- test('it removes the "nested" entry entries with "value" of empty string', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EntryNested = {
- field: 'host.name',
- type: OperatorTypeEnum.NESTED,
- entries: [getEntryMatchMock(), { ...getEntryMatchMock(), value: '' }],
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([
- {
- ...getExceptionListItemSchemaMock(),
- entries: [
- ...getExceptionListItemSchemaMock().entries,
- { ...mockEmptyException, entries: [getEntryMatchMock()] },
- ],
- },
- ]);
- });
-
- test('it removes the "nested" entry item if all its entries are invalid', () => {
- const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
- const mockEmptyException: EntryNested = {
- field: 'host.name',
- type: OperatorTypeEnum.NESTED,
- entries: [{ ...getEntryMatchMock(), value: '' }],
- };
- const output: Array<
- ExceptionListItemSchema | CreateExceptionListItemSchema
- > = filterExceptionItems([
- {
- ...rest,
- entries: [...entries, mockEmptyException],
- },
- ]);
-
- expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
- });
-
- test('it removes `temporaryId` from items', () => {
- const { meta, ...rest } = getNewExceptionItem({
- listId: '123',
- namespaceType: 'single',
- ruleName: 'rule name',
- });
- const exceptions = filterExceptionItems([{ ...rest, meta }]);
-
- expect(exceptions).toEqual([{ ...rest, entries: [], meta: undefined }]);
- });
- });
-
describe('#formatExceptionItemForUpdate', () => {
test('it should return correct update fields', () => {
const payload = getExceptionListItemSchemaMock();
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
index ce76114309e2e..437e93bb26fef 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
@@ -9,46 +9,36 @@ import React from 'react';
import { EuiText, EuiCommentProps, EuiAvatar } from '@elastic/eui';
import { capitalize } from 'lodash';
import moment from 'moment';
-import uuid from 'uuid';
-import * as i18n from './translations';
-import {
- AlertData,
- BuilderEntry,
- CreateExceptionListItemBuilderSchema,
- ExceptionsBuilderExceptionItem,
- Flattened,
-} from './types';
-import { EXCEPTION_OPERATORS, isOperator } from '../autocomplete/operators';
-import { OperatorOption } from '../autocomplete/types';
import {
+ comment,
+ osType,
CommentsArray,
Comment,
CreateComment,
Entry,
- ExceptionListItemSchema,
NamespaceType,
- OperatorTypeEnum,
- CreateExceptionListItemSchema,
- comment,
- entry,
- entriesNested,
- nestedEntryItem,
- createExceptionListItemSchema,
- exceptionListItemSchema,
- UpdateExceptionListItemSchema,
EntryNested,
OsTypeArray,
- EntriesArray,
- osType,
ExceptionListType,
+ ListOperatorTypeEnum as OperatorTypeEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import * as i18n from './translations';
+import { AlertData, ExceptionsBuilderExceptionItem, Flattened } from './types';
+import {
+ ExceptionListItemSchema,
+ CreateExceptionListItemSchema,
+ UpdateExceptionListItemSchema,
+ getOperatorType,
+ getNewExceptionItem,
+ addIdToEntries,
} from '../../../shared_imports';
+
import { IIndexPattern } from '../../../../../../../src/plugins/data/common';
-import { validate } from '../../../../common/validate';
import { Ecs } from '../../../../common/ecs';
import { CodeSignature } from '../../../../common/ecs/file';
import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard';
-import { addIdToItem, removeIdFromItem } from '../../../../common';
import exceptionableLinuxFields from './exceptionable_linux_fields.json';
import exceptionableWindowsMacFields from './exceptionable_windows_mac_fields.json';
import exceptionableEndpointFields from './exceptionable_endpoint_fields.json';
@@ -84,75 +74,6 @@ export const filterIndexPatterns = (
}
};
-export const addIdToEntries = (entries: EntriesArray): EntriesArray => {
- return entries.map((singleEntry) => {
- if (singleEntry.type === 'nested') {
- return addIdToItem({
- ...singleEntry,
- entries: singleEntry.entries.map((nestedEntry) => addIdToItem(nestedEntry)),
- });
- } else {
- return addIdToItem(singleEntry);
- }
- });
-};
-
-/**
- * Returns the operator type, may not need this if using io-ts types
- *
- * @param item a single ExceptionItem entry
- */
-export const getOperatorType = (item: BuilderEntry): OperatorTypeEnum => {
- switch (item.type) {
- case 'match':
- return OperatorTypeEnum.MATCH;
- case 'match_any':
- return OperatorTypeEnum.MATCH_ANY;
- case 'list':
- return OperatorTypeEnum.LIST;
- default:
- return OperatorTypeEnum.EXISTS;
- }
-};
-
-/**
- * Determines operator selection (is/is not/is one of, etc.)
- * Default operator is "is"
- *
- * @param item a single ExceptionItem entry
- */
-export const getExceptionOperatorSelect = (item: BuilderEntry): OperatorOption => {
- if (item.type === 'nested') {
- return isOperator;
- } else {
- const operatorType = getOperatorType(item);
- const foundOperator = EXCEPTION_OPERATORS.find((operatorOption) => {
- return item.operator === operatorOption.operator && operatorType === operatorOption.type;
- });
-
- return foundOperator ?? isOperator;
- }
-};
-
-/**
- * Returns the fields corresponding value for an entry
- *
- * @param item a single ExceptionItem entry
- */
-export const getEntryValue = (item: BuilderEntry): string | string[] | undefined => {
- switch (item.type) {
- case OperatorTypeEnum.MATCH:
- case OperatorTypeEnum.MATCH_ANY:
- return item.value;
- case OperatorTypeEnum.EXISTS:
- return undefined;
- case OperatorTypeEnum.LIST:
- return item.list.id;
- default:
- return undefined;
- }
-};
-
/**
* Formats os value array to a displayable string
*/
@@ -189,91 +110,6 @@ export const getFormattedComments = (comments: CommentsArray): EuiCommentProps[]
),
}));
-export const getNewExceptionItem = ({
- listId,
- namespaceType,
- ruleName,
-}: {
- listId: string;
- namespaceType: NamespaceType;
- ruleName: string;
-}): CreateExceptionListItemBuilderSchema => {
- return {
- comments: [],
- description: `${ruleName} - exception list item`,
- entries: addIdToEntries([
- {
- field: '',
- operator: 'included',
- type: 'match',
- value: '',
- },
- ]),
- item_id: undefined,
- list_id: listId,
- meta: {
- temporaryUuid: uuid.v4(),
- },
- name: `${ruleName} - exception list item`,
- namespace_type: namespaceType,
- tags: [],
- type: 'simple',
- };
-};
-
-export const filterExceptionItems = (
- exceptions: ExceptionsBuilderExceptionItem[]
-): Array => {
- return exceptions.reduce>(
- (acc, exception) => {
- const entries = exception.entries.reduce((nestedAcc, singleEntry) => {
- const strippedSingleEntry = removeIdFromItem(singleEntry);
-
- if (entriesNested.is(strippedSingleEntry)) {
- const nestedEntriesArray = strippedSingleEntry.entries.filter((singleNestedEntry) => {
- const noIdSingleNestedEntry = removeIdFromItem(singleNestedEntry);
- const [validatedNestedEntry] = validate(noIdSingleNestedEntry, nestedEntryItem);
- return validatedNestedEntry != null;
- });
- const noIdNestedEntries = nestedEntriesArray.map((singleNestedEntry) =>
- removeIdFromItem(singleNestedEntry)
- );
-
- const [validatedNestedEntry] = validate(
- { ...strippedSingleEntry, entries: noIdNestedEntries },
- entriesNested
- );
-
- if (validatedNestedEntry != null) {
- return [...nestedAcc, { ...singleEntry, entries: nestedEntriesArray }];
- }
- return nestedAcc;
- } else {
- const [validatedEntry] = validate(strippedSingleEntry, entry);
-
- if (validatedEntry != null) {
- return [...nestedAcc, singleEntry];
- }
- return nestedAcc;
- }
- }, []);
-
- const item = { ...exception, entries };
-
- if (exceptionListItemSchema.is(item)) {
- return [...acc, item];
- } else if (createExceptionListItemSchema.is(item)) {
- const { meta, ...rest } = item;
- const itemSansMetaId: CreateExceptionListItemSchema = { ...rest, meta: undefined };
- return [...acc, itemSansMetaId];
- } else {
- return acc;
- }
- },
- []
- );
-};
-
export const formatExceptionItemForUpdate = (
exceptionItem: ExceptionListItemSchema
): UpdateExceptionListItemSchema => {
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts
index 92a3cb2cfac93..49cdd7103c48b 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts
@@ -6,23 +6,22 @@
*/
import { ReactNode } from 'react';
-import { Ecs } from '../../../../common/ecs';
-import { CodeSignature } from '../../../../common/ecs/file';
-import { IFieldType } from '../../../../../../../src/plugins/data/common';
-import { OperatorOption } from '../autocomplete/types';
-import {
+import type {
EntryNested,
Entry,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryExists,
- ExceptionListItemSchema,
- CreateExceptionListItemSchema,
NamespaceType,
- OperatorTypeEnum,
- OperatorEnum,
-} from '../../../lists_plugin_deps';
+ ListOperatorTypeEnum as OperatorTypeEnum,
+ ListOperatorEnum as OperatorEnum,
+} from '@kbn/securitysolution-io-ts-list-types';
+import { Ecs } from '../../../../common/ecs';
+import { CodeSignature } from '../../../../common/ecs/file';
+import { IFieldType } from '../../../../../../../src/plugins/data/common';
+import { OperatorOption } from '../autocomplete/types';
+import { ExceptionListItemSchema, CreateExceptionListItemSchema } from '../../../lists_plugin_deps';
export interface FormattedEntry {
fieldName: string;
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx
index 0f6dd19ea9b66..f609acf9c6c63 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx
@@ -27,6 +27,7 @@ import {
ReturnUseAddOrUpdateException,
AddOrUpdateExceptionItemsFunc,
} from './use_add_exception';
+import { UpdateDocumentByQueryResponse } from 'elasticsearch';
const mockKibanaHttpService = coreMock.createStart().http;
const mockKibanaServices = KibanaServices.get as jest.Mock;
@@ -36,11 +37,9 @@ const fetchMock = jest.fn();
mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } });
describe('useAddOrUpdateException', () => {
- let updateAlertStatus: jest.SpyInstance>;
- let addExceptionListItem: jest.SpyInstance>;
- let updateExceptionListItem: jest.SpyInstance<
- ReturnType
- >;
+ let updateAlertStatus: jest.SpyInstance>;
+ let addExceptionListItem: jest.SpyInstance>;
+ let updateExceptionListItem: jest.SpyInstance>;
let getQueryFilter: jest.SpyInstance>;
let buildAlertStatusFilter: jest.SpyInstance<
ReturnType
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx
index 877f545b69d65..17237f4f94c61 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_fetch_or_create_rule_exception_list.test.tsx
@@ -12,7 +12,7 @@ import * as rulesApi from '../../../detections/containers/detection_engine/rules
import * as listsApi from '../../../../../lists/public/exceptions/api';
import { getExceptionListSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_schema.mock';
import { savedRuleMock } from '../../../detections/containers/detection_engine/rules/mock';
-import { ExceptionListType } from '../../../lists_plugin_deps';
+import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import { ListArray } from '../../../../common/detection_engine/schemas/types';
import { getListArrayMock } from '../../../../common/detection_engine/schemas/types/lists.mock';
import {
@@ -20,6 +20,7 @@ import {
UseFetchOrCreateRuleExceptionListProps,
ReturnUseFetchOrCreateRuleExceptionList,
} from './use_fetch_or_create_rule_exception_list';
+import { ExceptionListSchema } from '../../../shared_imports';
const mockKibanaHttpService = coreMock.createStart().http;
jest.mock('../../../detections/containers/detection_engine/rules/api');
@@ -31,7 +32,7 @@ describe('useFetchOrCreateRuleExceptionList', () => {
let addEndpointExceptionList: jest.SpyInstance<
ReturnType
>;
- let fetchExceptionListById: jest.SpyInstance>;
+ let fetchExceptionListById: jest.SpyInstance>;
let render: (
listType?: UseFetchOrCreateRuleExceptionListProps['exceptionListType']
) => RenderHookResult<
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx
index 8ded1b902f302..4f78b49ea266c 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx
@@ -11,8 +11,8 @@ import React from 'react';
import { ThemeProvider } from 'styled-components';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
+import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionsViewerHeader } from './exceptions_viewer_header';
-import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
addDecorator((storyFn) => (
({ eui: euiLightVars, darkMode: false })}>{storyFn()}
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx
index b82a472befdcf..7dcd59069b53c 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx
@@ -9,7 +9,8 @@ import React from 'react';
import { mount } from 'enzyme';
import { ExceptionsViewerHeader } from './exceptions_viewer_header';
-import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
+
+import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
describe('ExceptionsViewerHeader', () => {
it('it renders all disabled if "isInitLoading" is true', () => {
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx
index eff4368ef6809..8fc28ad89156d 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx
@@ -18,9 +18,9 @@ import {
} from '@elastic/eui';
import React, { useEffect, useState, useCallback, useMemo } from 'react';
+import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from '../translations';
import { Filter } from '../types';
-import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
interface ExceptionsViewerHeaderProps {
isInitLoading: boolean;
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/helpers.tsx
index 29764625075d6..abd45cf2945cb 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/helpers.tsx
@@ -7,8 +7,14 @@
import moment from 'moment';
-import { entriesNested, ExceptionListItemSchema } from '../../../../lists_plugin_deps';
-import { getEntryValue, getExceptionOperatorSelect, formatOperatingSystems } from '../helpers';
+import { entriesNested } from '@kbn/securitysolution-io-ts-list-types';
+import {
+ ExceptionListItemSchema,
+ getEntryValue,
+ getExceptionOperatorSelect,
+} from '../../../../lists_plugin_deps';
+
+import { formatOperatingSystems } from '../helpers';
import { FormattedEntry, BuilderEntry, DescriptionListItem } from '../types';
import * as i18n from '../translations';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx
index 3fe6497105af1..971b3fda47191 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx
@@ -11,11 +11,9 @@ import { ThemeProvider } from 'styled-components';
import { ExceptionsViewer } from './';
import { useKibana } from '../../../../common/lib/kibana';
-import {
- ExceptionListTypeEnum,
- useExceptionListItems,
- useApi,
-} from '../../../../../public/lists_plugin_deps';
+import { useExceptionListItems, useApi } from '../../../../../public/lists_plugin_deps';
+
+import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { getExceptionListSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_schema.mock';
import { getFoundExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/found_exception_list_item_schema.mock';
import { getMockTheme } from '../../../lib/kibana/kibana_react.mock';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx
index 8c4569ed29b33..da7607f40ab72 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx
@@ -9,6 +9,7 @@ import React, { useCallback, useEffect, useReducer } from 'react';
import { EuiSpacer } from '@elastic/eui';
import uuid from 'uuid';
+import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from '../translations';
import { useStateToaster } from '../../toasters';
import { useKibana } from '../../../../common/lib/kibana';
@@ -20,11 +21,11 @@ import { allExceptionItemsReducer, State, ViewerModalName } from './reducer';
import {
useExceptionListItems,
ExceptionListIdentifiers,
- ExceptionListTypeEnum,
ExceptionListItemSchema,
UseExceptionListItemsSuccess,
useApi,
} from '../../../../../public/lists_plugin_deps';
+
import { ExceptionsViewerPagination } from './exceptions_pagination';
import { ExceptionsViewerUtility } from './exceptions_utility';
import { ExceptionsViewerItems } from './exceptions_viewer_items';
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts
index 46ac19f47503d..bf8e454e9971f 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
FilterOptions,
ExceptionsPagination,
@@ -12,7 +13,6 @@ import {
Filter,
} from '../types';
import {
- ExceptionListType,
ExceptionListItemSchema,
ExceptionListIdentifiers,
Pagination,
diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx
index 69e41a2c3d0a2..3152c08fab323 100644
--- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx
@@ -19,6 +19,7 @@ import styled from 'styled-components';
import { getOr } from 'lodash/fp';
import { indexOf } from 'lodash';
+import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import { buildGetAlertByIdQuery } from '../../../../common/components/exceptions/helpers';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { TimelineId } from '../../../../../common/types/timeline';
@@ -44,7 +45,6 @@ import {
} from '../../../../common/components/toasters';
import { inputsModel } from '../../../../common/store';
import { useUserData } from '../../user_info';
-import { ExceptionListType } from '../../../../../common/shared_imports';
import { AlertData, EcsHit } from '../../../../common/components/exceptions/types';
import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query';
import { useSignalIndex } from '../../../containers/detection_engine/alerts/use_signal_index';
diff --git a/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/form.tsx b/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/form.tsx
index 94cb22592f4ed..ea903882c326d 100644
--- a/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/form.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/form.tsx
@@ -18,7 +18,9 @@ import {
EuiSelectOption,
} from '@elastic/eui';
-import { useImportList, ListSchema, Type } from '../../../shared_imports';
+import type { Type } from '@kbn/securitysolution-io-ts-list-types';
+import { useImportList, ListSchema } from '../../../shared_imports';
+
import * as i18n from './translations';
import { useKibana } from '../../../common/lib/kibana';
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx
index d11ceee7f5978..64cb936f160f1 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx
@@ -11,8 +11,8 @@ import React from 'react';
import { EuiButtonIcon, EuiBasicTableColumn, EuiToolTip } from '@elastic/eui';
import { History } from 'history';
+import { NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { Spacer } from '../../../../../../common/components/page';
-import { NamespaceType } from '../../../../../../../../lists/common';
import { FormatUrl } from '../../../../../../common/components/link_to';
import { LinkAnchor } from '../../../../../../common/components/links';
import * as i18n from './translations';
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx
index 146b7e8470718..50cf1b1830fec 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_table.tsx
@@ -15,9 +15,9 @@ import {
} from '@elastic/eui';
import { History } from 'history';
+import { NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts';
import { AutoDownload } from '../../../../../../common/components/auto_download/auto_download';
-import { NamespaceType } from '../../../../../../../../lists/common';
import { useKibana } from '../../../../../../common/lib/kibana';
import { ExceptionListFilter, useApi, useExceptionLists } from '../../../../../../shared_imports';
import { FormatUrl } from '../../../../../../common/components/link_to';
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/helpers.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/helpers.ts
index 64dfac5787f23..29b63721513d4 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/helpers.ts
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/helpers.ts
@@ -9,11 +9,12 @@ import { has, isEmpty } from 'lodash/fp';
import moment from 'moment';
import deepmerge from 'deepmerge';
+import type { ExceptionListType, NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { NOTIFICATION_THROTTLE_NO_ACTIONS } from '../../../../../../common/constants';
import { assertUnreachable } from '../../../../../../common/utility_types';
import { transformAlertToRuleAction } from '../../../../../../common/detection_engine/transform_actions';
import { List } from '../../../../../../common/detection_engine/schemas/types';
-import { ENDPOINT_LIST_ID, ExceptionListType, NamespaceType } from '../../../../../shared_imports';
+import { ENDPOINT_LIST_ID } from '../../../../../shared_imports';
import { Rule } from '../../../../containers/detection_engine/rules';
import {
Threats,
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
index 0fab428ef6d1b..9660132147a57 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx
@@ -28,6 +28,7 @@ import { useDispatch } from 'react-redux';
import styled from 'styled-components';
import deepEqual from 'fast-deep-equal';
+import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import {
useDeepEqualSelector,
useShallowEqualSelector,
@@ -83,7 +84,8 @@ import { ExceptionsViewer } from '../../../../../common/components/exceptions/vi
import { DEFAULT_INDEX_PATTERN } from '../../../../../../common/constants';
import { useGlobalFullScreen } from '../../../../../common/containers/use_full_screen';
import { Display } from '../../../../../hosts/pages/display';
-import { ExceptionListTypeEnum, ExceptionListIdentifiers } from '../../../../../shared_imports';
+import type { ExceptionListIdentifiers } from '../../../../../shared_imports';
+
import {
focusUtilityBarAction,
onTimelineTabKeyPressed,
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts
index 5d600f471994b..e1fa1107fcb01 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/constants.ts
@@ -5,9 +5,8 @@
* 2.0.
*/
+import { ExceptionListType, ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import {
- ExceptionListType,
- ExceptionListTypeEnum,
EXCEPTION_LIST_URL,
EXCEPTION_LIST_ITEM_URL,
ENDPOINT_EVENT_FILTERS_LIST_ID,
diff --git a/x-pack/plugins/security_solution/public/shared_imports.ts b/x-pack/plugins/security_solution/public/shared_imports.ts
index e77c4a0eec486..76ec761d41703 100644
--- a/x-pack/plugins/security_solution/public/shared_imports.ts
+++ b/x-pack/plugins/security_solution/public/shared_imports.ts
@@ -33,23 +33,23 @@ export { ERROR_CODE } from '../../../../src/plugins/es_ui_shared/static/forms/he
export {
exportList,
- useIsMounted,
useCursor,
useApi,
useAsync,
useExceptionListItems,
useExceptionLists,
- usePersistExceptionItem,
- usePersistExceptionList,
useFindLists,
useDeleteList,
useImportList,
useCreateListIndex,
useReadListIndex,
useReadListPrivileges,
- addExceptionListItem,
- updateExceptionListItem,
fetchExceptionListById,
+ addIdToEntries,
+ getOperatorType,
+ getNewExceptionItem,
+ getEntryValue,
+ getExceptionOperatorSelect,
addExceptionList,
ExceptionListFilter,
ExceptionListIdentifiers,
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/mapping.ts b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/mapping.ts
index 786a74e91b51a..e4704523a16c3 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/mapping.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/mapping.ts
@@ -7,17 +7,19 @@
import uuid from 'uuid';
-import { OsType } from '../../../../../lists/common/schemas';
-import {
+import type {
EntriesArray,
EntryMatch,
EntryMatchWildcard,
EntryNested,
- ExceptionListItemSchema,
NestedEntriesArray,
-} from '../../../../../lists/common';
+} from '@kbn/securitysolution-io-ts-list-types';
+
+import type { ExceptionListItemSchema } from '../../../../../lists/common';
+
+import type { OsType } from '../../../../../lists/common/schemas';
import { ENDPOINT_TRUSTED_APPS_LIST_ID } from '../../../../../lists/common/constants';
-import {
+import type {
CreateExceptionListItemOptions,
UpdateExceptionListItemOptions,
} from '../../../../../lists/server';
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts
index 3fa5d1178b3ec..578c1aba64558 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.test.ts
@@ -11,7 +11,7 @@ import { mockLogger, sampleDocWithSortId } from '../__mocks__/es_results';
import { getExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
import { listMock } from '../../../../../../lists/server/mocks';
import { getSearchListItemResponseMock } from '../../../../../../lists/common/schemas/response/search_list_item_schema.mock';
-import { EntryList } from '../../../../../../lists/common';
+import { EntryList } from '@kbn/securitysolution-io-ts-list-types';
import { buildRuleMessageMock as buildRuleMessage } from '../rule_messages.mock';
describe('filterEventsAgainstList', () => {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts
index b2002dbb5a7e2..40322029c1d98 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/create_field_and_set_tuples.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { EntryList, entriesList } from '../../../../../../lists/common';
+import { EntryList, entriesList } from '@kbn/securitysolution-io-ts-list-types';
import { createSetToFilterAgainst } from './create_set_to_filter_against';
import { CreateFieldAndSetTuplesOptions, FieldSet } from './types';
diff --git a/x-pack/plugins/uptime/public/components/fleet_package/http_advanced_fields.tsx b/x-pack/plugins/uptime/public/components/fleet_package/http_advanced_fields.tsx
index 5cc1dd12ef961..7ab6c81fbf162 100644
--- a/x-pack/plugins/uptime/public/components/fleet_package/http_advanced_fields.tsx
+++ b/x-pack/plugins/uptime/public/components/fleet_package/http_advanced_fields.tsx
@@ -17,6 +17,7 @@ import {
EuiDescribedFormGroup,
EuiCheckbox,
EuiSpacer,
+ EuiFieldPassword,
} from '@elastic/eui';
import { useHTTPAdvancedFieldsContext } from './contexts';
@@ -110,7 +111,7 @@ export const HTTPAdvancedFields = memo(({ validate }) => {
/>
}
>
-
handleInputChange({
diff --git a/x-pack/plugins/uptime/public/components/fleet_package/tls_fields.tsx b/x-pack/plugins/uptime/public/components/fleet_package/tls_fields.tsx
index e01d3d59175a4..de8879ec3a819 100644
--- a/x-pack/plugins/uptime/public/components/fleet_package/tls_fields.tsx
+++ b/x-pack/plugins/uptime/public/components/fleet_package/tls_fields.tsx
@@ -13,12 +13,12 @@ import {
EuiComboBox,
EuiComboBoxOptionOption,
EuiFormRow,
- EuiFieldText,
EuiTextArea,
EuiFormFieldset,
EuiSelect,
EuiScreenReaderOnly,
EuiSpacer,
+ EuiFieldPassword,
} from '@elastic/eui';
import { useTLSFieldsContext } from './contexts';
@@ -333,7 +333,7 @@ export const TLSFields: React.FunctionComponent<{
}
labelAppend={}
>
- {
const value = event.target.value;
diff --git a/x-pack/test/functional/apps/status_page/status_page.ts b/x-pack/test/functional/apps/status_page/status_page.ts
index 55a54245cf832..ecef6225632e9 100644
--- a/x-pack/test/functional/apps/status_page/status_page.ts
+++ b/x-pack/test/functional/apps/status_page/status_page.ts
@@ -12,17 +12,16 @@ export default function statusPageFunctonalTests({
getPageObjects,
}: FtrProviderContext) {
const esArchiver = getService('esArchiver');
- const PageObjects = getPageObjects(['security', 'statusPage', 'home']);
+ const PageObjects = getPageObjects(['security', 'statusPage', 'common']);
- // FLAKY: https://github.com/elastic/kibana/issues/50448
- describe.skip('Status Page', function () {
+ describe('Status Page', function () {
this.tags(['skipCloud', 'includeFirefox']);
before(async () => await esArchiver.load('empty_kibana'));
after(async () => await esArchiver.unload('empty_kibana'));
it('allows user to navigate without authentication', async () => {
await PageObjects.security.forceLogout();
- await PageObjects.statusPage.navigateToPage();
+ await PageObjects.common.navigateToApp('status_page', { shouldLoginIfPrompted: false });
await PageObjects.statusPage.expectStatusPage();
});
});
diff --git a/x-pack/test/functional/page_objects/status_page.ts b/x-pack/test/functional/page_objects/status_page.ts
index 9edaf4dea53f8..ed90aef954770 100644
--- a/x-pack/test/functional/page_objects/status_page.ts
+++ b/x-pack/test/functional/page_objects/status_page.ts
@@ -5,36 +5,18 @@
* 2.0.
*/
-import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function StatusPagePageProvider({ getService }: FtrProviderContext) {
- const retry = getService('retry');
const log = getService('log');
- const browser = getService('browser');
const find = getService('find');
- const deployment = getService('deployment');
-
class StatusPage {
async initTests() {
log.debug('StatusPage:initTests');
}
- async navigateToPage() {
- return await retry.try(async () => {
- const url = deployment.getHostPort() + '/status';
- log.info(`StatusPage:navigateToPage(): ${url}`);
- await browser.get(url);
- });
- }
-
async expectStatusPage(): Promise {
- return await retry.try(async () => {
- log.debug(`expectStatusPage()`);
- await find.byCssSelector('[data-test-subj="statusPageRoot"]', 20000);
- const url = await browser.getCurrentUrl();
- expect(url).to.contain(`/status`);
- });
+ await find.byCssSelector('[data-test-subj="statusPageRoot"]', 20000);
}
}