Prevalence details paywall (#165435)

This commit is contained in:
Philippe Oberti 2023-09-28 12:35:40 -05:00 committed by GitHub
parent 4221e79ff9
commit d4defbd980
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 12 deletions

View file

@ -18,6 +18,7 @@ import {
PREVALENCE_DETAILS_UPSELL_TEST_ID, PREVALENCE_DETAILS_UPSELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID, PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID, PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID,
} from './test_ids'; } from './test_ids';
import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { usePrevalence } from '../../shared/hooks/use_prevalence';
import { TestProviders } from '../../../common/mock'; import { TestProviders } from '../../../common/mock';
@ -54,6 +55,8 @@ const panelContextValue = {
dataFormattedForFieldBrowser: [], dataFormattedForFieldBrowser: [],
} as unknown as LeftPanelContext; } as unknown as LeftPanelContext;
const UPSELL_MESSAGE = 'Host and user prevalence are only available with a';
const renderPrevalenceDetails = () => const renderPrevalenceDetails = () =>
render( render(
<TestProviders> <TestProviders>
@ -70,7 +73,7 @@ describe('PrevalenceDetails', () => {
licenseServiceMock.isPlatinumPlus.mockReturnValue(true); licenseServiceMock.isPlatinumPlus.mockReturnValue(true);
}); });
it('should render the table with all columns if license is platinum', () => { it('should render the table with all data if license is platinum', () => {
const field1 = 'field1'; const field1 = 'field1';
const field2 = 'field2'; const field2 = 'field2';
(usePrevalence as jest.Mock).mockReturnValue({ (usePrevalence as jest.Mock).mockReturnValue({
@ -117,6 +120,38 @@ describe('PrevalenceDetails', () => {
expect(queryByText(NO_DATA_MESSAGE)).not.toBeInTheDocument(); expect(queryByText(NO_DATA_MESSAGE)).not.toBeInTheDocument();
}); });
it('should hide data in prevalence columns if license is not platinum', () => {
const field1 = 'field1';
licenseServiceMock.isPlatinumPlus.mockReturnValue(false);
(usePrevalence as jest.Mock).mockReturnValue({
loading: false,
error: false,
data: [
{
field: field1,
values: ['value1'],
alertCount: 1,
docCount: 1,
hostPrevalence: 0.05,
userPrevalence: 0.1,
},
],
});
const { getByTestId, getAllByTestId } = renderPrevalenceDetails();
expect(getByTestId(PREVALENCE_DETAILS_TABLE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(PREVALENCE_DETAILS_UPSELL_TEST_ID)).toHaveTextContent(UPSELL_MESSAGE);
expect(getAllByTestId(PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID).length).toEqual(2);
expect(
getByTestId(PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID)
).not.toHaveTextContent('5%');
expect(
getByTestId(PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID)
).not.toHaveTextContent('10%');
});
it('should render formatted numbers for the alert and document count columns', () => { it('should render formatted numbers for the alert and document count columns', () => {
(usePrevalence as jest.Mock).mockReturnValue({ (usePrevalence as jest.Mock).mockReturnValue({
loading: false, loading: false,

View file

@ -19,6 +19,7 @@ import {
EuiSuperDatePicker, EuiSuperDatePicker,
EuiText, EuiText,
EuiToolTip, EuiToolTip,
useEuiTheme,
} from '@elastic/eui'; } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react'; import { FormattedMessage } from '@kbn/i18n-react';
import { FormattedCount } from '../../../common/components/formatted_number'; import { FormattedCount } from '../../../common/components/formatted_number';
@ -36,6 +37,7 @@ import {
PREVALENCE_DETAILS_DATE_PICKER_TEST_ID, PREVALENCE_DETAILS_DATE_PICKER_TEST_ID,
PREVALENCE_DETAILS_TABLE_TEST_ID, PREVALENCE_DETAILS_TABLE_TEST_ID,
PREVALENCE_DETAILS_UPSELL_TEST_ID, PREVALENCE_DETAILS_UPSELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID,
} from './test_ids'; } from './test_ids';
import { useLeftPanelContext } from '../context'; import { useLeftPanelContext } from '../context';
import { import {
@ -49,6 +51,19 @@ export const PREVALENCE_TAB_ID = 'prevalence-details';
const DEFAULT_FROM = 'now-30d'; const DEFAULT_FROM = 'now-30d';
const DEFAULT_TO = 'now'; const DEFAULT_TO = 'now';
/**
* Component that renders a grey box to indicate the user doesn't have proper license to view the actual data
*/
export const LicenseProtectedCell: React.FC = () => {
const { euiTheme } = useEuiTheme();
return (
<div
data-test-subj={PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID}
style={{ height: '16px', width: '100%', background: euiTheme.colors.lightShade }}
/>
);
};
interface PrevalenceDetailsRow extends PrevalenceData { interface PrevalenceDetailsRow extends PrevalenceData {
/** /**
* From datetime selected in the date picker to pass to timeline * From datetime selected in the date picker to pass to timeline
@ -58,6 +73,10 @@ interface PrevalenceDetailsRow extends PrevalenceData {
* To datetime selected in the date picker to pass to timeline * To datetime selected in the date picker to pass to timeline
*/ */
to: string; to: string;
/**
* License to drive the rendering of the last 2 prevalence columns
*/
isPlatinumPlus: boolean;
} }
const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
@ -196,7 +215,6 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
width: '10%', width: '10%',
}, },
{ {
field: 'hostPrevalence',
name: ( name: (
<EuiToolTip <EuiToolTip
content={ content={
@ -223,13 +241,18 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
</EuiToolTip> </EuiToolTip>
), ),
'data-test-subj': PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID, 'data-test-subj': PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID,
render: (hostPrevalence: number) => ( render: (data: PrevalenceDetailsRow) => (
<EuiText size="xs">{`${Math.round(hostPrevalence * 100)}%`}</EuiText> <>
{data.isPlatinumPlus ? (
<EuiText size="xs">{`${Math.round(data.hostPrevalence * 100)}%`}</EuiText>
) : (
<LicenseProtectedCell />
)}
</>
), ),
width: '10%', width: '10%',
}, },
{ {
field: 'userPrevalence',
name: ( name: (
<EuiToolTip <EuiToolTip
content={ content={
@ -256,8 +279,14 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
</EuiToolTip> </EuiToolTip>
), ),
'data-test-subj': PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID, 'data-test-subj': PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID,
render: (userPrevalence: number) => ( render: (data: PrevalenceDetailsRow) => (
<EuiText size="xs">{`${Math.round(userPrevalence * 100)}%`}</EuiText> <>
{data.isPlatinumPlus ? (
<EuiText size="xs">{`${Math.round(data.userPrevalence * 100)}%`}</EuiText>
) : (
<LicenseProtectedCell />
)}
</>
), ),
width: '10%', width: '10%',
}, },
@ -312,10 +341,10 @@ export const PrevalenceDetails: React.FC = () => {
}, },
}); });
// add timeRange to pass it down to timeline // add timeRange to pass it down to timeline and license to drive the rendering of the last 2 prevalence columns
const items = useMemo( const items = useMemo(
() => data.map((item) => ({ ...item, from: absoluteStart, to: absoluteEnd })), () => data.map((item) => ({ ...item, from: absoluteStart, to: absoluteEnd, isPlatinumPlus })),
[data, absoluteStart, absoluteEnd] [data, absoluteStart, absoluteEnd, isPlatinumPlus]
); );
const upsell = ( const upsell = (
@ -323,13 +352,13 @@ export const PrevalenceDetails: React.FC = () => {
<EuiCallOut data-test-subj={PREVALENCE_DETAILS_UPSELL_TEST_ID}> <EuiCallOut data-test-subj={PREVALENCE_DETAILS_UPSELL_TEST_ID}>
<FormattedMessage <FormattedMessage
id="xpack.securitySolution.flyout.left.insights.prevalence.tableAlertUpsellDescription" id="xpack.securitySolution.flyout.left.insights.prevalence.tableAlertUpsellDescription"
defaultMessage="Preview of a {subscription} feature showing host and user prevalence." defaultMessage="Host and user prevalence are only available with a {subscription}."
values={{ values={{
subscription: ( subscription: (
<EuiLink href="https://www.elastic.co/pricing/" target="_blank"> <EuiLink href="https://www.elastic.co/pricing/" target="_blank">
<FormattedMessage <FormattedMessage
id="xpack.securitySolution.flyout.left.insights.prevalence.tableAlertUpsellLinkText" id="xpack.securitySolution.flyout.left.insights.prevalence.tableAlertUpsellLinkText"
defaultMessage="Platinum" defaultMessage="Platinum or higher subscription"
/> />
</EuiLink> </EuiLink>
), ),

View file

@ -34,6 +34,8 @@ export const PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID =
`${PREVALENCE_DETAILS_TABLE_TEST_ID}HostPrevalenceCell` as const; `${PREVALENCE_DETAILS_TABLE_TEST_ID}HostPrevalenceCell` as const;
export const PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID = export const PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID =
`${PREVALENCE_DETAILS_TABLE_TEST_ID}UserPrevalenceCell` as const; `${PREVALENCE_DETAILS_TABLE_TEST_ID}UserPrevalenceCell` as const;
export const PREVALENCE_DETAILS_TABLE_UPSELL_CELL_TEST_ID =
`${PREVALENCE_DETAILS_TABLE_TEST_ID}UpsellCell` as const;
/* Entities */ /* Entities */