[Security Solution][Exceptions] - Fixes up some bugs in the all exception items view (#141682) (#142237)

### Summary
Addresses #140709, #141056, #141421, #141042

(cherry picked from commit 49d0858a40)

Co-authored-by: Yara Tercero <yctercero@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2022-09-29 10:39:10 -06:00 committed by GitHub
parent c5e9eb8c11
commit 9ac9f39bcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 21 deletions

View file

@ -6,20 +6,21 @@
*/
import React, { useCallback, useMemo, useEffect, useReducer } from 'react';
import { EuiPanel, EuiSpacer } from '@elastic/eui';
import { EuiPanel, EuiSpacer, EuiText } from '@elastic/eui';
import type {
ExceptionListItemSchema,
UseExceptionListItemsSuccess,
Pagination,
ExceptionListTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { transformInput } from '@kbn/securitysolution-list-hooks';
import {
deleteExceptionListItemById,
fetchExceptionListsItemsByListIds,
} from '@kbn/securitysolution-list-api';
import styled from 'styled-components';
import { DEFAULT_INDEX_PATTERN } from '../../../../../common/constants';
import { useUserData } from '../../../../detections/components/user_info';
import { useKibana, useToasts } from '../../../../common/lib/kibana';
@ -37,6 +38,10 @@ import * as i18n from './translations';
import { useFindExceptionListReferences } from '../../logic/use_find_references';
import type { Rule } from '../../../../detections/containers/detection_engine/rules/types';
const StyledText = styled(EuiText)`
font-style: italic;
`;
const STATES_SEARCH_HIDDEN: ViewerState[] = ['error', 'empty'];
const STATES_PAGINATION_UTILITY_HIDDEN: ViewerState[] = [
'loading',
@ -51,7 +56,7 @@ const initialState: State = {
pageIndex: 0,
pageSize: 25,
totalItemCount: 0,
pageSizeOptions: [1, 5, 10, 25, 50, 100, 200, 300],
pageSizeOptions: [5, 10, 25, 50, 100, 200, 300],
},
exceptions: [],
exceptionToEdit: null,
@ -154,7 +159,18 @@ const ExceptionsViewerComponent = ({
[dispatch]
);
const [_, allReferences] = useFindExceptionListReferences(exceptionListsToQuery);
const [isLoadingReferences, isFetchReferencesError, allReferences] =
useFindExceptionListReferences(exceptionListsToQuery);
useEffect(() => {
if (isFetchReferencesError) {
setViewerState('error');
} else if (viewerState == null && isLoadingReferences) {
setViewerState('loading');
} else if (viewerState === 'loading' && !isLoadingReferences) {
setViewerState(null);
}
}, [isLoadingReferences, isFetchReferencesError, setViewerState, viewerState]);
const handleFetchItems = useCallback(
async (options?: GetExceptionItemProps) => {
@ -212,12 +228,8 @@ const ExceptionsViewerComponent = ({
const handleGetExceptionListItems = useCallback(
async (options?: GetExceptionItemProps) => {
try {
setViewerState('loading');
const { pageIndex, itemsPerPage, total, data } = await handleFetchItems(options);
setViewerState(total > 0 ? null : 'empty');
setExceptions({
exceptions: data,
pagination: {
@ -226,6 +238,8 @@ const ExceptionsViewerComponent = ({
total,
},
});
setViewerState(total > 0 ? null : 'empty');
} catch (e) {
setViewerState('error');
@ -367,6 +381,12 @@ const ExceptionsViewerComponent = ({
<EuiPanel hasBorder={false} hasShadow={false}>
<>
<StyledText size="s">
{listType === ExceptionListTypeEnum.ENDPOINT
? i18n.ENDPOINT_EXCEPTIONS_TAB_ABOUT
: i18n.EXCEPTIONS_TAB_ABOUT}
</StyledText>
<EuiSpacer size="l" />
{!STATES_SEARCH_HIDDEN.includes(viewerState) && (
<ExceptionsViewerSearchBar
canAddException={isReadOnly}

View file

@ -9,7 +9,8 @@ import React, { useCallback, useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSearchBar } from '@elastic/eui';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from '../../utils/translations';
import * as sharedI18n from '../../utils/translations';
import * as i18n from './translations';
import type { GetExceptionItemProps } from '.';
const ITEMS_SCHEMA = {
@ -75,8 +76,8 @@ const ExceptionsViewerSearchBarComponent = ({
const addExceptionButtonText = useMemo(() => {
return listType === ExceptionListTypeEnum.ENDPOINT
? i18n.ADD_TO_ENDPOINT_LIST
: i18n.ADD_TO_DETECTIONS_LIST;
? sharedI18n.ADD_TO_ENDPOINT_LIST
: sharedI18n.ADD_TO_DETECTIONS_LIST;
}, [listType]);
return (
@ -84,7 +85,7 @@ const ExceptionsViewerSearchBarComponent = ({
<EuiFlexItem grow={true}>
<EuiSearchBar
box={{
placeholder: 'Search on the fields below: e.g. name:"my list"',
placeholder: i18n.SEARCH_PLACEHOLDER,
incremental: true,
schema: ITEMS_SCHEMA,
'data-test-subj': 'exceptionsViewerSearchBar',

View file

@ -38,8 +38,7 @@ export const EXCEPTION_EMPTY_PROMPT_BODY = i18n.translate(
export const EXCEPTION_EMPTY_ENDPOINT_PROMPT_BODY = i18n.translate(
'xpack.securitySolution.exceptions.allItems.endpoint.emptyPromptBody',
{
defaultMessage:
'There are no endpoint exceptions. Endpoint exceptions are applied to the endpoint and the detection rule. Create your first endpoint exception.',
defaultMessage: 'There are no endpoint exceptions. Create your first endpoint exception.',
}
);
@ -112,3 +111,25 @@ export const EXCEPTION_ITEM_DELETE_TEXT = (itemName: string) =>
values: { itemName },
defaultMessage: '"{itemName}" deleted successfully.',
});
export const ENDPOINT_EXCEPTIONS_TAB_ABOUT = i18n.translate(
'xpack.securitySolution.exceptions.allExceptionItems.exceptionEndpointDetailsDescription',
{
defaultMessage:
'Endpoint exceptions are added to both the detection rule and the Elastic Endpoint agent on your hosts.',
}
);
export const EXCEPTIONS_TAB_ABOUT = i18n.translate(
'xpack.securitySolution.exceptions.allExceptionItems.exceptionDetectionDetailsDescription',
{
defaultMessage: 'Rule exceptions are added to the detection rule.',
}
);
export const SEARCH_PLACEHOLDER = i18n.translate(
'xpack.securitySolution.exceptions.allExceptionItems.searchPlaceholder',
{
defaultMessage: 'Filter exceptions using simple query syntax, for example, name:"my list"',
}
);

View file

@ -14,7 +14,7 @@ import { useToasts } from '../../../common/lib/kibana';
import type { FindRulesReferencedByExceptionsListProp } from '../../../detections/containers/detection_engine/rules/types';
import * as i18n from '../utils/translations';
export type ReturnUseFindExceptionListReferences = [boolean, RuleReferences | null];
export type ReturnUseFindExceptionListReferences = [boolean, boolean, RuleReferences | null];
export interface RuleReferences {
[key: string]: RuleReferenceSchema[];
@ -28,6 +28,7 @@ export const useFindExceptionListReferences = (
): ReturnUseFindExceptionListReferences => {
const toasts = useToasts();
const [isLoading, setIsLoading] = useState(false);
const [errorExists, setErrorExists] = useState(false);
const [references, setReferences] = useState<RuleReferences | null>(null);
const listRefs = useMemo((): FindRulesReferencedByExceptionsListProp[] => {
return ruleExceptionLists.map((list) => {
@ -61,11 +62,13 @@ export const useFindExceptionListReferences = (
}, {});
if (isSubscribed) {
setErrorExists(false);
setIsLoading(false);
setReferences(results);
}
} catch (error) {
if (isSubscribed) {
setErrorExists(true);
setIsLoading(false);
toasts.addError(error, { title: i18n.ERROR_FETCHING_REFERENCES_TITLE });
}
@ -73,6 +76,7 @@ export const useFindExceptionListReferences = (
};
if (listRefs.length === 0 && isSubscribed) {
setErrorExists(false);
setIsLoading(false);
setReferences(null);
} else {
@ -85,5 +89,5 @@ export const useFindExceptionListReferences = (
};
}, [ruleExceptionLists, listRefs, toasts]);
return [isLoading, references];
return [isLoading, errorExists, references];
};

View file

@ -155,9 +155,9 @@ export const referenceErrorMessage = (referenceCount: number) =>
});
export const EXCEPTION_LIST_SEARCH_PLACEHOLDER = i18n.translate(
'xpack.securitySolution.exceptions.searchPlaceholder',
'xpack.securitySolution.detectionEngine.rules.all.exceptions.searchPlaceholder',
{
defaultMessage: 'e.g. Example List Name',
defaultMessage: 'Search by name or list_id',
}
);

View file

@ -27945,7 +27945,6 @@
"xpack.securitySolution.exceptions.referenceModalCancelButton": "Annuler",
"xpack.securitySolution.exceptions.referenceModalDeleteButton": "Retirer la liste d'exceptions",
"xpack.securitySolution.exceptions.referenceModalTitle": "Retirer la liste d'exceptions",
"xpack.securitySolution.exceptions.searchPlaceholder": "par ex. Exemple de liste de noms",
"xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "Ajouter un nouveau commentaire...",
"xpack.securitySolution.exceptions.viewer.addToClipboard": "Commentaire",
"xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "Ajouter une exception à une règle",

View file

@ -27920,7 +27920,6 @@
"xpack.securitySolution.exceptions.referenceModalCancelButton": "キャンセル",
"xpack.securitySolution.exceptions.referenceModalDeleteButton": "例外リストを削除",
"xpack.securitySolution.exceptions.referenceModalTitle": "例外リストを削除",
"xpack.securitySolution.exceptions.searchPlaceholder": "例:例外リスト名",
"xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "新しいコメントを追加...",
"xpack.securitySolution.exceptions.viewer.addToClipboard": "コメント",
"xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "ルール例外の追加",

View file

@ -27951,7 +27951,6 @@
"xpack.securitySolution.exceptions.referenceModalCancelButton": "取消",
"xpack.securitySolution.exceptions.referenceModalDeleteButton": "移除例外列表",
"xpack.securitySolution.exceptions.referenceModalTitle": "移除例外列表",
"xpack.securitySolution.exceptions.searchPlaceholder": "例如,示例列表名称",
"xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "添加新注释......",
"xpack.securitySolution.exceptions.viewer.addToClipboard": "注释",
"xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "添加规则例外",