[AI4DSOC] [REVERT] Disable Visualize, Lens and Maps for Search AI Lake Tier #218089 (#221141)

Reverts: https://github.com/elastic/kibana/pull/218089 

Previous PR: 
<img width="199" alt="Screenshot 2025-05-21 at 17 52 10"
src="https://github.com/user-attachments/assets/51e87073-eec5-47fc-8c20-59399a9e1042"
/>

This PR:
<img width="215" alt="Screenshot 2025-05-21 at 18 04 15"
src="https://github.com/user-attachments/assets/30e5bc50-b9e4-486f-af17-e42ca5c6b84c"
/>


-----

We realized that there are so many dependencies on `lens`, and thus
`visualizations` that we decided to revert this, and find another way to
hide the features in AI_SOC plugin. Hopefully approach with `overrides`
would be just enough for our need.

Thank you everyone for the initial help and reviews.
This commit is contained in:
Tomasz Ciecierski 2025-05-21 20:39:09 +02:00 committed by GitHub
parent 6f41f41626
commit 4cfcf3b190
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
61 changed files with 103 additions and 243 deletions

View file

@ -9,12 +9,6 @@ xpack.serverless.chat.enabled: true
## Cloud settings
xpack.cloud.serverless.project_type: search
## Fine-tune the search solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides.
xpack.features.overrides:
### Not sure if CHAT solution uses dashboard or maps
### Maps feature is hidden in Role management since it's automatically granted by Dashboard feature.
maps_v2.hidden: true
## Set the home route
uiSettings.overrides.defaultRoute: /app/workchat

View file

@ -50,8 +50,6 @@ xpack.features.overrides:
dev_tools.category: "enterpriseSearch"
### Discover feature is moved from Analytics category to the Search one.
discover_v2.category: "enterpriseSearch"
### Maps feature is hidden in Role management since it's automatically granted by Dashboard feature.
maps_v2.hidden: true
### Machine Learning feature is moved from Analytics category to the Management one.
ml.category: "management"
### Stack Alerts feature is moved from Analytics category to the Search one renamed to simply `Alerts`.

View file

@ -84,8 +84,6 @@ xpack.features.overrides:
privileges: [ "read" ]
### Logs feature is hidden in Role management since it's automatically granted by either Infrastructure, or Applications features.
logs.hidden: true
### Maps feature is hidden in Role management since it's automatically granted by Dashboard feature.
maps_v2.hidden: true
### Machine Learning feature should be moved from Analytics category to the Observability one and renamed to `AI Ops`.
ml:
category: "observability"

View file

@ -1,4 +1 @@
# Security Complete tier config
xpack.features.overrides:
### The following features are hidden in Role management since they're automatically granted by SIEM feature.
maps_v2.hidden: true

View file

@ -1,4 +1,2 @@
# Security Essentials tier config
xpack.features.overrides:
### The following features are hidden in Role management since they're automatically granted by SIEM feature.
maps_v2.hidden: true

View file

@ -1,14 +1,9 @@
# Security Search AI Lake tier config
## Disable xpack plugins
## Disable plugins
xpack.osquery.enabled: false
xpack.maps.enabled: false
xpack.ml.ad.enabled: false
xpack.ml.dfa.enabled: false
xpack.lens.enabled: false
### Disable shared plugins
visualizations.enabled: false
## Disable plugin features
xpack.alerting.maintenanceWindow.enabled: false
@ -23,51 +18,6 @@ xpack.features.overrides:
siemV2.description: null
securitySolutionSiemMigrations.hidden: true
## Fine-tune the security solution essentials feature privileges. These feature privilege overrides are set individually for each project type. Also, refer to `serverless.yml` for the project-agnostic overrides.
dashboard:
privileges:
## We do not need to compose dashboard from maps and visualizations because these functionalities are disabled in this tier
## Setting to empty array so the values from serverless.yml or serverless.security.yml are overwritten
all.composedOf: []
read.composedOf: []
dashboard_v2:
privileges:
## Setting to empty array so the values from serverless.yml or serverless.security.yml are overwritten
## We do not need to compose dashboard from maps and visualizations because these functionalities are disabled in this tier
all.composedOf: []
read.composedOf: []
siemV2:
privileges:
all.composedOf:
## Limited values so the fields from serverless.yml or serverless.security.yml are overwritten
## We do not need to compose siemV2 from maps and visualizations because these functionalities are disabled in this tier
- feature: "discover_v2"
privileges: [ "all" ]
- feature: "dashboard_v2"
privileges: [ "all" ]
read.composedOf:
- feature: "discover_v2"
privileges: [ "read" ]
- feature: "dashboard_v2"
privileges: [ "read" ]
siem:
privileges:
all.composedOf:
## Limited values so the fields from serverless.yml or serverless.security.yml are overwritten
## We do not need to compose siemV2 from maps and visualizations because these functionalities are disabled in this tier
- feature: "discover_v2"
privileges: [ "all" ]
- feature: "dashboard_v2"
privileges: [ "all" ]
- feature: "savedQueryManagement"
privileges: [ "all" ]
read.composedOf:
- feature: "discover_v2"
privileges: [ "read" ]
- feature: "dashboard_v2"
privileges: [ "read" ]
- feature: "savedQueryManagement"
privileges: [ "read" ]
# Custom integrations/fleet settings
xpack.fleet.agentless.isDefault: true
xpack.fleet.integrationsHomeOverride: '/app/security/configurations/integrations'

