From e8cc2ff72f967a048d64c1f5072df8b1a4f2dae9 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Thu, 30 Jul 2020 13:02:54 -0400 Subject: [PATCH] [SECURITY_SOLUTION][ENDPOINT] Fix Endpoint Hosts crashing periodically when switching between policy responses from linux and windows (#73809) * Fix use of hooks in policy response * Additional fixes to use of `useMemo` * Added error boundary to management pages --- .../components/management_page_view.tsx | 7 ++- .../view/details/policy_response.tsx | 12 ++---- .../view/policy_forms/events/checkbox.tsx | 3 +- .../view/policy_forms/protections/malware.tsx | 3 +- .../pages/policy/view/policy_list.tsx | 43 ++++++++----------- 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx index aa562b9a202017..54d9131209d0d8 100644 --- a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx +++ b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx @@ -5,10 +5,15 @@ */ import React, { memo } from 'react'; +import { EuiErrorBoundary } from '@elastic/eui'; import { PageView, PageViewProps } from '../../common/components/endpoint/page_view'; export const ManagementPageView = memo>((options) => { - return ; + return ( + + + + ); }); ManagementPageView.displayName = 'ManagementPageView'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/policy_response.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/policy_response.tsx index 4cdfaad69eb726..3a1dd180405e04 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/policy_response.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/policy_response.tsx @@ -140,20 +140,16 @@ export const PolicyResponse = memo( responseActions: Immutable; responseAttentionCount: Map; }) => { + const generateId = useMemo(() => htmlIdGenerator(), []); + return ( <> {Object.entries(responseConfig).map(([key, val]) => { const attentionCount = responseAttentionCount.get(key); return ( htmlIdGenerator()(), []) - } - key={ - /* eslint-disable-next-line react-hooks/rules-of-hooks */ - useMemo(() => htmlIdGenerator()(), []) - } + id={generateId(`id_${key}`)} + key={generateId(`key_${key}`)} data-test-subj="hostDetailsPolicyResponseConfigAccordion" buttonContent={ diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx index 9ceade5d0264c4..76077831c670b4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx @@ -27,6 +27,7 @@ export const EventsCheckbox = React.memo(function ({ const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); const selected = getter(policyDetailsConfig); const dispatch = useDispatch<(action: PolicyDetailsAction) => void>(); + const checkboxId = useMemo(() => htmlIdGenerator()(), []); const handleCheckboxChange = useCallback( (event: React.ChangeEvent) => { @@ -42,7 +43,7 @@ export const EventsCheckbox = React.memo(function ({ return ( htmlIdGenerator()(), [])} + id={checkboxId} label={name} checked={selected} onChange={handleCheckboxChange} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx index 84d4bf5355cd98..1698f5bc3fd0c2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/protections/malware.tsx @@ -41,6 +41,7 @@ const protection = 'malware'; const ProtectionRadio = React.memo(({ id, label }: { id: ProtectionModes; label: string }) => { const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); const dispatch = useDispatch(); + const radioButtonId = useMemo(() => htmlIdGenerator()(), []); // currently just taking windows.malware, but both windows.malware and mac.malware should be the same value const selected = policyDetailsConfig && policyDetailsConfig.windows.malware.mode; @@ -66,7 +67,7 @@ const ProtectionRadio = React.memo(({ id, label }: { id: ProtectionModes; label: htmlIdGenerator()(), [])} + id={radioButtonId} checked={selected === id} onChange={handleRadioChange} disabled={selected === ProtectionModes.off} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx index 246dbeb39886fb..39b77d259add1b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx @@ -377,6 +377,22 @@ export const PolicyList = React.memo(() => { [services.application, handleDeleteOnClick, formatUrl, search] ); + const bodyContent = useMemo(() => { + return policyItems && policyItems.length > 0 ? ( + + ) : ( + + ); + }, [policyItems, loading, columns, handleCreatePolicyClick, handleTableChange, paginationSetup]); + return ( <> {showDelete && ( @@ -449,32 +465,7 @@ export const PolicyList = React.memo(() => { )} - {useMemo(() => { - return ( - <> - {policyItems && policyItems.length > 0 ? ( - - ) : ( - - )} - - ); - }, [ - policyItems, - loading, - columns, - handleCreatePolicyClick, - handleTableChange, - paginationSetup, - ])} + {bodyContent}