Skip to content

Commit

Permalink
[Security Solutions] Hide User flyout managed data section behind flag (
Browse files Browse the repository at this point in the history
#174753)

## Summary
Hide User flyout managed data section behind an experimental flag
(`newUserDetailsFlyoutManagedUser`)

<img width="300"
src="https://github.com/elastic/kibana/assets/1490444/dd409cad-fcfe-4f53-a122-e6b7c293de4e"/>

### How to test it?
* Open security solutions app and ingest data
* Create alerts
* Enable risk engine
* Go to the Alerts page and click on the user name cell
* The sections should **not** show
* Enable the flag and follow the same steps to see the section


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
machadoum authored Jan 15, 2024
1 parent 9aa310e commit 02fa843
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ export const allowedExperimentalValues = Object.freeze({
**/
newUserDetailsFlyout: false,

/*
* Enables the Managed User section inside the new user details flyout.
* To see this section you also need newUserDetailsFlyout flag enabled.
*
**/
newUserDetailsFlyoutManagedUser: false,

/*
* Enables the new host details flyout displayed on the Alerts table.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ describe('useInstalledIntegrations', () => {
return wrapper;
};

const render = () =>
const render = ({ skip } = { skip: false }) =>
renderHook(
() =>
useInstalledIntegrations({
packages: [],
skip,
}),
{
wrapper: createReactQueryWrapper(),
Expand All @@ -68,6 +69,17 @@ describe('useInstalledIntegrations', () => {
);
});

it('does not call the API when skip is true', async () => {
const fetchInstalledIntegrations = jest.spyOn(
fleetIntegrationsApi,
'fetchInstalledIntegrations'
);

render({ skip: true });

expect(fetchInstalledIntegrations).toHaveBeenCalledTimes(0);
});

it('fetches data from the API', async () => {
const { result, waitForNextUpdate } = render();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ const ONE_MINUTE = 60000;

export interface UseInstalledIntegrationsArgs {
packages?: string[];
skip?: boolean;
}

export const useInstalledIntegrations = ({ packages }: UseInstalledIntegrationsArgs) => {
export const useInstalledIntegrations = ({
packages,
skip = false,
}: UseInstalledIntegrationsArgs) => {
// const { addError } = useAppToasts();

return useQuery<InstalledIntegrationArray>(
Expand All @@ -38,6 +42,7 @@ export const useInstalledIntegrations = ({ packages }: UseInstalledIntegrationsA
{
keepPreviousData: true,
staleTime: ONE_MINUTE * 5,
enabled: !skip,
onError: (e) => {
// Suppressing for now to prevent excessive errors when fleet isn't configured
// addError(e, { title: i18n.INTEGRATIONS_FETCH_FAILURE });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { EuiHorizontalRule } from '@elastic/eui';

import React from 'react';
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
import { AssetCriticalitySelector } from '../../../entity_analytics/components/asset_criticality/asset_criticality_selector';

import { OBSERVED_USER_QUERY_ID } from '../../../explore/users/containers/users/observed_details';
Expand Down Expand Up @@ -45,6 +46,7 @@ export const UserPanelContent = ({
openDetailsPanel,
}: UserPanelContentProps) => {
const observedFields = useObservedUserItems(observedUser);
const isManagedUserEnable = useIsExperimentalFeatureEnabled('newUserDetailsFlyoutManagedUser');

return (
<FlyoutBody>
Expand All @@ -68,12 +70,14 @@ export const UserPanelContent = ({
queryId={OBSERVED_USER_QUERY_ID}
/>
<EuiHorizontalRule margin="m" />
<ManagedUser
managedUser={managedUser}
contextID={contextID}
isDraggable={isDraggable}
openDetailsPanel={openDetailsPanel}
/>
{isManagedUserEnable && (
<ManagedUser
managedUser={managedUser}
contextID={contextID}
isDraggable={isDraggable}
openDetailsPanel={openDetailsPanel}
/>
)}
</FlyoutBody>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ jest.mock('./hooks/use_observed_user', () => ({
useObservedUser: () => mockedUseObservedUser(),
}));

const mockedUseIsExperimentalFeatureEnabled = jest.fn().mockReturnValue(true);
jest.mock('../../../common/hooks/use_experimental_features', () => ({
useIsExperimentalFeatureEnabled: () => mockedUseIsExperimentalFeatureEnabled(),
}));

describe('UserPanel', () => {
beforeEach(() => {
mockedUseRiskScore.mockReturnValue(mockRiskScoreState);
Expand Down Expand Up @@ -95,6 +100,18 @@ describe('UserPanel', () => {
expect(getByTestId('securitySolutionFlyoutLoading')).toBeInTheDocument();
});

it('does not render managed user when experimental flag is disabled', () => {
mockedUseIsExperimentalFeatureEnabled.mockReturnValue(false);

const { queryByTestId } = render(
<TestProviders>
<UserPanel {...mockProps} />
</TestProviders>
);

expect(queryByTestId('managedUser-accordion-button')).not.toBeInTheDocument();
});

it('renders loading state when managed user is loading', () => {
mockedUseManagedUser.mockReturnValue({
...mockManagedUserData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/

import { useEffect, useMemo } from 'react';

import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features';
import type { ManagedUserHits } from '../../../../../../common/search_strategy/security_solution/users/managed_details';
import { useInstalledIntegrations } from '../../../../../detections/components/rules/related_integrations/use_installed_integrations';
import { UsersQueries } from '../../../../../../common/search_strategy';
Expand Down Expand Up @@ -35,6 +37,7 @@ export const useManagedUser = (
email: string[] | undefined,
isLoading?: boolean
): ManagedUserData => {
const skip = useIsExperimentalFeatureEnabled('newUserDetailsFlyoutManagedUser');
const { to, from, isInitializing, deleteQuery, setQuery } = useGlobalTime();
const spaceId = useSpaceId();
const {
Expand All @@ -57,17 +60,18 @@ export const useManagedUser = (
);

useEffect(() => {
if (!isInitializing && defaultIndex.length > 0 && !isLoading && userName) {
if (!isInitializing && defaultIndex.length > 0 && !isLoading && userName && !skip) {
search({
defaultIndex,
userEmail: email,
userName,
});
}
}, [from, search, to, isInitializing, defaultIndex, userName, isLoading, email]);
}, [from, search, to, isInitializing, defaultIndex, userName, isLoading, email, skip]);

const { data: installedIntegrations, isLoading: loadingIntegrations } = useInstalledIntegrations({
packages,
skip,
});

useQueryInspector({
Expand Down

0 comments on commit 02fa843

Please sign in to comment.