View file

@ -18,6 +18,8 @@ xpack.features.overrides:
dashboard_v2.hidden: true
visualize.hidden: true
visualize_v2.hidden: true
maps.hidden: true
maps_v2.hidden: true
### Machine Learning feature is moved from Analytics category to the Security one as the last item.
ml:
category: "security"

View file

@ -81,6 +81,8 @@ xpack.features.overrides:
includeIn: "read"
### Shared images feature is hidden in Role management since it's not needed.
filesSharedImage.hidden: true
### Maps feature is hidden in Role management since it's automatically granted by Dashboard feature.
maps_v2.hidden: true
### Reporting feature is supposed to give access to reporting capabilities across different features.
reporting:
privileges:

View file

@ -11,6 +11,7 @@ import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
readOnly: offeringBasedSchema({
serverless: schema.boolean({ defaultValue: false }),
}),

View file

@ -51,7 +51,7 @@ export const createVisEmbeddableFromObject =
}
const capabilities = {
visualizeSave: Boolean(getCapabilities().visualize_v2?.save),
visualizeSave: Boolean(getCapabilities().visualize_v2.save),
dashboardSave: Boolean(getCapabilities().dashboard_v2?.showWriteControls),
visualizeOpen: Boolean(getCapabilities().visualize_v2?.show),
};

View file

@ -1,14 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { schema } from '@kbn/config-schema';
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
});

View file

