Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
* 2.0.
*/

import { HttpStart } from 'kibana/public';
import { Dispatch } from 'redux';
import { CoreStart, HttpStart } from 'kibana/public';
import {
EndpointAction,
HostInfo,
HostIsolationRequestBody,
HostIsolationResponse,
HostResultList,
Immutable,
ImmutableObject,
} from '../../../../../common/endpoint/types';
import { GetPolicyListResponse } from '../../policy/types';
import { ImmutableMiddlewareAPI, ImmutableMiddlewareFactory } from '../../../../common/store';
Expand Down Expand Up @@ -54,6 +56,7 @@ import {
import { isolateHost, unIsolateHost } from '../../../../common/lib/host_isolation';
import { AppAction } from '../../../../common/store/actions';
import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables';
import { ServerReturnedEndpointPackageInfo } from './action';

type EndpointPageStore = ImmutableMiddlewareAPI<EndpointState, AppAction>;

Expand All @@ -78,26 +81,14 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState

const { getState, dispatch } = store;

await getEndpointPackageInfo(getState(), dispatch, coreStart);

// Endpoint list
if (
(action.type === 'userChangedUrl' || action.type === 'appRequestedEndpointList') &&
isOnEndpointPage(getState()) &&
hasSelectedEndpoint(getState()) !== true
) {
if (!endpointPackageInfo(getState())) {
try {
const packageInfo = await sendGetEndpointSecurityPackage(coreStart.http);
dispatch({
type: 'serverReturnedEndpointPackageInfo',
payload: packageInfo,
});
} catch (error) {
// Ignore Errors, since this should not hinder the user's ability to use the UI
// eslint-disable-next-line no-console
console.error(error);
}
}

const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(getState());
let endpointResponse;

Expand Down Expand Up @@ -523,3 +514,23 @@ const handleIsolateEndpointHost = async (
});
}
};

