diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index 24fccbbbfed0..b1921452354d 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -1,5 +1,50 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`TelemetryManagementSectionComponent does not show the endpoint link when isSecurityExampleEnabled returns false 1`] = ` + +

+ + + , + } + } + /> +

+

+ + + , + } + } + /> +

+
+`; + exports[`TelemetryManagementSectionComponent renders as expected 1`] = ` , "endpointSecurityData": { it('renders as expected', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -52,6 +53,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={true} enableSaving={true} + isSecurityExampleEnabled={isSecurityExampleEnabled} toasts={coreStart.notifications.toasts} /> ) @@ -60,6 +62,7 @@ describe('TelemetryManagementSectionComponent', () => { it('renders null because query does not match the SEARCH_TERMS', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -83,6 +86,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={false} enableSaving={true} + isSecurityExampleEnabled={isSecurityExampleEnabled} toasts={coreStart.notifications.toasts} /> @@ -98,6 +102,7 @@ describe('TelemetryManagementSectionComponent', () => { showAppliesSettingMessage={false} enableSaving={true} toasts={coreStart.notifications.toasts} + isSecurityExampleEnabled={isSecurityExampleEnabled} /> ); @@ -110,6 +115,7 @@ describe('TelemetryManagementSectionComponent', () => { it('renders because query matches the SEARCH_TERMS', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -131,6 +137,7 @@ describe('TelemetryManagementSectionComponent', () => { telemetryService={telemetryService} onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={false} + isSecurityExampleEnabled={isSecurityExampleEnabled} enableSaving={true} toasts={coreStart.notifications.toasts} /> @@ -155,6 +162,7 @@ describe('TelemetryManagementSectionComponent', () => { it('renders null because allowChangingOptInStatus is false', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -177,6 +185,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={true} enableSaving={true} + isSecurityExampleEnabled={isSecurityExampleEnabled} toasts={coreStart.notifications.toasts} /> ); @@ -191,6 +200,7 @@ describe('TelemetryManagementSectionComponent', () => { it('shows the OptInExampleFlyout', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -213,6 +223,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={false} enableSaving={true} + isSecurityExampleEnabled={isSecurityExampleEnabled} toasts={coreStart.notifications.toasts} /> ); @@ -228,6 +239,7 @@ describe('TelemetryManagementSectionComponent', () => { it('shows the OptInSecurityExampleFlyout', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -249,6 +261,7 @@ describe('TelemetryManagementSectionComponent', () => { telemetryService={telemetryService} onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={false} + isSecurityExampleEnabled={isSecurityExampleEnabled} enableSaving={true} toasts={coreStart.notifications.toasts} /> @@ -263,8 +276,48 @@ describe('TelemetryManagementSectionComponent', () => { } }); + it('does not show the endpoint link when isSecurityExampleEnabled returns false', () => { + const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(false); + const telemetryService = new TelemetryService({ + config: { + enabled: true, + url: '', + banner: true, + allowChangingOptInStatus: true, + optIn: false, + optInStatusUrl: '', + sendUsageFrom: 'browser', + }, + reportOptInStatusChange: false, + currentKibanaVersion: 'mock_kibana_version', + notifications: coreStart.notifications, + http: coreSetup.http, + }); + + const component = mountWithIntl( + + ); + + try { + const description = (component.instance() as TelemetryManagementSection).renderDescription(); + expect(isSecurityExampleEnabled).toBeCalled(); + expect(description).toMatchSnapshot(); + } finally { + component.unmount(); + } + }); + it('toggles the OptIn button', async () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -287,6 +340,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} showAppliesSettingMessage={false} enableSaving={true} + isSecurityExampleEnabled={isSecurityExampleEnabled} toasts={coreStart.notifications.toasts} /> ); @@ -311,6 +365,7 @@ describe('TelemetryManagementSectionComponent', () => { it('test the wrapper (for coverage purposes)', () => { const onQueryMatchChange = jest.fn(); + const isSecurityExampleEnabled = jest.fn().mockReturnValue(true); const telemetryService = new TelemetryService({ config: { enabled: true, @@ -335,6 +390,7 @@ describe('TelemetryManagementSectionComponent', () => { onQueryMatchChange={onQueryMatchChange} enableSaving={true} toasts={coreStart.notifications.toasts} + isSecurityExampleEnabled={isSecurityExampleEnabled} /> ).html() ).toMatchSnapshot(); diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx index 822d8b49661c..c43b600597c5 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx @@ -45,6 +45,7 @@ const SEARCH_TERMS = ['telemetry', 'usage', 'data', 'usage data']; interface Props { telemetryService: TelemetryService; onQueryMatchChange: (searchTermMatches: boolean) => void; + isSecurityExampleEnabled: () => boolean; showAppliesSettingMessage: boolean; enableSaving: boolean; query?: any; @@ -89,8 +90,9 @@ export class TelemetryManagementSection extends Component { } render() { - const { telemetryService } = this.props; + const { telemetryService, isSecurityExampleEnabled } = this.props; const { showExample, showSecurityExample, queryMatches, enabled, processing } = this.state; + const securityExampleEnabled = isSecurityExampleEnabled(); if (!telemetryService.getCanChangeOptInStatus()) { return null; @@ -108,7 +110,9 @@ export class TelemetryManagementSection extends Component { onClose={this.toggleExample} /> )} - {showSecurityExample && } + {showSecurityExample && securityExampleEnabled && ( + + )} @@ -181,48 +185,63 @@ export class TelemetryManagementSection extends Component { ); }; - renderDescription = () => ( - -

- - - - ), - }} - /> -

-

- - - - ), - endpointSecurityData: ( - - - - ), - }} - /> -

-
- ); + renderDescription = () => { + const { isSecurityExampleEnabled } = this.props; + const securityExampleEnabled = isSecurityExampleEnabled(); + const clusterDataLink = ( + + + + ); + + const endpointSecurityDataLink = ( + + + + ); + + return ( + +

+ + + + ), + }} + /> +

+

+ {securityExampleEnabled ? ( + + ) : ( + + )} +

+
+ ); + }; toggleOptIn = async (): Promise => { const { telemetryService, toasts } = this.props; @@ -264,6 +283,9 @@ export class TelemetryManagementSection extends Component { }; toggleSecurityExample = () => { + const { isSecurityExampleEnabled } = this.props; + const securityExampleEnabled = isSecurityExampleEnabled(); + if (!securityExampleEnabled) return; this.setState({ showSecurityExample: !this.state.showSecurityExample, }); diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx index f61268c4772a..95acbaba3884 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx @@ -28,13 +28,15 @@ type Props = any; const TelemetryManagementSectionComponent = lazy(() => import('./telemetry_management_section')); export function telemetryManagementSectionWrapper( - telemetryService: TelemetryPluginSetup['telemetryService'] + telemetryService: TelemetryPluginSetup['telemetryService'], + shouldShowSecuritySolutionUsageExample: () => boolean ) { const TelemetryManagementSectionWrapper = (props: Props) => ( }> diff --git a/src/plugins/telemetry_management_section/public/index.ts b/src/plugins/telemetry_management_section/public/index.ts index 082f68809a67..f3aef9eca750 100644 --- a/src/plugins/telemetry_management_section/public/index.ts +++ b/src/plugins/telemetry_management_section/public/index.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -export { OptInExampleFlyout } from './components'; import { TelemetryManagementSectionPlugin } from './plugin'; +export { OptInExampleFlyout } from './components'; + +export { TelemetryManagementSectionPluginSetup } from './plugin'; export function plugin() { return new TelemetryManagementSectionPlugin(); } diff --git a/src/plugins/telemetry_management_section/public/plugin.tsx b/src/plugins/telemetry_management_section/public/plugin.tsx index 738b38c36d30..c200e830c8f6 100644 --- a/src/plugins/telemetry_management_section/public/plugin.tsx +++ b/src/plugins/telemetry_management_section/public/plugin.tsx @@ -38,16 +38,32 @@ export interface TelemetryManagementSectionPluginDepsSetup { advancedSettings: AdvancedSettingsSetup; } -export class TelemetryManagementSectionPlugin implements Plugin { +export interface TelemetryManagementSectionPluginSetup { + toggleSecuritySolutionExample: (enabled: boolean) => void; +} + +export class TelemetryManagementSectionPlugin + implements Plugin { + private showSecuritySolutionExample = false; + private shouldShowSecuritySolutionExample = () => { + return this.showSecuritySolutionExample; + }; + public setup( core: CoreSetup, { advancedSettings, telemetry: { telemetryService } }: TelemetryManagementSectionPluginDepsSetup ) { advancedSettings.component.register( advancedSettings.component.componentType.PAGE_FOOTER_COMPONENT, - telemetryManagementSectionWrapper(telemetryService), + telemetryManagementSectionWrapper(telemetryService, this.shouldShowSecuritySolutionExample), true ); + + return { + toggleSecuritySolutionExample: (enabled: boolean) => { + this.showSecuritySolutionExample = enabled; + }, + }; } public start(core: CoreStart) {} diff --git a/x-pack/plugins/security_solution/kibana.json b/x-pack/plugins/security_solution/kibana.json index 1fea4bb1aba5..145e34c4fc99 100644 --- a/x-pack/plugins/security_solution/kibana.json +++ b/x-pack/plugins/security_solution/kibana.json @@ -28,7 +28,8 @@ "usageCollection", "lists", "home", - "telemetry" + "telemetry", + "telemetryManagementSection" ], "server": true, "ui": true, diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts index e79ef0d12822..863097a5cd2e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts @@ -25,7 +25,15 @@ export const track: TrackFn = (type, event, count) => { } }; -export const initTelemetry = (usageCollection: SetupPlugins['usageCollection'], appId: string) => { +export const initTelemetry = ( + { + usageCollection, + telemetryManagementSection, + }: Pick, + appId: string +) => { + telemetryManagementSection?.toggleSecuritySolutionExample(true); + _track = usageCollection?.reportUiStats?.bind(null, appId) ?? noop; }; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 29aa0b111b78..ea8c086c9bdc 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -85,7 +85,13 @@ export class Plugin implements IPlugin, plugins: SetupPlugins): PluginSetup { - initTelemetry(plugins.usageCollection, APP_ID); + initTelemetry( + { + usageCollection: plugins.usageCollection, + telemetryManagementSection: plugins.telemetryManagementSection, + }, + APP_ID + ); if (plugins.home) { plugins.home.featureCatalogue.registerSolution({ diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index 80cc014285ae..d72a8b926158 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -13,6 +13,7 @@ import { NewsfeedPublicPluginStart } from '../../../../src/plugins/newsfeed/publ import { Start as InspectorStart } from '../../../../src/plugins/inspector/public'; import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; +import { TelemetryManagementSectionPluginSetup } from '../../../../src/plugins/telemetry_management_section/public'; import { Storage } from '../../../../src/plugins/kibana_utils/public'; import { IngestManagerStart } from '../../ingest_manager/public'; import { PluginStart as ListsPluginStart } from '../../lists/public'; @@ -38,6 +39,7 @@ export interface SetupPlugins { security: SecurityPluginSetup; triggersActionsUi: TriggersActionsSetup; usageCollection?: UsageCollectionSetup; + telemetryManagementSection?: TelemetryManagementSectionPluginSetup; ml?: MlPluginSetup; } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f511dbc3b587..578f5232f6fc 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3158,7 +3158,6 @@ "telemetry.provideUsageStatisticsTitle": "使用統計を提供", "telemetry.readOurUsageDataPrivacyStatementLinkText": "プライバシーポリシー", "telemetry.securityData": "Endpoint Securityデータ", - "telemetry.seeExamplesOfWhatWeCollect": "当社が収集する{clusterData}および{endpointSecurityData}の例をご覧ください。", "telemetry.telemetryBannerDescription": "Elastic Stackの改善にご協力ください使用状況データの収集は現在無効です。使用状況データの収集を有効にすると、製品とサービスを管理して改善することができます。詳細については、{privacyStatementLink}をご覧ください。", "telemetry.telemetryConfigAndLinkDescription": "使用状況データの収集を有効にすると、製品とサービスを管理して改善することができます。詳細については、{privacyStatementLink}をご覧ください。", "telemetry.telemetryConfigDescription": "基本的な機能の利用状況に関する統計情報を提供して、Elastic Stack の改善にご協力ください。このデータは Elastic 社外と共有されません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6bd1129cd438..d4e9c5b1fca5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3159,7 +3159,6 @@ "telemetry.provideUsageStatisticsTitle": "提供使用情况统计", "telemetry.readOurUsageDataPrivacyStatementLinkText": "隐私声明", "telemetry.securityData": "Endpoint Security 数据", - "telemetry.seeExamplesOfWhatWeCollect": "查看我们收集的{clusterData}和 {endpointSecurityData}的示例。", "telemetry.telemetryBannerDescription": "想帮助我们改进 Elastic Stack?数据使用情况收集当前已禁用。启用数据使用情况收集可帮助我们管理并改善产品和服务。有关详情,请参阅我们的{privacyStatementLink}。", "telemetry.telemetryConfigAndLinkDescription": "启用使用情况数据收集可帮助我们管理并改善产品和服务。有关更多详情,请参阅我们的{privacyStatementLink}。", "telemetry.telemetryConfigDescription": "通过提供基本功能的使用情况统计信息,来帮助我们改进 Elastic Stack。我们不会在 Elastic 之外共享此数据。",