@ -7,19 +7,11 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
import { configSchema } from './config';
import { PluginInitializerContext } from '@kbn/core/server';
// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export const config: PluginConfigDescriptor<any> = {
schema: configSchema,
exposeToBrowser: {
visualize_v2: { enabled: true },
},
};
export async function plugin(initializerContext: PluginInitializerContext) {
const { VisualizationsPlugin } = await import('./plugin');
return new VisualizationsPlugin(initializerContext);

View file

@ -14,6 +14,7 @@
"requiredPlugins": [
"charts",
"data",
"lens",
"licensing",
"uiActions",
"embeddable",
@ -26,8 +27,7 @@
"optionalPlugins": [
"cases",
"observabilityAIAssistant",
"usageCollection",
"lens"
"usageCollection"
],
"requiredBundles": [
"dataViews",

View file

@ -20,6 +20,7 @@
"actions",
"data",
"embeddable",
"lens",
"licensing",
"features",
"triggersActionsUi",
@ -38,15 +39,13 @@
"taskManager",
"usageCollection",
"spaces",
"serverless",
"lens"
"serverless"
],
"requiredBundles": [
"esUiShared",
"kibanaReact",
"kibanaUtils",
"savedObjectsFinder",
"lens"
"savedObjectsFinder"
],
"extraPublicDirs": [
"common"

View file

@ -27,11 +27,7 @@ interface StartServiceArgs {
license?: ILicense | null;
}
type StartServicesWithRequiredLens = StartServices & Required<Pick<StartServices, 'lens'>>;
export const createStartServicesMock = ({
license,
}: StartServiceArgs = {}): StartServicesWithRequiredLens => {
export const createStartServicesMock = ({ license }: StartServiceArgs = {}): StartServices => {
const licensingPluginMock = licensingMock.createStart();
const triggersActionsUi = triggersActionsUiMock.createStart();
@ -52,7 +48,7 @@ export const createStartServicesMock = ({
license != null
? { ...licensingPluginMock, license$: new BehaviorSubject(license) }
: licensingPluginMock,
} as unknown as StartServicesWithRequiredLens;
} as unknown as StartServices;
services.application.currentAppId$ = new BehaviorSubject<string>('testAppId');
services.application.applications$ = new BehaviorSubject<Map<string, PublicAppInfo>>(

View file

@ -10,7 +10,7 @@ import type { CasesUiConfigType } from '../../../../common/ui/types';
import type { CasesPublicStartDependencies } from '../../../types';
type GlobalServices = Pick<CoreStart, 'application' | 'http' | 'theme' | 'userProfile'> &
Pick<CasesPublicStartDependencies, 'serverless' | 'lens'>;
Pick<CasesPublicStartDependencies, 'serverless'>;
export class KibanaServices {
private static kibanaVersion?: string;

View file

@ -21,11 +21,14 @@ export const useLensOpenVisualization = ({ comment }: { comment: string }) => {
const parsedComment = parseCommentString(comment);
const lensVisualization = getLensVisualizations(parsedComment?.children ?? []);
const { lens } = useKibana().services;
const hasLensPermissions = lens?.canUseEditor();
const {
lens: { navigateToPrefilledEditor, canUseEditor },
} = useKibana().services;
const hasLensPermissions = canUseEditor();
const handleClick = useCallback(() => {
lens?.navigateToPrefilledEditor(
navigateToPrefilledEditor(
{
id: '',
timeRange: lensVisualization[0].timeRange,
@ -36,7 +39,7 @@ export const useLensOpenVisualization = ({ comment }: { comment: string }) => {
openInNewTab: true,
}
);
}, [lens, lensVisualization]);
}, [lensVisualization, navigateToPrefilledEditor]);
if (!lensVisualization.length || lensVisualization?.[0]?.attributes == null) {
return { canUseEditor: hasLensPermissions, actionConfig: null };

View file

@ -13,13 +13,12 @@ import {
import { useMemo } from 'react';
import { useTimelineContext } from '../timeline_context/use_timeline_context';
import type { TemporaryProcessingPluginsType } from './types';
import { KibanaServices, useApplicationCapabilities, useKibana } from '../../common/lib/kibana';
import { KibanaServices, useApplicationCapabilities } from '../../common/lib/kibana';
import * as lensMarkdownPlugin from './plugins/lens';
import { ID as LensPluginId } from './plugins/lens/constants';
export const usePlugins = (disabledPlugins?: string[]) => {
const kibanaConfig = KibanaServices.getConfig();
const { services } = useKibana();
const timelinePlugins = useTimelineContext()?.editor_plugins;
const appCapabilities = useApplicationCapabilities();
@ -39,7 +38,6 @@ export const usePlugins = (disabledPlugins?: string[]) => {
}
if (
services.lens !== undefined &&
kibanaConfig?.markdownPlugins?.lens &&
!disabledPlugins?.includes(LensPluginId) &&
appCapabilities?.visualize.crud
@ -60,7 +58,6 @@ export const usePlugins = (disabledPlugins?: string[]) => {
appCapabilities?.visualize.crud,
disabledPlugins,
kibanaConfig?.markdownPlugins?.lens,
services.lens,
timelinePlugins,
]);
};

View file

@ -15,14 +15,11 @@ import type { LensProps } from './types';
const LENS_VISUALIZATION_HEIGHT = 200;
const LensRendererComponent: React.FC<LensProps> = ({ attributes, timeRange, metadata }) => {
const { lens } = useKibana().services;
const {
lens: { EmbeddableComponent },
} = useKibana().services;
const { euiTheme } = useEuiTheme();
if (!lens) {
return null;
}
const { EmbeddableComponent } = lens;
if (!attributes) {
return null;
}

View file

@ -15,10 +15,12 @@ import type { LensProps } from './types';
type Props = LensProps & { attachmentId: string };
const OpenLensButtonComponent: React.FC<Props> = ({ attachmentId, attributes, timeRange }) => {
const { lens } = useKibana().services;
const {
lens: { navigateToPrefilledEditor, canUseEditor },
} = useKibana().services;
const onClick = useCallback(() => {
lens?.navigateToPrefilledEditor(
navigateToPrefilledEditor(
{
id: attachmentId,
timeRange,
@ -28,9 +30,9 @@ const OpenLensButtonComponent: React.FC<Props> = ({ attachmentId, attributes, ti
openInNewTab: true,
}
);
}, [attachmentId, attributes, lens, timeRange]);
}, [attachmentId, attributes, navigateToPrefilledEditor, timeRange]);
const hasLensPermissions = lens?.canUseEditor();
const hasLensPermissions = canUseEditor();
const isESQLQuery = isOfAggregateQueryType(attributes.state.query);
if (!hasLensPermissions || isESQLQuery) {

View file

@ -79,10 +79,7 @@ export interface CasesPublicStartDependencies {
embeddable: EmbeddableStart;
features: FeaturesPluginStart;
files: FilesStart;
/**
* Lens is not supported in all serverless tiers
*/
lens?: LensPublicStart;
lens: LensPublicStart;
/**
* Cases in used by other plugins. Plugins pass the
* service to their KibanaContext. ML does not pass

View file

@ -364,7 +364,7 @@ export const extractLensReferencesFromCommentString = (
lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory'],
comment: string
): SavedObjectReference[] => {
const extract = lensEmbeddableFactory && lensEmbeddableFactory().extract;
const extract = lensEmbeddableFactory()?.extract;
if (extract) {
const parsedComment = parseCommentString(comment);

View file

@ -62,7 +62,7 @@ export class CasePlugin
private readonly kibanaVersion: PluginInitializerContext['env']['packageInfo']['version'];
private clientFactory: CasesClientFactory;
private securityPluginSetup?: SecurityPluginSetup;
private lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory'];
private lensEmbeddableFactory?: LensServerPluginSetup['lensEmbeddableFactory'];
private persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry;
private externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry;
private userProfileService: UserProfileService;
@ -92,7 +92,7 @@ export class CasePlugin
registerCaseFileKinds(this.caseConfig.files, plugins.files, core.security.fips.isEnabled());
this.securityPluginSetup = plugins.security;
this.lensEmbeddableFactory = plugins.lens?.lensEmbeddableFactory;
this.lensEmbeddableFactory = plugins.lens.lensEmbeddableFactory;
if (this.caseConfig.stack.enabled) {
// V1 is deprecated, but has to be maintained for the time being
@ -209,7 +209,12 @@ export class CasePlugin
featuresPluginStart: plugins.features,
actionsPluginStart: plugins.actions,
licensingPluginStart: plugins.licensing,
lensEmbeddableFactory: this.lensEmbeddableFactory,
/**
* Lens will be always defined as
* it is declared as required plugin in kibana.json
*/
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
lensEmbeddableFactory: this.lensEmbeddableFactory!,
persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry,
externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry,
publicBaseUrl: core.http.basePath.publicBaseUrl,

View file

@ -98,7 +98,7 @@ export const getLensMigrations = <T>({
lensEmbeddableFactory,
migratorFactory,
}: GetLensMigrationsArgs<T>) => {
const lensMigrations = lensEmbeddableFactory?.().migrations;
const lensMigrations = lensEmbeddableFactory().migrations;
const lensMigrationObject = isFunction(lensMigrations) ? lensMigrations() : lensMigrations || {};
const embeddableMigrations = mapValues<MigrateFunctionsObject, SavedObjectMigrationParams<T, T>>(

View file

@ -39,7 +39,7 @@ import type { PersistableStateAttachmentTypeRegistry } from './attachment_framew
export interface CasesServerSetupDependencies {
alerting: AlertingServerSetup;
actions: ActionsPluginSetup;
lens?: LensServerPluginSetup;
lens: LensServerPluginSetup;
features: FeaturesPluginSetup;
files: FilesSetup;
security: SecurityPluginSetup;

View file

@ -25,13 +25,13 @@
"fleet",
"fieldFormats",
"dataViews",
"lens",
"fieldsMetadata",
"taskManager",
"usageCollection"
],
"optionalPlugins": [
"telemetry",
"lens"
"telemetry"
],
"requiredBundles": [
"discover"

View file

@ -19,6 +19,7 @@
"inspector",
"navigation",
"urlForwarding",
"visualizations",
"uiActions",
"uiActionsEnhanced",
"embeddable",
@ -47,7 +48,6 @@
"serverless",
"licensing",
"fieldsMetadata",
"visualizations"
],
"requiredBundles": [
"unifiedSearch",
@ -58,8 +58,7 @@
"fieldFormats",
"charts",
"esqlDataGrid",
"visualizations",
"esql"
"esql",
],
"extraPublicDirs": ["common/constants"]
}

View file

@ -200,7 +200,7 @@ export function App({
useEffect(() => {
onAppLeave((actions) => {
if (
application.capabilities.visualize_v2?.save &&
application.capabilities.visualize_v2.save &&
!isLensEqualWrapper(persistedDoc) &&
(isSaveable || persistedDoc)
) {
@ -226,7 +226,7 @@ export function App({
lastKnownDoc,
isSaveable,
persistedDoc,
application.capabilities.visualize_v2?.save,
application.capabilities.visualize_v2.save,
data.query.filterManager,
datasourceMap,
visualizationMap,

View file

@ -481,7 +481,7 @@ export const LensTopNavMenu = ({
const { from, to } = data.query.timefilter.timefilter.getTime();
const savingToLibraryPermitted = Boolean(
isSaveable && application.capabilities.visualize_v2?.save
isSaveable && application.capabilities.visualize_v2.save
);
const savingToDashboardPermitted = Boolean(
isSaveable && application.capabilities.dashboard_v2?.showWriteControls

View file

@ -170,7 +170,7 @@ export async function mountApp(
const embeddableEditorIncomingState = stateTransfer?.getIncomingEditorState(APP_ID);
addHelpMenuToAppChrome(coreStart.chrome, coreStart.docLinks);
if (!lensServices.application.capabilities.visualize_v2?.save) {
if (!lensServices.application.capabilities.visualize_v2.save) {
coreStart.chrome.setBadge({
text: i18n.translate('xpack.lens.badge.readOnly.text', {
defaultMessage: 'Read only',

View file

@ -164,7 +164,7 @@ export function SaveModalContainer({
}
const savingToLibraryPermitted = Boolean(
isSaveable && application.capabilities.visualize_v2?.save
isSaveable && application.capabilities.visualize_v2.save
);
return (

View file

@ -189,8 +189,8 @@ function loadViewUnderlyingDataArgs(
activeData,
capabilities: {
canSaveDashboards: Boolean(capabilities.dashboard_v2?.showWriteControls),
canSaveVisualizations: Boolean(capabilities.visualize_v2?.save),
canOpenVisualizations: Boolean(capabilities.visualize_v2?.show),
canSaveVisualizations: Boolean(capabilities.visualize_v2.save),
canOpenVisualizations: Boolean(capabilities.visualize_v2.show),
navLinks: capabilities.navLinks,
discover_v2: capabilities.discover_v2,
},

View file

@ -211,10 +211,10 @@ export function initializeEditApi(
return false;
}
return (
Boolean(capabilities.visualize_v2?.save) ||
Boolean(capabilities.visualize_v2.save) ||
(!getState().savedObjectId &&
Boolean(capabilities.dashboard_v2?.showWriteControls) &&
Boolean(capabilities.visualize_v2?.show))
Boolean(capabilities.visualize_v2.show))
);
};

View file

@ -17,7 +17,7 @@ export const convertToLensActionFactory =
type: ACTION_CONVERT_TO_LENS,
id,
getDisplayName: () => displayName,
isCompatible: async () => !!application.capabilities.visualize_v2?.show,
isCompatible: async () => !!application.capabilities.visualize_v2.show,
execute: async (context: { [key: string]: VisualizeEditorContext }) => {
const table = Object.values(context.layers);
const payload = {

View file

@ -22,7 +22,7 @@ export const visualizeDashboardVisualizePanelction = (application: ApplicationSt
i18n.translate('xpack.lens.visualizeLegacyVisualizationChart', {
defaultMessage: 'Visualize legacy visualization chart',
}),
isCompatible: async () => !!application.capabilities.visualize_v2?.show,
isCompatible: async () => !!application.capabilities.visualize_v2.show,
execute: async (context: { [key: string]: VisualizeEditorContext }) => {
const table = Object.values(context.layers);
const payload = {

View file

@ -22,7 +22,7 @@ export const visualizeAggBasedVisAction = (application: ApplicationStart) =>
i18n.translate('xpack.lens.visualizeAggBasedLegend', {
defaultMessage: 'Visualize agg based chart',
}),
isCompatible: async () => !!application.capabilities.visualize_v2?.show,
isCompatible: async () => !!application.capabilities.visualize_v2.show,
execute: async (context: { [key: string]: VisualizeEditorContext }) => {
const table = Object.values(context.layers);
const payload = {

View file

@ -5,14 +5,8 @@
* 2.0.
*/
import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core-plugins-server';
import type { PluginInitializerContext } from '@kbn/core-plugins-server';
export type { LensServerPluginSetup } from './plugin';
import type { ConfigType } from '../common/config';
import { ConfigSchema } from '../common/config';
export const config: PluginConfigDescriptor<ConfigType> = {
schema: ConfigSchema,
};
export const plugin = async (initContext: PluginInitializerContext) => {
const { LensServerPlugin } = await import('./plugin');

View file

@ -51,7 +51,7 @@ export interface LensServerPluginSetup {
/**
* Server side embeddable definition which provides migrations to run if Lens state is embedded into another saved object somewhere
*/
lensEmbeddableFactory: ReturnType<typeof makeLensEmbeddableFactory> | undefined;
lensEmbeddableFactory: ReturnType<typeof makeLensEmbeddableFactory>;
/**
* Register custom migration functions for custom third party Lens visualizations
*/

View file

@ -17,6 +17,7 @@
"requiredPlugins": [
"controls",
"unifiedSearch",
"lens",
"licensing",
"features",
"inspector",
@ -26,6 +27,7 @@
"uiActions",
"navigation",
"expressions",
"visualizations",
"embeddable",
"mapsEms",
"share",
@ -37,26 +39,22 @@
"customIntegrations",
"embeddableEnhanced",
"home",
"lens",
"savedObjectsTagging",
"charts",
"screenshotMode",
"security",
"spaces",
"usageCollection",
"serverless",
"visualizations"
"serverless"
],
"requiredBundles": [
"kibanaReact",
"kibanaUtils",
"lens",
"usageCollection",
"unifiedSearch",
"fieldFormats",
"esql",
"savedObjects",
"visualizations"
"savedObjects"
],
"extraPublicDirs": [
"common"

View file

@ -93,7 +93,7 @@ export interface MapsPluginSetupDependencies {
inspector: InspectorSetupContract;
home?: HomePublicPluginSetup;
lens: LensPublicSetup;
visualizations?: VisualizationsSetup;
visualizations: VisualizationsSetup;
embeddable: EmbeddableSetup;
share: SharePluginSetup;
licensing: LicensingPluginSetup;
@ -188,7 +188,7 @@ export class MapsPlugin
if (plugins.home) {
plugins.home.featureCatalogue.register(featureCatalogueEntry);
}
plugins.visualizations?.registerAlias(mapsVisTypeAlias);
plugins.visualizations.registerAlias(mapsVisTypeAlias);
core.application.register({
id: APP_ID,
@ -230,10 +230,10 @@ export class MapsPlugin
plugins.data.search.aggs.types.registerLegacy(GEOHASH_GRID, getGeoHashBucketAgg);
plugins.expressions.registerFunction(createRegionMapFn);
plugins.expressions.registerRenderer(regionMapRenderer);
plugins.visualizations?.createBaseVisualization(regionMapVisType);
plugins.visualizations.createBaseVisualization(regionMapVisType);
plugins.expressions.registerFunction(createTileMapFn);
plugins.expressions.registerRenderer(tileMapRenderer);
plugins.visualizations?.createBaseVisualization(tileMapVisType);
plugins.visualizations.createBaseVisualization(tileMapVisType);
setIsCloudEnabled(!!plugins.cloud?.isCloudEnabled);

View file

@ -36,7 +36,7 @@ export function initializeEditApi(
});
},
isEditingEnabled: () => {
return getMapsCapabilities()?.save as boolean;
return getMapsCapabilities().save as boolean;
},
getEditHref: async () => {
return getHttp().basePath.prepend(getFullPath(savedObjectId));

View file

@ -36,7 +36,7 @@ export function initializeLibraryTransforms(
return {
canLinkToLibrary: async () => {
const { maps_v2: maps } = getCore().application.capabilities;
return maps?.save && savedMap.getSavedObjectId() === undefined;
return maps.save && savedMap.getSavedObjectId() === undefined;
},
saveToLibrary: async (title: string) => {
const state = serializeState();

View file

@ -50,7 +50,7 @@ export const DEFAULT_MAP_UI_STATE = {
flyoutDisplay: FLYOUT_STATE.NONE,
drawMode: DRAW_MODE.NONE,
isFullScreen: false,
isReadOnly: !getMapsCapabilities()?.save,
isReadOnly: !getMapsCapabilities().save,
isLayerTOCOpen: DEFAULT_IS_LAYER_TOC_OPEN,
isTimesliderOpen: false,
// storing TOC detail visibility outside of map.layerList because its UI state and not map rendering state.

View file

@ -29,7 +29,7 @@ import { registerLayerWizards } from './classes/layers/wizards/load_layer_wizard
import { MapSerializedState } from './react_embeddable/types';
function setAppChrome() {
if (!getMapsCapabilities()?.save) {
if (!getMapsCapabilities().save) {
getCoreChrome().setBadge({
text: i18n.translate('xpack.maps.badge.readOnly.text', {
defaultMessage: 'Read only',

View file

@ -69,7 +69,7 @@ function MapsListViewComp({ history }: Props) {
page: 'list',
});
const isReadOnly = !getMapsCapabilities()?.save;
const isReadOnly = !getMapsCapabilities().save;
const initialPageSize = getUiSettings().get(SAVED_OBJECTS_PER_PAGE_SETTING);
// TLDR; render should be side effect free

View file

@ -112,7 +112,7 @@ export function getTopNavConfig({
});
}
if (getMapsCapabilities()?.save) {
if (getMapsCapabilities().save) {
const hasSaveAndReturnConfig = savedMap.hasSaveAndReturnConfig();
const mapDescription = savedMap.getAttributes().description
? savedMap.getAttributes().description!

View file

@ -26,7 +26,7 @@ export const visualizeGeoFieldAction = createAction<VisualizeFieldContext>({
defaultMessage: 'Visualize in Maps',
}),
isCompatible: async (context) => {
return Boolean(!!getVisualizeCapabilities()?.show && context.dataViewSpec && context.fieldName);
return Boolean(!!getVisualizeCapabilities().show && context.dataViewSpec && context.fieldName);
},
getHref: async (context) => {
const { app, path } = await getMapsLink(context);

View file

@ -13,7 +13,6 @@ export interface MapsConfigType {
}
export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
// flag used in functional testing
showMapsInspectorAdapter: schema.boolean({ defaultValue: false }),
// flag used in functional testing

View file

@ -22,6 +22,7 @@
"embeddable",
"features",
"fieldFormats",
"lens",
"licensing",
"share",
"taskManager",
@ -38,7 +39,6 @@
"alerting",
"dashboard",
"home",
"lens",
"licenseManagement",
"management",
"maps",

View file

@ -29,6 +29,7 @@
"dashboard",
"licensing",
"expressions",
"lens",
"controls",
"embeddable",
"fieldsMetadata",
@ -38,7 +39,6 @@
"cloud",
"features",
"home",
"lens",
"spaces",
"serverless",
"share"

View file

@ -23,6 +23,7 @@
"features",
"files",
"inspector",
"lens",
"observabilityShared",
"security",
"share",
@ -33,7 +34,6 @@
"discover",
"embeddable",
"home",
"lens",
"licensing",
"spaces",
"usageCollection",

View file

@ -23,6 +23,7 @@
"embeddable",
"features",
"fieldFormats",
"lens",
"logsShared",
"metricsDataAccess",
"observability",
@ -41,7 +42,6 @@
"fieldsMetadata"
],
"optionalPlugins": [
"lens",
"spaces",
"ml",
"home",

View file

@ -32,12 +32,14 @@
"features",
"files",
"inspector",
"lens",
"observabilityShared",
"ruleRegistry",
"triggersActionsUi",
"security",
"share",
"unifiedSearch",
"visualizations",
"dashboard",
"expressions",
"logsShared",
@ -48,7 +50,6 @@
"optionalPlugins": [
"discover",
"home",
"lens",
"usageCollection",
"cloud",
"spaces",
@ -56,8 +57,7 @@
"guidedOnboarding",
"observabilityAIAssistant",
"investigate",
"streams",
"visualizations"
"streams"
],
"requiredBundles": [
"data",

View file

@ -22,6 +22,7 @@
"actions",
"data",
"dataViews",
"lens",
"ruleRegistry",
"uiActions",
"triggersActionsUi",
@ -37,8 +38,7 @@
"llmTasks"
],
"optionalPlugins": [
"cloud",
"lens"
"cloud"
],
"requiredBundles": [
"kibanaReact",

View file

@ -28,15 +28,15 @@
"searchprofiler",
"security",
"serverless",
"share"
"share",
"visualizations"
],
"optionalPlugins": [
"indexManagement",
"contentConnectors",
"searchInferenceEndpoints",
"searchPlayground",
"usageCollection",
"visualizations"
"usageCollection"
],
"requiredBundles": [
"kibanaReact"

View file

@ -31,7 +31,9 @@
"features",
"fieldFormats",
"inspector",
"lens",
"licensing",
"maps",
"navigation",
"ruleRegistry",
"sessionView",
@ -68,9 +70,7 @@
"usageCollection",
"lists",
"home",
"lens",
"management",
"maps",
"dataViewFieldEditor",
"osquery",
"savedObjectsTaggingOss",
@ -84,12 +84,10 @@
"kibanaUtils",
"kibanaReact",
"usageCollection",
"lens",
"lists",
"ml",
"unifiedSearch",
"esql",
"maps"
"esql"
],
"extraPublicDirs": [
"common"

View file

@ -1,30 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { login } from '../../../tasks/login';
import { visit } from '../../../tasks/navigation';
import { APP_NOT_FOUND_PAGE } from '../../../screens/ai_soc';
import { VISUALIZE_URL, MAPS_URL, LENS_URL } from '../../../urls/navigation';
describe('Disabled features', { tags: '@serverless' }, () => {
beforeEach(() => {
login('admin');
});
it('visualize app should not be available', () => {
visit(VISUALIZE_URL);
cy.get(APP_NOT_FOUND_PAGE).should('exist');
});
it('maps app should not be available', () => {
visit(MAPS_URL);
cy.get(APP_NOT_FOUND_PAGE).should('exist');
});
it('lens app should not be available', () => {
visit(LENS_URL);
cy.get(APP_NOT_FOUND_PAGE).should('exist');
});
});

View file

@ -86,6 +86,7 @@ describe('Capabilities', { tags: '@serverless' }, () => {
after(() => role.teardown());
// Individual test cases with clear descriptions
it('should show alert summary prompt when visiting alert summary page', () => {
visit(ALERT_SUMMARY_URL);
cy.get(ALERTS_SUMMARY_PROMPT).should('exist');

View file

@ -4,12 +4,3 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
export const ConfigSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
});
export type ConfigType = TypeOf<typeof ConfigSchema>;

View file

@ -9,4 +9,3 @@ export const ALERTS_SUMMARY_PROMPT = '[data-test-subj="alert-summary-landing-pag
export const GET_STARTED_PAGE = '[data-test-subj="onboarding-hub-page"]';
export const AI_SOC_NAVIGATION =
'[data-test-subj="nav-item nav-item-security_solution_ai_nav nav-item-id-security_solution_ai_nav"]';
export const APP_NOT_FOUND_PAGE = '[data-test-subj="appNotFoundPageContent"]';

View file

@ -91,9 +91,6 @@ export const exceptionsListDetailsUrl = (listId: string) =>
export const DISCOVER_URL = '/app/discover';
export const OSQUERY_URL = '/app/osquery';
export const FLEET_URL = '/app/fleet';
export const VISUALIZE_URL = '/app/visualize';
export const MAPS_URL = '/app/maps';
export const LENS_URL = '/app/lens';
// Entity Analytics
export const ENTITY_ANALYTICS_DASHBOARD_URL = '/app/security/entity_analytics';