diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts index 4b6566415f3e18..50a25423b5eb82 100644 --- a/src/legacy/core_plugins/telemetry/index.ts +++ b/src/legacy/core_plugins/telemetry/index.ts @@ -17,6 +17,7 @@ * under the License. */ +import * as Rx from 'rxjs'; import { resolve } from 'path'; import JoiNamespace from 'joi'; import { Server } from 'hapi'; @@ -45,6 +46,14 @@ const telemetry = (kibana: any) => { config(Joi: typeof JoiNamespace) { return Joi.object({ enabled: Joi.boolean().default(true), + optIn: Joi.when('allowChangingOptInStatus', { + is: false, + then: Joi.valid(true), + otherwise: Joi.boolean() + .allow(null) + .default(null), + }), + allowChangingOptInStatus: Joi.boolean().default(true), // `config` is used internally and not intended to be set config: Joi.string().default(Joi.ref('$defaultConfigPath')), banner: Joi.boolean().default(true), @@ -80,8 +89,25 @@ const telemetry = (kibana: any) => { }, }, async replaceInjectedVars(originalInjectedVars: any, request: any) { + const config = request.server.config(); + const optIn = config.get('telemetry.optIn'); + const allowChangingOptInStatus = config.get('telemetry.allowChangingOptInStatus'); const currentKibanaVersion = getCurrentKibanaVersion(request.server); - const telemetryOptedIn = await getTelemetryOptIn({ request, currentKibanaVersion }); + let telemetryOptedIn: boolean | null; + + if (typeof optIn === 'boolean' && !allowChangingOptInStatus) { + // When not allowed to change optIn status and an optIn value is set, we'll overwrite with that + telemetryOptedIn = optIn; + } else { + telemetryOptedIn = await getTelemetryOptIn({ + request, + currentKibanaVersion, + }); + if (telemetryOptedIn === null) { + // In the senario there's no value set in telemetryOptedIn, we'll return optIn value + telemetryOptedIn = optIn; + } + } return { ...originalInjectedVars, @@ -93,20 +119,36 @@ const telemetry = (kibana: any) => { return { telemetryEnabled: getXpackConfigWithDeprecated(config, 'telemetry.enabled'), telemetryUrl: getXpackConfigWithDeprecated(config, 'telemetry.url'), - telemetryBanner: getXpackConfigWithDeprecated(config, 'telemetry.banner'), - telemetryOptedIn: null, + telemetryBanner: + config.get('telemetry.allowChangingOptInStatus') !== false && + getXpackConfigWithDeprecated(config, 'telemetry.banner'), + telemetryOptedIn: config.get('telemetry.optIn'), + allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'), }; }, hacks: ['plugins/telemetry/hacks/telemetry_init', 'plugins/telemetry/hacks/telemetry_opt_in'], mappings, }, - init(server: Server) { + async init(server: Server) { const initializerContext = { env: { packageInfo: { version: getCurrentKibanaVersion(server), }, }, + config: { + create() { + const config = server.config(); + return Rx.of({ + enabled: config.get('telemetry.enabled'), + optIn: config.get('telemetry.optIn'), + config: config.get('telemetry.config'), + banner: config.get('telemetry.banner'), + url: config.get('telemetry.url'), + allowChangingOptInStatus: config.get('telemetry.allowChangingOptInStatus'), + }); + }, + }, } as PluginInitializerContext; const coreSetup = ({ @@ -114,7 +156,7 @@ const telemetry = (kibana: any) => { log: server.log, } as any) as CoreSetup; - telemetryPlugin(initializerContext).setup(coreSetup); + await telemetryPlugin(initializerContext).setup(coreSetup); // register collectors server.usage.collectorSet.register(createLocalizationUsageCollector(server)); diff --git a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap index c1ad6276aee250..e1aead3798de7a 100644 --- a/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap +++ b/src/legacy/core_plugins/telemetry/public/components/__snapshots__/telemetry_form.test.js.snap @@ -1,6 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TelemetryForm renders as expected 1`] = ` +exports[`TelemetryForm doesn't render form when not allowed to change optIn status 1`] = `""`; + +exports[`TelemetryForm renders as expected when allows to change optIn status 1`] = ` { switch (key) { case '$http': return mockHttp; + case 'allowChangingOptInStatus': + return true; default: return null; } @@ -47,7 +49,23 @@ const buildTelemetryOptInProvider = () => { }; describe('TelemetryForm', () => { - it('renders as expected', () => { + it('renders as expected when allows to change optIn status', () => { + mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true }); + + expect(shallowWithIntl( + ) + ).toMatchSnapshot(); + }); + + it(`doesn't render form when not allowed to change optIn status`, () => { + mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: false }); + expect(shallowWithIntl( { const optIn = true; const bannerId = 'bruce-banner'; - mockInjectedMetadata({ telemetryOptedIn: optIn }); + mockInjectedMetadata({ telemetryOptedIn: optIn, allowChangingOptInStatus: true }); const telemetryOptInProvider = getTelemetryOptInProvider(); telemetryOptInProvider.setBannerId(bannerId); @@ -92,7 +92,7 @@ describe('click_banner', () => { remove: sinon.spy() }; const optIn = true; - mockInjectedMetadata({ telemetryOptedIn: null }); + mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true }); const telemetryOptInProvider = getTelemetryOptInProvider({ simulateFailure: true }); await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications }); @@ -110,7 +110,7 @@ describe('click_banner', () => { remove: sinon.spy() }; const optIn = false; - mockInjectedMetadata({ telemetryOptedIn: null }); + mockInjectedMetadata({ telemetryOptedIn: null, allowChangingOptInStatus: true }); const telemetryOptInProvider = getTelemetryOptInProvider({ simulateError: true }); await clickBanner(telemetryOptInProvider, optIn, { _banners: banners, _toastNotifications: toastNotifications }); diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js index fd21a5122b5946..f26ca0ca0e3c51 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js +++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/handle_old_settings.test.js @@ -38,7 +38,7 @@ const getTelemetryOptInProvider = (enabled, { simulateFailure = false } = {}) => const chrome = { addBasePath: url => url }; - mockInjectedMetadata({ telemetryOptedIn: enabled }); + mockInjectedMetadata({ telemetryOptedIn: enabled, allowChangingOptInStatus: true }); const $injector = { get: (key) => { diff --git a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js index 19e7ccbe618661..240c991a75b646 100644 --- a/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js +++ b/src/legacy/core_plugins/telemetry/public/hacks/welcome_banner/should_show_banner.test.js @@ -38,7 +38,7 @@ const getMockInjector = () => { }; const getTelemetryOptInProvider = ({ telemetryOptedIn = null } = {}) => { - mockInjectedMetadata({ telemetryOptedIn }); + mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus: true }); const injector = getMockInjector(); const chrome = { addBasePath: (url) => url diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js index 0034fa4438238a..26f14fc87d937c 100644 --- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js +++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.js @@ -34,7 +34,7 @@ describe('TelemetryOptInProvider', () => { addBasePath: (url) => url }; - mockInjectedMetadata({ telemetryOptedIn: optedIn }); + mockInjectedMetadata({ telemetryOptedIn: optedIn, allowChangingOptInStatus: true }); const mockInjector = { get: (key) => { diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js index f98f5e16e00c3b..012f8de6400420 100644 --- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js +++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.test.mocks.js @@ -24,10 +24,11 @@ import { } from '../../../../../core/public/mocks'; const injectedMetadataMock = injectedMetadataServiceMock.createStartContract(); -export function mockInjectedMetadata({ telemetryOptedIn }) { +export function mockInjectedMetadata({ telemetryOptedIn, allowChangingOptInStatus }) { const mockGetInjectedVar = jest.fn().mockImplementation((key) => { switch (key) { case 'telemetryOptedIn': return telemetryOptedIn; + case 'allowChangingOptInStatus': return allowChangingOptInStatus; default: throw new Error(`unexpected injectedVar ${key}`); } }); diff --git a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts index f4462ffea7a337..4d27bad352cd4d 100644 --- a/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts +++ b/src/legacy/core_plugins/telemetry/public/services/telemetry_opt_in.ts @@ -28,11 +28,15 @@ let currentOptInStatus = false; export function TelemetryOptInProvider($injector: any, chrome: any) { currentOptInStatus = npStart.core.injectedMetadata.getInjectedVar('telemetryOptedIn') as boolean; + const allowChangingOptInStatus = npStart.core.injectedMetadata.getInjectedVar( + 'allowChangingOptInStatus' + ) as boolean; setCanTrackUiMetrics(currentOptInStatus); const provider = { getBannerId: () => bannerId, getOptIn: () => currentOptInStatus, + canChangeOptInStatus: () => allowChangingOptInStatus, setBannerId(id: string) { bannerId = id; }, diff --git a/src/legacy/core_plugins/telemetry/server/plugin.ts b/src/legacy/core_plugins/telemetry/server/plugin.ts index a5f0f1234799a4..813aa0df09e8c8 100644 --- a/src/legacy/core_plugins/telemetry/server/plugin.ts +++ b/src/legacy/core_plugins/telemetry/server/plugin.ts @@ -29,7 +29,7 @@ export class TelemetryPlugin { this.currentKibanaVersion = initializerContext.env.packageInfo.version; } - public setup(core: CoreSetup) { + public async setup(core: CoreSetup) { const currentKibanaVersion = this.currentKibanaVersion; telemetryCollectionManager.setStatsGetter(getStats, 'local'); registerRoutes({ core, currentKibanaVersion }); diff --git a/src/legacy/core_plugins/telemetry/server/routes/index.ts b/src/legacy/core_plugins/telemetry/server/routes/index.ts index 2eb6bf95b4f45e..549b3ef6068ec4 100644 --- a/src/legacy/core_plugins/telemetry/server/routes/index.ts +++ b/src/legacy/core_plugins/telemetry/server/routes/index.ts @@ -27,6 +27,6 @@ interface RegisterRoutesParams { } export function registerRoutes({ core, currentKibanaVersion }: RegisterRoutesParams) { - registerOptInRoutes({ core, currentKibanaVersion }); registerTelemetryDataRoutes(core); + registerOptInRoutes({ core, currentKibanaVersion }); } diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/telemetry_opt_in.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/telemetry_opt_in.test.js.snap index 642b8399ff6d18..f82e8b03527c04 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/telemetry_opt_in.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/telemetry_opt_in.test.js.snap @@ -104,7 +104,261 @@ exports[`TelemetryOptIn should display when telemetry not opted in 1`] = ` "timeZone": null, } } -/> +> + +
+ + +

+ + Help Elastic support provide better service + +

+
+ +
+ + + + + + } + className="eui-AlignBaseline" + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="readMorePopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" + > + +

+ + + , + "telemetryPrivacyStatementLink": + + , + } + } + /> +

+
+ , + } + } + /> + + } + onChange={[Function]} + > +
+ +
+ +
+ + `; exports[`TelemetryOptIn should not display when telemetry is opted in 1`] = ` @@ -213,3 +467,110 @@ exports[`TelemetryOptIn should not display when telemetry is opted in 1`] = ` } /> `; + +exports[`TelemetryOptIn shouldn't display when telemetry optIn status can't change 1`] = ` + +`; diff --git a/x-pack/legacy/plugins/license_management/__jest__/telemetry_opt_in.test.js b/x-pack/legacy/plugins/license_management/__jest__/telemetry_opt_in.test.js index 4e94657e03deeb..a92ca384e8a371 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/telemetry_opt_in.test.js +++ b/x-pack/legacy/plugins/license_management/__jest__/telemetry_opt_in.test.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; +import { setTelemetryEnabled, setTelemetryOptInService } from '../public/lib/telemetry'; import { TelemetryOptIn } from '../public/components/telemetry_opt_in'; import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; @@ -11,16 +12,30 @@ jest.mock('ui/capabilities', () => ({ get: jest.fn(), })); +setTelemetryEnabled(true); + describe('TelemetryOptIn', () => { test('should display when telemetry not opted in', () => { - const telemetry = require('../public/lib/telemetry'); - telemetry.showTelemetryOptIn = () => { return true; }; + setTelemetryOptInService({ + getOptIn: () => false, + canChangeOptInStatus: () => true, + }); const rendered = mountWithIntl(); expect(rendered).toMatchSnapshot(); }); test('should not display when telemetry is opted in', () => { - const telemetry = require('../public/lib/telemetry'); - telemetry.showTelemetryOptIn = () => { return false; }; + setTelemetryOptInService({ + getOptIn: () => true, + canChangeOptInStatus: () => true, + }); + const rendered = mountWithIntl(); + expect(rendered).toMatchSnapshot(); + }); + test(`shouldn't display when telemetry optIn status can't change`, () => { + setTelemetryOptInService({ + getOptIn: () => false, + canChangeOptInStatus: () => false, + }); const rendered = mountWithIntl(); expect(rendered).toMatchSnapshot(); }); diff --git a/x-pack/legacy/plugins/license_management/public/lib/telemetry.js b/x-pack/legacy/plugins/license_management/public/lib/telemetry.js index bf8bed05aabed3..61d0322227d8ef 100644 --- a/x-pack/legacy/plugins/license_management/public/lib/telemetry.js +++ b/x-pack/legacy/plugins/license_management/public/lib/telemetry.js @@ -25,7 +25,7 @@ export const optInToTelemetry = async (enableTelemetry) => { await telemetryOptInService.setOptIn(enableTelemetry); }; export const shouldShowTelemetryOptIn = () => { - return telemetryEnabled && !telemetryOptInService.getOptIn(); + return telemetryEnabled && !telemetryOptInService.getOptIn() && telemetryOptInService.canChangeOptInStatus(); }; export const getTelemetryFetcher = () => { return fetchTelemetry(httpClient, { unencrypted: true });