diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx
index a0fa1f6683964..ecc4f7954460d 100644
--- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.test.tsx
@@ -160,11 +160,11 @@ describe('Alert table context menu', () => {
ecsRowData: { ...ecsRowData, agent: { type: ['endpoint'] }, event: { kind: ['event'] } },
};
- describe('when users can access endpoint management', () => {
+ describe('when users has write event filters privilege', () => {
beforeEach(() => {
(useUserPrivileges as jest.Mock).mockReturnValue({
...mockInitialUserPrivilegesState(),
- endpointPrivileges: { loading: false, canAccessEndpointManagement: true },
+ endpointPrivileges: { loading: false, canWriteEventFilters: true },
});
});
@@ -246,15 +246,15 @@ describe('Alert table context menu', () => {
});
});
- describe('when users can NOT access endpoint management', () => {
+ describe("when users don't have write event filters privilege", () => {
beforeEach(() => {
(useUserPrivileges as jest.Mock).mockReturnValue({
...mockInitialUserPrivilegesState(),
- endpointPrivileges: { loading: false, canAccessEndpointManagement: false },
+ endpointPrivileges: { loading: false, canWriteEventFilters: false },
});
});
- test('it disables AddEndpointEventFilter when timeline id is host events page but cannot acces endpoint management', () => {
+ test('it removes AddEndpointEventFilter option when timeline id is host events page but does not has write event filters privilege', () => {
const wrapper = mount(
,
{
@@ -262,12 +262,11 @@ describe('Alert table context menu', () => {
}
);
- wrapper.find(actionMenuButton).simulate('click');
- expect(wrapper.find(addEndpointEventFilterButton).first().exists()).toEqual(true);
- expect(wrapper.find(addEndpointEventFilterButton).first().props().disabled).toEqual(true);
+ // Entire actionMenuButton is removed as there is no option available
+ expect(wrapper.find(actionMenuButton).first().exists()).toEqual(false);
});
- test('it disables AddEndpointEventFilter when timeline id is user events page but cannot acces endpoint management', () => {
+ test('it removes AddEndpointEventFilter option when timeline id is user events page but does not has write event filters privilege', () => {
const wrapper = mount(
,
{
@@ -275,9 +274,8 @@ describe('Alert table context menu', () => {
}
);
- wrapper.find(actionMenuButton).simulate('click');
- expect(wrapper.find(addEndpointEventFilterButton).first().exists()).toEqual(true);
- expect(wrapper.find(addEndpointEventFilterButton).first().props().disabled).toEqual(true);
+ // Entire actionMenuButton is removed as there is no option available
+ expect(wrapper.find(actionMenuButton).first().exists()).toEqual(false);
});
});
});
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 31a548e2ced9c..9d8aac03daea3 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
@@ -90,11 +90,11 @@ const AlertContextMenuComponent: React.FC !canAccessEndpointManagementLoading && canAccessEndpointManagement,
- [canAccessEndpointManagement, canAccessEndpointManagementLoading]
+ () => !endpointPrivilegesLoading && canWriteEventFilters,
+ [canWriteEventFilters, endpointPrivilegesLoading]
);
const alertStatus = get(0, ecsRowData?.kibana?.alert?.workflow_status) as Status | undefined;
@@ -194,8 +194,7 @@ const AlertContextMenuComponent: React.FC {
setAlertDetailsDataMockToEvent();
});
- test('should enable the "Add Endpoint event filter" button if provided endpoint event', async () => {
+ test('should enable the "Add Endpoint event filter" button if provided endpoint event and has right privileges', async () => {
+ (useUserPrivileges as jest.Mock).mockReturnValue({
+ ...mockInitialUserPrivilegesState(),
+ endpointPrivileges: { loading: false, canWriteEventFilters: true },
+ });
wrapper = mount(
@@ -334,10 +338,10 @@ describe('take action dropdown', () => {
});
});
- test('should disable the "Add Endpoint event filter" button if no endpoint management privileges', async () => {
+ test('should hide the "Add Endpoint event filter" button if no write event filters privileges', async () => {
(useUserPrivileges as jest.Mock).mockReturnValue({
...mockInitialUserPrivilegesState(),
- endpointPrivileges: { loading: false, canAccessEndpointManagement: false },
+ endpointPrivileges: { loading: false, canWriteEventFilters: false },
});
wrapper = mount(
@@ -346,9 +350,7 @@ describe('take action dropdown', () => {
);
wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click');
await waitFor(() => {
- expect(
- wrapper.find('[data-test-subj="add-event-filter-menu-item"]').first().getDOMNode()
- ).toBeDisabled();
+ expect(wrapper.exists('[data-test-subj="add-event-filter-menu-item"]')).toBeFalsy();
});
});
@@ -473,10 +475,10 @@ describe('take action dropdown', () => {
});
});
- it('should not display the button if user is not allowed to manage endpoints', async () => {
+ it('should not display the button if user is not allowed to write event filters', async () => {
(useUserPrivileges as jest.Mock).mockReturnValue({
...mockInitialUserPrivilegesState(),
- endpointPrivileges: { loading: false, canAccessEndpointManagement: false },
+ endpointPrivileges: { loading: false, canWriteEventFilters: false },
});
render();
diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx
index 059a1c0c4b64f..c5f33d34b1997 100644
--- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx
@@ -75,12 +75,12 @@ export const TakeActionDropdown = React.memo(
scopeId,
}: TakeActionDropdownProps) => {
const tGridEnabled = useIsExperimentalFeatureEnabled('tGridEnabled');
- const { loading: canAccessEndpointManagementLoading, canAccessEndpointManagement } =
+ const { loading: endpointPrivilegesLoading, canWriteEventFilters } =
useUserPrivileges().endpointPrivileges;
const canCreateEndpointEventFilters = useMemo(
- () => !canAccessEndpointManagementLoading && canAccessEndpointManagement,
- [canAccessEndpointManagement, canAccessEndpointManagementLoading]
+ () => !endpointPrivilegesLoading && canWriteEventFilters,
+ [canWriteEventFilters, endpointPrivilegesLoading]
);
const { osquery } = useKibana().services;
@@ -168,7 +168,6 @@ export const TakeActionDropdown = React.memo(
const { eventFilterActionItems } = useEventFilterAction({
onAddEventFilterClick: handleOnAddEventFilterClick,
- disabled: !isEndpointEvent || !canCreateEndpointEventFilters,
});
const onMenuItemClick = useCallback(() => {
@@ -210,12 +209,13 @@ export const TakeActionDropdown = React.memo(
() =>
!isEvent && actionsData.ruleId
? [...statusActionItems, ...exceptionActionItems]
- : isEndpointEvent
+ : isEndpointEvent && canCreateEndpointEventFilters
? eventFilterActionItems
: [],
[
eventFilterActionItems,
isEndpointEvent,
+ canCreateEndpointEventFilters,
exceptionActionItems,
statusActionItems,
isEvent,
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx
index e34227f0bfe8f..dce89dc199d9e 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.test.tsx
@@ -19,8 +19,11 @@ import {
GuidedOnboardingTourStep,
SecurityTourStep,
} from '../../../../../common/components/guided_onboarding_tour/tour_step';
+import { initialUserPrivilegesState as mockInitialUserPrivilegesState } from '../../../../../common/components/user_privileges/user_privileges_context';
+import { useUserPrivileges } from '../../../../../common/components/user_privileges';
import { SecurityStepId } from '../../../../../common/components/guided_onboarding_tour/tour_config';
+jest.mock('../../../../../common/components/user_privileges');
jest.mock('../../../../../common/components/guided_onboarding_tour');
jest.mock('../../../../../detections/components/user_info', () => ({
useUserData: jest.fn().mockReturnValue([{ canUserCRUD: true, hasIndexWrite: true }]),
@@ -268,6 +271,12 @@ describe('Actions', () => {
});
describe('Alert context menu enabled?', () => {
+ beforeEach(() => {
+ (useUserPrivileges as jest.Mock).mockReturnValue({
+ ...mockInitialUserPrivilegesState(),
+ endpointPrivileges: { loading: false, canWriteEventFilters: true },
+ });
+ });
test('it disables for eventType=raw', () => {
const wrapper = mount(