diff --git a/x-pack/platform/plugins/shared/ml/common/license/ml_license.ts b/x-pack/platform/plugins/shared/ml/common/license/ml_license.ts index c8f09954fda33..3c38bee5602a4 100644 --- a/x-pack/platform/plugins/shared/ml/common/license/ml_license.ts +++ b/x-pack/platform/plugins/shared/ml/common/license/ml_license.ts @@ -10,8 +10,6 @@ import { BehaviorSubject } from 'rxjs'; import type { ILicense } from '@kbn/licensing-types'; import { distinctUntilChanged, map } from 'rxjs'; import { isEqual } from 'lodash'; -import type { MlCapabilities } from '@kbn/ml-common-types/capabilities'; -import type { MlCoreSetup } from '../../public/plugin'; import { PLUGIN_ID } from '../constants/app'; export const MINIMUM_LICENSE = 'basic'; @@ -143,20 +141,3 @@ export function isMinimumLicense(license: ILicense) { export function isMlEnabled(license: ILicense) { return license.getFeature(PLUGIN_ID).isEnabled; } - -export async function isMlAvailable(getStartServices: MlCoreSetup['getStartServices']) { - const [coreStart, pluginStart] = await getStartServices(); - const license = await pluginStart.licensing.getLicense(); - return ( - isFullLicense(license) && - isMlEnabled(license) && - (coreStart.application.capabilities.ml as MlCapabilities).canGetMlInfo - ); -} - -export async function ensureMlAvailable(getStartServices: MlCoreSetup['getStartServices']) { - const isAvailable = await isMlAvailable(getStartServices); - if (!isAvailable) { - throw new Error('ML is not available'); - } -} diff --git a/x-pack/platform/plugins/shared/ml/public/application/capabilities/check_capabilities.ts b/x-pack/platform/plugins/shared/ml/public/application/capabilities/check_capabilities.ts index 47e8bf5c1b0eb..3b17775d7abf1 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/capabilities/check_capabilities.ts +++ b/x-pack/platform/plugins/shared/ml/public/application/capabilities/check_capabilities.ts @@ -29,6 +29,7 @@ import { hasLicenseExpired } from '../license'; import { getCapabilities } from './get_capabilities'; import type { MlApi } from '../services/ml_api_service'; import type { MlGlobalServices } from '../app'; +import type { MlCoreSetup } from '../../plugin'; let _capabilities: MlCapabilities = getDefaultMlCapabilities(); @@ -232,6 +233,20 @@ export function checkPermission(capability: keyof MlCapabilities) { return _capabilities[capability] === true && licenseHasExpired !== true; } +export async function checkPermissionAsync( + getStartServices: MlCoreSetup['getStartServices'], + capability: keyof MlCapabilities, + throwError: boolean = false +) { + const [coreStart] = await getStartServices(); + const hasPermission = + (coreStart.application.capabilities.ml as MlCapabilities)[capability] === true; + if (!hasPermission && throwError) { + throw new Error('You do not have permission to access this feature'); + } + return hasPermission; +} + // create the text for the button's tooltips if the user's license has // expired or if they don't have the privilege to press that button export function createPermissionFailureMessage(privilegeType: keyof MlCapabilities) { diff --git a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx index 8b1ea75d6f398..c465e9f2ae8ed 100644 --- a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx +++ b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable_factory.tsx @@ -41,7 +41,7 @@ import { LazyAnomalyChartsContainer } from './lazy_anomaly_charts_container'; import { getAnomalyChartsServiceDependencies } from './get_anomaly_charts_services_dependencies'; import { buildDataViewPublishingApi } from '../common/build_data_view_publishing_api'; import { EmbeddableAnomalyChartsUserInput } from './anomaly_charts_setup_flyout'; -import { ensureMlAvailable } from '../../../common/license/ml_license'; +import { checkPermissionAsync } from '../../application/capabilities/check_capabilities'; export const getAnomalyChartsReactEmbeddableFactory = ( getStartServices: StartServicesAccessor, @@ -50,7 +50,7 @@ export const getAnomalyChartsReactEmbeddableFactory = ( const factory: EmbeddableFactory = { type: ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { - await ensureMlAvailable(getStartServices); + await checkPermissionAsync(getStartServices, 'canGetJobs', true); if (!apiHasExecutionContext(parentApi)) { throw new Error('Parent API does not have execution context'); } diff --git a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx index 623fd1f58900e..53f5282918773 100644 --- a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx +++ b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.test.tsx @@ -33,9 +33,9 @@ const mockResponse = of([ }, ]); -jest.mock('../../../common/license/ml_license', () => { +jest.mock('../../application/capabilities/check_capabilities', () => { return { - ensureMlAvailable: jest.fn(), + checkPermissionAsync: jest.fn().mockResolvedValue(true), }; }); diff --git a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx index aba209ec32190..33e29d420e2ff 100644 --- a/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx +++ b/x-pack/platform/plugins/shared/ml/public/embeddables/anomaly_swimlane/anomaly_swimlane_embeddable_factory.tsx @@ -50,7 +50,7 @@ import { initializeSwimLaneControls, swimLaneComparators } from './initialize_sw import { initializeSwimLaneDataFetcher } from './initialize_swim_lane_data_fetcher'; import type { AnomalySwimLaneEmbeddableApi } from './types'; import { AnomalySwimlaneUserInput } from './anomaly_swimlane_setup_flyout'; -import { ensureMlAvailable } from '../../../common/license/ml_license'; +import { checkPermissionAsync } from '../../application/capabilities/check_capabilities'; /** * Provides the services required by the Anomaly Swimlane Embeddable. @@ -91,7 +91,7 @@ export const getAnomalySwimLaneEmbeddableFactory = ( const factory: EmbeddableFactory = { type: ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { - await ensureMlAvailable(getStartServices); + await checkPermissionAsync(getStartServices, 'canGetJobs', true); if (!apiHasExecutionContext(parentApi)) { throw new Error('Parent API does not have execution context'); } diff --git a/x-pack/platform/plugins/shared/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx b/x-pack/platform/plugins/shared/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx index 0cf5d238d320e..aeec31d837cae 100644 --- a/x-pack/platform/plugins/shared/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx +++ b/x-pack/platform/plugins/shared/ml/public/embeddables/single_metric_viewer/single_metric_viewer_embeddable_factory.tsx @@ -36,7 +36,7 @@ import { getServices } from './get_services'; import { useReactEmbeddableExecutionContext } from '../common/use_embeddable_execution_context'; import { getSingleMetricViewerComponent } from '../../shared_components/single_metric_viewer'; import { EmbeddableSingleMetricViewerUserInput } from './single_metric_viewer_setup_flyout'; -import { ensureMlAvailable } from '../../../common/license/ml_license'; +import { checkPermissionAsync } from '../../application/capabilities/check_capabilities'; export const getSingleMetricViewerEmbeddableFactory = ( getStartServices: StartServicesAccessor, @@ -48,7 +48,7 @@ export const getSingleMetricViewerEmbeddableFactory = ( > = { type: ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE, buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { - await ensureMlAvailable(getStartServices); + await checkPermissionAsync(getStartServices, 'canGetJobs', true); const services = await getServices(getStartServices, usageCollection); const subscriptions = new Subscription(); const titleManager = initializeTitleManager(initialState); diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_entity_filters_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_entity_filters_action.tsx index c0fbf62b9b577..7de9074c214fd 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_entity_filters_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_entity_filters_action.tsx @@ -17,7 +17,7 @@ import { ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE, } from '../embeddables'; import { CONTROLLED_BY_ANOMALY_CHARTS_FILTER } from './constants'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const APPLY_ENTITY_FIELD_FILTERS_ACTION = 'applyEntityFieldFiltersAction'; @@ -81,7 +81,7 @@ export function createApplyEntityFieldFiltersAction( ); }, async isCompatible({ embeddable, data }) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return ( (embeddable.type === ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE || embeddable.type === ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE) && diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_influencer_filters_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_influencer_filters_action.tsx index e3c72f312ccf5..0d8bc3f106f08 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_influencer_filters_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_influencer_filters_action.tsx @@ -18,7 +18,7 @@ import { VIEW_BY_JOB_LABEL } from '../application/explorer/explorer_constants'; import type { SwimLaneDrilldownContext } from '../embeddables'; import type { MlCoreSetup } from '../plugin'; import { CONTROLLED_BY_SWIM_LANE_FILTER } from './constants'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const APPLY_INFLUENCER_FILTERS_ACTION = 'applyInfluencerFiltersAction'; @@ -77,7 +77,7 @@ export function createApplyInfluencerFiltersAction( ); }, async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; const [{ application }] = await getStartServices(); const appId = await firstValueFrom(application.currentAppId$); diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_time_range_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_time_range_action.tsx index 277830341256c..6b49f6f9bf36d 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_time_range_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/apply_time_range_action.tsx @@ -15,7 +15,7 @@ import { isAnomalySwimlaneSelectionTriggerContext } from './triggers'; import type { AppStateSelectedCells } from '../application/explorer/explorer_utils'; import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const APPLY_TIME_RANGE_SELECTION_ACTION = 'applyTimeRangeSelectionAction'; @@ -65,7 +65,7 @@ export function createApplyTimeRangeSelectionAction( }); }, async isCompatible(context) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; const [{ application }] = await getStartServices(); const appId = await firstValueFrom(application.currentAppId$); return isAnomalySwimlaneSelectionTriggerContext(context) && supportedApps.includes(appId!); diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/clear_selection_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/clear_selection_action.tsx index 68a886c3f84a0..1144c39bf87ff 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/clear_selection_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/clear_selection_action.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; import type { MlCoreSetup } from '../plugin'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const CLEAR_SELECTION_ACTION = 'clearSelectionAction'; @@ -34,7 +34,7 @@ export function createClearSelectionAction( updateCallback(); }, async isCompatible({ updateCallback }) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return typeof updateCallback === 'function'; }, }; diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_anomaly_chart.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_anomaly_chart.tsx index d955581ee0475..7df52557daf1a 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_anomaly_chart.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_anomaly_chart.tsx @@ -17,7 +17,7 @@ import type { AnomalyChartsEmbeddableApi } from '../embeddables'; import { ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE } from '../embeddables'; import type { MlCoreSetup } from '../plugin'; import { EmbeddableAnomalyChartsUserInput } from '../embeddables/anomaly_charts/anomaly_charts_setup_flyout'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const EDIT_ANOMALY_CHARTS_PANEL_ACTION = 'editAnomalyChartsPanelAction'; @@ -56,7 +56,7 @@ export function createAddAnomalyChartsPanelAction( defaultMessage: 'View anomaly detection results in a chart.', }), async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_single_metric_viewer.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_single_metric_viewer.tsx index 4b03e17ce4f6a..993185890862e 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_single_metric_viewer.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_single_metric_viewer.tsx @@ -18,7 +18,7 @@ import { ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE } from '../embeddables'; import type { SingleMetricViewerEmbeddableApi } from '../embeddables/types'; import type { MlCoreSetup } from '../plugin'; import { EmbeddableSingleMetricViewerUserInput } from '../embeddables/single_metric_viewer/single_metric_viewer_setup_flyout'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export type CreateSingleMetricViewerPanelActionContext = EmbeddableApiContext & { embeddable: SingleMetricViewerEmbeddableApi; @@ -57,7 +57,7 @@ export function createAddSingleMetricViewerPanelAction( 'View anomaly detection results for a single metric on a focused date range.', }), async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_swim_lane.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_swim_lane.tsx index 6b80fc2a37264..76cf3c7b011f5 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/create_swim_lane.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/create_swim_lane.tsx @@ -17,7 +17,7 @@ import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE } from '../embeddables'; import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; import { AnomalySwimlaneUserInput } from '../embeddables/anomaly_swimlane/anomaly_swimlane_setup_flyout'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction'; @@ -56,7 +56,7 @@ export function createAddSwimlanePanelAction( defaultMessage: 'View anomaly detection results in a timeline.', }), async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return Boolean(await parentApiIsCompatible(context.embeddable)); }, async execute(context) { diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_create_categorization_job_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_create_categorization_job_action.tsx index e5e77d1aca952..6c5957f312f03 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_create_categorization_job_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_create_categorization_job_action.tsx @@ -12,7 +12,7 @@ import { type CreateCategorizationADJobContext, } from '@kbn/ml-ui-actions'; import type { MlCoreSetup } from '../plugin'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export function createCategorizationADJobAction( getStartServices: MlCoreSetup['getStartServices'] @@ -51,7 +51,7 @@ export function createCategorizationADJobAction( } }, async isCompatible({ dataView, field }: CreateCategorizationADJobContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canCreateJob'))) return false; return ( dataView.timeFieldName !== undefined && dataView.fields.find((f) => f.name === field.name) !== undefined diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx index 693c2388e0b59..3094f9eac3b08 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx @@ -22,7 +22,7 @@ import type { AnomalySwimLaneEmbeddableApi } from '../embeddables/anomaly_swimla import { isSwimLaneEmbeddableContext } from '../embeddables/anomaly_swimlane/types'; import type { MlCoreSetup } from '../plugin'; import { getEmbeddableTimeRange } from './get_embeddable_time_range'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export interface OpenInAnomalyExplorerSwimLaneActionContext extends EmbeddableApiContext { embeddable: AnomalySwimLaneEmbeddableApi; @@ -155,7 +155,7 @@ export function createOpenInExplorerAction( } }, async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return isSwimLaneEmbeddableContext(context) || isAnomalyChartsEmbeddableContext(context); }, }; diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_single_metric_viewer_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_single_metric_viewer_action.tsx index 6724a1efe617d..65faa128d7984 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_single_metric_viewer_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_in_single_metric_viewer_action.tsx @@ -19,7 +19,7 @@ import { ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE } from '../embeddables'; import type { MlCoreSetup } from '../plugin'; import { getEmbeddableTimeRange } from './get_embeddable_time_range'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export interface OpenInSingleMetricViewerActionContext extends EmbeddableApiContext { embeddable: SingleMetricViewerEmbeddableApi; @@ -92,7 +92,7 @@ export function createOpenInSingleMetricViewerAction( } }, async isCompatible(context: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; return isSingleMetricViewerEmbeddableContext(context); }, }; diff --git a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_vis_in_ml_action.tsx b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_vis_in_ml_action.tsx index 9380f3ee7344c..bb8ab723ac7a8 100644 --- a/x-pack/platform/plugins/shared/ml/public/ui_actions/open_vis_in_ml_action.tsx +++ b/x-pack/platform/plugins/shared/ml/public/ui_actions/open_vis_in_ml_action.tsx @@ -14,7 +14,7 @@ import { isOfAggregateQueryType } from '@kbn/es-query'; import { LENS_EMBEDDABLE_TYPE } from '@kbn/lens-common'; import type { ActionApi } from './types'; import type { MlCoreSetup } from '../plugin'; -import { isMlAvailable } from '../../common/license/ml_license'; +import { checkPermissionAsync } from '../application/capabilities/check_capabilities'; export const CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION = 'createMLADJobAction'; @@ -58,7 +58,7 @@ export function createVisToADJobAction( } }, async isCompatible({ embeddable }: EmbeddableApiContext) { - if (!(await isMlAvailable(getStartServices))) return false; + if (!(await checkPermissionAsync(getStartServices, 'canGetJobs'))) return false; if ( !isApiCompatible(embeddable) || !(apiIsOfType(embeddable, LENS_EMBEDDABLE_TYPE) || apiIsOfType(embeddable, 'map'))