Skip to content

Commit

Permalink
[8.14] [Security Solution] Timeline : Disabling Timeline ESQL feature…
Browse files Browse the repository at this point in the history
… flag should disable ESQL Tab. (#182816) (#182905)

# Backport

This will backport the following commits from `main` to `8.14`:
- [[Security Solution] Timeline : Disabling Timeline ESQL feature flag
should disable ESQL Tab.
(#182816)](#182816)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Jatin
Kathuria","email":"jatin.kathuria@elastic.co"},"sourceCommit":{"committedDate":"2024-05-08T06:21:30Z","message":"[Security
Solution] Timeline : Disabling Timeline ESQL feature flag should disable
ESQL Tab. (#182816)\n\n## Summary\r\n\r\nhandles
https://github.com/elastic/kibana/issues/182798\r\n\r\nRecently there
was PR : https://github.com/elastic/kibana/pull/181616\r\nwhich does not
disable ES|QL tab in timeline even if feature flag is\r\ndisabled when
:\r\n- User has already created a ESQL Query in timeline and saved
the\r\ntimeline.\r\n\r\nThis PR makes sure when below feature flag
exists, then `ES|QL` tab will\r\nbe definitely disabled even when user
has a saved timeline with ES|QL\r\nQuery in
it.\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n -
timelineEsqlTabDisabled\r\n\r\n```\r\n\r\n## Desk Testing
Guidelines\r\n\r\n1. Remove above Feature Flag\r\n2. Go to Timeline and
Create a Timeline with ESQL Query\r\n3. Save the timeline.\r\n4. Go To
advanced Settings and search for `esql` and disable the\r\n`enableESQL`
setting.\r\n5. Go back to the timeline saved in step 3. \r\n6. ✅ Assert
that the `ES|QL` tab is still there.\r\n7. ✅ Assert that the `ES|QL` tab
is NOT there in a new timeline.\r\n8. Add above feature flag - which
disables the esql Tab.\r\n9. Go back to the timeline saved in step
3.\r\n10. ✅ Assert that the `ES|QL` tab is no longer there.\r\n11. ✅
Assert that the `ES|QL` tab is NOT there in a new
timeline.\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"c43da3e4349a6bb13cdab507530efd926147c30b","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:Threat
Hunting:Investigations","backport:prev-minor","v8.14.0","v8.15.0"],"title":"[Security
Solution] Timeline : Disabling Timeline ESQL feature flag should disable
ESQL Tab.
","number":182816,"url":"https://github.com/elastic/kibana/pull/182816","mergeCommit":{"message":"[Security
Solution] Timeline : Disabling Timeline ESQL feature flag should disable
ESQL Tab. (#182816)\n\n## Summary\r\n\r\nhandles
https://github.com/elastic/kibana/issues/182798\r\n\r\nRecently there
was PR : https://github.com/elastic/kibana/pull/181616\r\nwhich does not
disable ES|QL tab in timeline even if feature flag is\r\ndisabled when
:\r\n- User has already created a ESQL Query in timeline and saved
the\r\ntimeline.\r\n\r\nThis PR makes sure when below feature flag
exists, then `ES|QL` tab will\r\nbe definitely disabled even when user
has a saved timeline with ES|QL\r\nQuery in
it.\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n -
timelineEsqlTabDisabled\r\n\r\n```\r\n\r\n## Desk Testing
Guidelines\r\n\r\n1. Remove above Feature Flag\r\n2. Go to Timeline and
Create a Timeline with ESQL Query\r\n3. Save the timeline.\r\n4. Go To
advanced Settings and search for `esql` and disable the\r\n`enableESQL`
setting.\r\n5. Go back to the timeline saved in step 3. \r\n6. ✅ Assert
that the `ES|QL` tab is still there.\r\n7. ✅ Assert that the `ES|QL` tab
is NOT there in a new timeline.\r\n8. Add above feature flag - which
disables the esql Tab.\r\n9. Go back to the timeline saved in step
3.\r\n10. ✅ Assert that the `ES|QL` tab is no longer there.\r\n11. ✅
Assert that the `ES|QL` tab is NOT there in a new
timeline.\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"c43da3e4349a6bb13cdab507530efd926147c30b"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","branchLabelMappingKey":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/182816","number":182816,"mergeCommit":{"message":"[Security
Solution] Timeline : Disabling Timeline ESQL feature flag should disable
ESQL Tab. (#182816)\n\n## Summary\r\n\r\nhandles
https://github.com/elastic/kibana/issues/182798\r\n\r\nRecently there
was PR : https://github.com/elastic/kibana/pull/181616\r\nwhich does not
disable ES|QL tab in timeline even if feature flag is\r\ndisabled when
:\r\n- User has already created a ESQL Query in timeline and saved
the\r\ntimeline.\r\n\r\nThis PR makes sure when below feature flag
exists, then `ES|QL` tab will\r\nbe definitely disabled even when user
has a saved timeline with ES|QL\r\nQuery in
it.\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n -
timelineEsqlTabDisabled\r\n\r\n```\r\n\r\n## Desk Testing
Guidelines\r\n\r\n1. Remove above Feature Flag\r\n2. Go to Timeline and
Create a Timeline with ESQL Query\r\n3. Save the timeline.\r\n4. Go To
advanced Settings and search for `esql` and disable the\r\n`enableESQL`
setting.\r\n5. Go back to the timeline saved in step 3. \r\n6. ✅ Assert
that the `ES|QL` tab is still there.\r\n7. ✅ Assert that the `ES|QL` tab
is NOT there in a new timeline.\r\n8. Add above feature flag - which
disables the esql Tab.\r\n9. Go back to the timeline saved in step
3.\r\n10. ✅ Assert that the `ES|QL` tab is no longer there.\r\n11. ✅
Assert that the `ES|QL` tab is NOT there in a new
timeline.\r\n\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"c43da3e4349a6bb13cdab507530efd926147c30b"}}]}]
BACKPORT-->

Co-authored-by: Jatin Kathuria <jatin.kathuria@elastic.co>
  • Loading branch information
kibanamachine and logeekal authored May 8, 2024
1 parent f7234b4 commit e5f3983
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ import { useIsExperimentalFeatureEnabled } from '../use_experimental_features';
export const useEsqlAvailability = () => {
const { uiSettings } = useKibana().services;
const isEsqlAdvancedSettingEnabled = uiSettings?.get(ENABLE_ESQL);

const isTimelineEsqlFeatureFlagDisabled =
useIsExperimentalFeatureEnabled('timelineEsqlTabDisabled');

const isEsqlRuleTypeEnabled =
!useIsExperimentalFeatureEnabled('esqlRulesDisabled') && isEsqlAdvancedSettingEnabled;
const isESQLTabInTimelineEnabled =
!useIsExperimentalFeatureEnabled('timelineEsqlTabDisabled') && isEsqlAdvancedSettingEnabled;

return useMemo(
() => ({
isEsqlAdvancedSettingEnabled,
isEsqlRuleTypeEnabled,
isESQLTabInTimelineEnabled,
isTimelineEsqlEnabledByFeatureFlag: !isTimelineEsqlFeatureFlagDisabled,
}),
[isESQLTabInTimelineEnabled, isEsqlAdvancedSettingEnabled, isEsqlRuleTypeEnabled]
[isEsqlAdvancedSettingEnabled, isTimelineEsqlFeatureFlagDisabled, isEsqlRuleTypeEnabled]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { render, screen, waitFor } from '@testing-library/react';

jest.mock('../../../../common/hooks/esql/use_esql_availability', () => ({
useEsqlAvailability: jest.fn().mockReturnValue({
isESQLTabInTimelineEnabled: true,
isEsqlAdvancedSettingEnabled: true,
isTimelineEsqlEnabledByFeatureFlag: true,
}),
}));

Expand All @@ -44,38 +45,79 @@ describe('Timeline', () => {
expect(screen.getByTestId(esqlTabSubj)).toBeVisible();
});

it('should not show the esql tab when the advanced setting is disabled', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isESQLTabInTimelineEnabled: false,
describe('no existing esql query is present', () => {
it('should not show the esql tab when the advanced setting is disabled', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isEsqlAdvancedSettingEnabled: false,
isTimelineEsqlEnabledByFeatureFlag: true,
});
render(
<TestProviders>
<TabsContent {...defaultProps} />
</TestProviders>
);

await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeNull();
});
});
render(
<TestProviders>
<TabsContent {...defaultProps} />
</TestProviders>
);
it('should not show the esql tab when the esql is disabled by feature flag', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isEsqlAdvancedSettingEnabled: false,
isTimelineEsqlEnabledByFeatureFlag: false,
});
render(
<TestProviders>
<TabsContent {...defaultProps} />
</TestProviders>
);

await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeNull();
await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeNull();
});
});
});

it('should show the esql tab when the advanced setting is disabled, but an esql query is present', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isESQLTabInTimelineEnabled: false,
describe('existing esql query is present', () => {
let mockStore: ReturnType<typeof createMockStore>;
beforeEach(() => {
const stateWithSavedSearchId = structuredClone(mockGlobalState);
stateWithSavedSearchId.timeline.timelineById[TimelineId.test].savedSearchId = 'test-id';
mockStore = createMockStore(stateWithSavedSearchId);
});

const stateWithSavedSearchId = structuredClone(mockGlobalState);
stateWithSavedSearchId.timeline.timelineById[TimelineId.test].savedSearchId = 'test-id';
const mockStore = createMockStore(stateWithSavedSearchId);
it('should show the esql tab when the advanced setting is disabled', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isESQLTabInTimelineEnabled: false,
isTimelineEsqlEnabledByFeatureFlag: true,
});

render(
<TestProviders store={mockStore}>
<TabsContent {...defaultProps} />
</TestProviders>
);
render(
<TestProviders store={mockStore}>
<TabsContent {...defaultProps} />
</TestProviders>
);

await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeVisible();
});
});

it('should not show the esql tab when the esql is disabled by the feature flag', async () => {
useEsqlAvailabilityMock.mockReturnValue({
isESQLTabInTimelineEnabled: true,
isTimelineEsqlEnabledByFeatureFlag: false,
});

render(
<TestProviders store={mockStore}>
<TabsContent {...defaultProps} />
</TestProviders>
);

await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeVisible();
await waitFor(() => {
expect(screen.queryByTestId(esqlTabSubj)).toBeNull();
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,20 @@ const ActiveTimelineTab = memo<ActiveTimelineTabProps>(
showTimeline,
}) => {
const { hasAssistantPrivilege } = useAssistantAvailability();
const { isESQLTabInTimelineEnabled } = useEsqlAvailability();
const { isTimelineEsqlEnabledByFeatureFlag, isEsqlAdvancedSettingEnabled } =
useEsqlAvailability();
const timelineESQLSavedSearch = useShallowEqualSelector((state) =>
selectTimelineESQLSavedSearchId(state, timelineId)
);
const shouldShowESQLTab = isESQLTabInTimelineEnabled || timelineESQLSavedSearch != null;
const shouldShowESQLTab = useMemo(() => {
// disabling esql feature from feature flag should unequivocally hide the tab
// irrespective of the fact that the advanced setting is enabled or
// not or existing esql query is present or not
if (!isTimelineEsqlEnabledByFeatureFlag) {
return false;
}
return isEsqlAdvancedSettingEnabled || timelineESQLSavedSearch != null;
}, [isEsqlAdvancedSettingEnabled, isTimelineEsqlEnabledByFeatureFlag, timelineESQLSavedSearch]);
const aiAssistantFlyoutMode = useIsExperimentalFeatureEnabled('aiAssistantFlyoutMode');
const getTab = useCallback(
(tab: TimelineTabs) => {
Expand Down Expand Up @@ -271,14 +280,24 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
const getAppNotes = useMemo(() => getNotesSelector(), []);
const getTimelineNoteIds = useMemo(() => getNoteIdsSelector(), []);
const getTimelinePinnedEventNotes = useMemo(() => getEventIdToNoteIdsSelector(), []);
const { isESQLTabInTimelineEnabled } = useEsqlAvailability();
const { isEsqlAdvancedSettingEnabled, isTimelineEsqlEnabledByFeatureFlag } =
useEsqlAvailability();

const timelineESQLSavedSearch = useShallowEqualSelector((state) =>
selectTimelineESQLSavedSearchId(state, timelineId)
);

const activeTab = useShallowEqualSelector((state) => getActiveTab(state, timelineId));
const showTimeline = useShallowEqualSelector((state) => getShowTimeline(state, timelineId));
const shouldShowESQLTab = isESQLTabInTimelineEnabled || timelineESQLSavedSearch != null;
const shouldShowESQLTab = useMemo(() => {
// disabling esql feature from feature flag should unequivocally hide the tab
// irrespective of the fact that the advanced setting is enabled or
// not or existing esql query is present or not
if (!isTimelineEsqlEnabledByFeatureFlag) {
return false;
}
return isEsqlAdvancedSettingEnabled || timelineESQLSavedSearch != null;
}, [isEsqlAdvancedSettingEnabled, isTimelineEsqlEnabledByFeatureFlag, timelineESQLSavedSearch]);

const numberOfPinnedEvents = useShallowEqualSelector((state) =>
getNumberOfPinnedEvents(state, timelineId)
Expand Down

0 comments on commit e5f3983

Please sign in to comment.