mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
This PR adds a new feature for streams to control whether the UI and API is available. Changes: * Add the feature with two privileges (`show` and `manage_assets`) * Can be configured with the classic `none`/`read`/`all` so it's automatically aligned with serverless editor/viewer permissions * None also means the app is not shown - to do this, the existing `status$` observable also looks for at least the `streams.show` capability * Only guards changes to the linked dashboards - changes to the Elasticsearch level are still delegated to the Elasticsearch-level permissions of the user * This happens on the UI level (disabled button and dashboard selection on the dashboard page) * and on the API level (all endpoints that can change linked dashboards require the permission) # Questions * Not sure about the name `manage_assets` - maybe it should be something else * Not sure about how the queries stuff should work - @kdelemme anything we should do in this area? --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
156 lines
4.9 KiB
TypeScript
156 lines
4.9 KiB
TypeScript
/*
|
|
* 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 {
|
|
CoreSetup,
|
|
CoreStart,
|
|
DEFAULT_APP_CATEGORIES,
|
|
KibanaRequest,
|
|
Logger,
|
|
Plugin,
|
|
PluginConfigDescriptor,
|
|
PluginInitializerContext,
|
|
} from '@kbn/core/server';
|
|
import { registerRoutes } from '@kbn/server-route-repository';
|
|
import { KibanaFeatureScope } from '@kbn/features-plugin/common';
|
|
import { i18n } from '@kbn/i18n';
|
|
import { StreamsConfig, configSchema, exposeToBrowserConfig } from '../common/config';
|
|
import { streamsRouteRepository } from './routes';
|
|
import {
|
|
StreamsPluginSetupDependencies,
|
|
StreamsPluginStartDependencies,
|
|
StreamsServer,
|
|
} from './types';
|
|
import { AssetService } from './lib/streams/assets/asset_service';
|
|
import { RouteHandlerScopedClients } from './routes/types';
|
|
import { StreamsService } from './lib/streams/service';
|
|
import { StreamsTelemetryService } from './lib/telemetry/service';
|
|
import { STREAMS_API_PRIVILEGES, STREAMS_UI_PRIVILEGES } from '../common/constants';
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
export interface StreamsPluginSetup {}
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
export interface StreamsPluginStart {}
|
|
|
|
export const config: PluginConfigDescriptor<StreamsConfig> = {
|
|
schema: configSchema,
|
|
exposeToBrowser: exposeToBrowserConfig,
|
|
};
|
|
|
|
export class StreamsPlugin
|
|
implements
|
|
Plugin<
|
|
StreamsPluginSetup,
|
|
StreamsPluginStart,
|
|
StreamsPluginSetupDependencies,
|
|
StreamsPluginStartDependencies
|
|
>
|
|
{
|
|
public config: StreamsConfig;
|
|
public logger: Logger;
|
|
public server?: StreamsServer;
|
|
private isDev: boolean;
|
|
private telemtryService = new StreamsTelemetryService();
|
|
|
|
constructor(context: PluginInitializerContext<StreamsConfig>) {
|
|
this.isDev = context.env.mode.dev;
|
|
this.config = context.config.get();
|
|
this.logger = context.logger.get();
|
|
}
|
|
|
|
public setup(
|
|
core: CoreSetup<StreamsPluginStartDependencies>,
|
|
plugins: StreamsPluginSetupDependencies
|
|
): StreamsPluginSetup {
|
|
this.server = {
|
|
config: this.config,
|
|
logger: this.logger,
|
|
} as StreamsServer;
|
|
|
|
this.telemtryService.setup(core.analytics);
|
|
|
|
const assetService = new AssetService(core, this.logger);
|
|
const streamsService = new StreamsService(core, this.logger, this.isDev);
|
|
|
|
plugins.features.registerKibanaFeature({
|
|
id: 'streams',
|
|
name: i18n.translate('xpack.streams.featureRegistry.streamsFeatureName', {
|
|
defaultMessage: 'Streams',
|
|
}),
|
|
order: 600,
|
|
category: DEFAULT_APP_CATEGORIES.observability,
|
|
scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security],
|
|
app: ['streams'],
|
|
privileges: {
|
|
all: {
|
|
app: ['streams'],
|
|
savedObject: {
|
|
all: [],
|
|
read: [],
|
|
},
|
|
api: [STREAMS_API_PRIVILEGES.read, STREAMS_API_PRIVILEGES.manage],
|
|
ui: [STREAMS_UI_PRIVILEGES.show, STREAMS_UI_PRIVILEGES.manage],
|
|
},
|
|
read: {
|
|
app: ['streams'],
|
|
savedObject: {
|
|
all: [],
|
|
read: [],
|
|
},
|
|
api: [STREAMS_API_PRIVILEGES.read],
|
|
ui: [STREAMS_UI_PRIVILEGES.show],
|
|
},
|
|
},
|
|
});
|
|
|
|
registerRoutes({
|
|
repository: streamsRouteRepository,
|
|
dependencies: {
|
|
assets: assetService,
|
|
server: this.server,
|
|
telemetry: this.telemtryService.getClient(),
|
|
getScopedClients: async ({
|
|
request,
|
|
}: {
|
|
request: KibanaRequest;
|
|
}): Promise<RouteHandlerScopedClients> => {
|
|
const [[coreStart, pluginsStart], assetClient] = await Promise.all([
|
|
core.getStartServices(),
|
|
assetService.getClientWithRequest({ request }),
|
|
]);
|
|
|
|
const streamsClient = await streamsService.getClientWithRequest({ request, assetClient });
|
|
|
|
const scopedClusterClient = coreStart.elasticsearch.client.asScoped(request);
|
|
const soClient = coreStart.savedObjects.getScopedClient(request);
|
|
const inferenceClient = pluginsStart.inference.getClient({ request });
|
|
|
|
return { scopedClusterClient, soClient, assetClient, streamsClient, inferenceClient };
|
|
},
|
|
},
|
|
core,
|
|
logger: this.logger,
|
|
runDevModeChecks: this.isDev,
|
|
});
|
|
|
|
return {};
|
|
}
|
|
|
|
public start(core: CoreStart, plugins: StreamsPluginStartDependencies): StreamsPluginStart {
|
|
if (this.server) {
|
|
this.server.core = core;
|
|
this.server.isServerless = core.elasticsearch.getCapabilities().serverless;
|
|
this.server.security = plugins.security;
|
|
this.server.encryptedSavedObjects = plugins.encryptedSavedObjects;
|
|
this.server.taskManager = plugins.taskManager;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
public stop() {}
|
|
}
|