async function getEndpointPackageInfo(
state: ImmutableObject<EndpointState>,
dispatch: Dispatch<ServerReturnedEndpointPackageInfo>,
coreStart: CoreStart
) {
if (endpointPackageInfo(state)) return;

try {
const packageInfo = await sendGetEndpointSecurityPackage(coreStart.http);
dispatch({
type: 'serverReturnedEndpointPackageInfo',
payload: packageInfo,
});
} catch (error) {
// Ignore Errors, since this should not hinder the user's ability to use the UI
// eslint-disable-next-line no-console
console.error(error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('Policy Details', () => {
describe('when displayed with invalid id', () => {
let releaseApiFailure: () => void;
beforeEach(() => {
http.get.mockImplementationOnce(async () => {
http.get.mockImplementation(async () => {
await new Promise((_, reject) => {
releaseApiFailure = reject.bind(null, new Error('policy not found'));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,18 +633,21 @@ describe('When on the Trusted Apps Page', () => {
});
});

it('should close the flyout', async () => {
it('should close the flyout', () => {
expect(renderResult.queryByTestId('addTrustedAppFlyout')).toBeNull();
});

it('should show success toast notification', async () => {
it('should show success toast notification', () => {
expect(coreStart.notifications.toasts.addSuccess.mock.calls[0][0]).toEqual(
'"one app" has been added to the Trusted Applications list.'
);
});

it('should trigger the List to reload', async () => {
expect(coreStart.http.get.mock.calls[0][0]).toEqual(TRUSTED_APPS_LIST_API);
it('should trigger the List to reload', () => {
const isCalled = coreStart.http.get.mock.calls.some(
(call) => call[0].toString() === TRUSTED_APPS_LIST_API
);
expect(isCalled).toEqual(true);
});
});

Expand All @@ -666,18 +669,18 @@ describe('When on the Trusted Apps Page', () => {
});
});

it('should continue to show the flyout', async () => {
it('should continue to show the flyout', () => {
expect(renderResult.getByTestId('addTrustedAppFlyout')).not.toBeNull();
});

it('should enable the Cancel Button', async () => {
it('should enable the Cancel Button', () => {
expect(
(renderResult.getByTestId('addTrustedAppFlyout-cancelButton') as HTMLButtonElement)
.disabled
).toBe(false);
});

it('should show the dialog close button', async () => {
it('should show the dialog close button', () => {
expect(renderResult.getByTestId('euiFlyoutCloseButton')).not.toBeNull();
});

Expand All @@ -688,7 +691,7 @@ describe('When on the Trusted Apps Page', () => {
).toBe(false);
});

it('should show API errors in the form', async () => {
it('should show API errors in the form', () => {
expect(renderResult.container.querySelector('.euiForm__errors')).not.toBeNull();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { OverviewEmpty } from '.';
import { useIngestEnabledCheck } from '../../../common/hooks/endpoint/ingest_enabled';

const endpointPackageVersion = '0.19.1';

jest.mock('../../../common/lib/kibana');
jest.mock('../../../management/pages/endpoint_hosts/view/hooks', () => ({
useIngestUrl: jest
.fn()
.mockReturnValue({ appId: 'ingestAppId', appPath: 'ingestPath', url: 'ingestUrl' }),
useEndpointSelector: jest.fn().mockReturnValue({ endpointPackageVersion }),
}));

jest.mock('../../../common/hooks/endpoint/ingest_enabled', () => ({
Expand Down Expand Up @@ -57,7 +61,7 @@ describe('OverviewEmpty', () => {
fill: false,
label: 'Add Endpoint Security',
onClick: undefined,
url: '/app/home#/tutorial_directory/security',
url: `#/integrations/endpoint-${endpointPackageVersion}/add-integration`,
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,41 @@

import React, { useMemo } from 'react';
import { omit } from 'lodash/fp';
import { createStructuredSelector } from 'reselect';

import { FormattedMessage } from '@kbn/i18n/react';
import { EuiLink } from '@elastic/eui';
import * as i18nCommon from '../../../common/translations';
import { EmptyPage, EmptyPageActionsProps } from '../../../common/components/empty_page';
import { useKibana } from '../../../common/lib/kibana';
import { ADD_DATA_PATH } from '../../../../common/constants';
import { useIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks';
import {
useEndpointSelector,
useIngestUrl,
} from '../../../management/pages/endpoint_hosts/view/hooks';
import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { useIngestEnabledCheck } from '../../../common/hooks/endpoint/ingest_enabled';
import { CreateStructuredSelector } from '../../../common/store';
import { endpointPackageVersion as useEndpointPackageVersion } from '../../../management/pages/endpoint_hosts/store/selectors';

const OverviewEmptyComponent: React.FC = () => {
const { http, docLinks } = useKibana().services;
const basePath = http.basePath.get();
const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useIngestUrl(
'integrations?category=security'
);
const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath });
const selector = (createStructuredSelector as CreateStructuredSelector)({
endpointPackageVersion: useEndpointPackageVersion,
});
const { endpointPackageVersion } = useEndpointSelector(selector);
const { url: ingestUrl } = useIngestUrl('');

const endpointIntegrationUrlPath = endpointPackageVersion
? `/endpoint-${endpointPackageVersion}/add-integration`
: '';
const endpointIntegrationUrl = `#/integrations${endpointIntegrationUrlPath}`;
const handleEndpointClick = useNavigateToAppEventHandler('fleet', {
path: endpointIntegrationUrl,
});
const { allEnabled: isIngestEnabled } = useIngestEnabledCheck();

const emptyPageActions: EmptyPageActionsProps = useMemo(
() => ({
elasticAgent: {
Expand All @@ -42,13 +58,13 @@ const OverviewEmptyComponent: React.FC = () => {
},
endpoint: {
label: i18nCommon.EMPTY_ACTION_ENDPOINT,
url: `${basePath}${ADD_DATA_PATH}`,
url: endpointIntegrationUrl,
description: i18nCommon.EMPTY_ACTION_ENDPOINT_DESCRIPTION,
onClick: handleOnClick,
onClick: handleEndpointClick,
fill: false,
},
}),
[basePath, ingestUrl, handleOnClick]
[basePath, ingestUrl, endpointIntegrationUrl, handleEndpointClick]
);

const emptyPageIngestDisabledActions = useMemo(
Expand Down