kibana/x-pack/plugins/spaces/server/plugin.ts
Larry Gregory 9c2fa892ca
[7.x] Spaces - Client NP Migration, Phase 1 (#40856) (#53113)
* Spaces - Client NP Migration, Phase 1 (#40856)

* shimming NP for spaces client-side plugin

* refresh active space in nav control when updated

* fix advanced settings screen

* allow npStart from unauthed routes

* use NP for deriving space management url

* remove security's usage of SpacesManager

* remove usages of ui/capabilities

* fix tests

* implement NP plugin interface

* remove hack in favor of convention in migration guide

* shim feature catalogue registration

* streamline nav control, and handle async loading more gracefully

* adding opaqueId

* fixes from merge

* fix merge from master

* fixing merge from master

* move _active_space route to NP

* moving to the NP feature catalogue registry

* moving setup to setup phase

* optimizing active space retrieval

* reverting test isolation change

* Apply suggestions from code review

Co-Authored-By: Aleh Zasypkin <aleh.zasypkin@gmail.com>

* removing unnecessary PluginInitializerContext

* updating advanced settings subtitle

* using NP anonymousPaths service

* additional nav_control_popover cleanup

* additional cleanup

* testing out onActiveSpaceChange$ property

* make the linter happy

* make the type checker happy

* fixing types

* fix merge from master

* spaces LP init should run on all pages, not just the kibana app

* address nits

* fix infra/logs, and the spaces disabled scenario

* fix typescript errors

* revert changes to infra plugin

* reintroducing activeSpace injected var for legacy plugins

* fixing react deprecation warning and unhandled promise rejection

* restore activeSpace default var

* spaces does not need to check its own enabled status

* fix from merge

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

* fix backport merge
2019-12-16 12:13:05 -05:00

206 lines
6.8 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;
* you may not use this file except in compliance with the Elastic License.
*/
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { HomeServerPluginSetup } from 'src/plugins/home/server';
import {
SavedObjectsLegacyService,
CoreSetup,
Logger,
PluginInitializerContext,
} from '../../../../src/core/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
import { PluginSetupContract as SecurityPluginSetup } from '../../security/server';
import { LicensingPluginSetup } from '../../licensing/server';
import { XPackMainPlugin } from '../../../legacy/plugins/xpack_main/xpack_main';
import { createDefaultSpace } from './lib/create_default_space';
// @ts-ignore
import { AuditLogger } from '../../../../server/lib/audit_logger';
import { spacesSavedObjectsClientWrapperFactory } from './lib/saved_objects_client/saved_objects_client_wrapper_factory';
import { SpacesAuditLogger } from './lib/audit_logger';
import { createSpacesTutorialContextFactory } from './lib/spaces_tutorial_context_factory';
import { registerSpacesUsageCollector } from './lib/spaces_usage_collector';
import { SpacesService } from './spaces_service';
import { SpacesServiceSetup } from './spaces_service/spaces_service';
import { ConfigType } from './config';
import { toggleUICapabilities } from './lib/toggle_ui_capabilities';
import { initSpacesRequestInterceptors } from './lib/request_interceptors';
import { initExternalSpacesApi } from './routes/api/external';
import { initInternalSpacesApi } from './routes/api/internal';
/**
* Describes a set of APIs that is available in the legacy platform only and required by this plugin
* to function properly.
*/
export interface LegacyAPI {
savedObjects: SavedObjectsLegacyService;
tutorial: {
addScopedTutorialContextFactory: (factory: any) => void;
};
auditLogger: {
create: (pluginId: string) => AuditLogger;
};
legacyConfig: {
kibanaIndex: string;
};
xpackMain: XPackMainPlugin;
}
export interface PluginsSetup {
features: FeaturesPluginSetup;
licensing: LicensingPluginSetup;
security?: SecurityPluginSetup;
usageCollection?: UsageCollectionSetup;
home?: HomeServerPluginSetup;
}
export interface SpacesPluginSetup {
spacesService: SpacesServiceSetup;
__legacyCompat: {
registerLegacyAPI: (legacyAPI: LegacyAPI) => void;
// TODO: We currently need the legacy plugin to inform this plugin when it is safe to create the default space.
// The NP does not have the equivilent ES connection/health/comapt checks that the legacy world does.
// See: https://github.com/elastic/kibana/issues/43456
createDefaultSpace: () => Promise<void>;
};
}
export class Plugin {
private readonly pluginId = 'spaces';
private readonly config$: Observable<ConfigType>;
private readonly log: Logger;
private legacyAPI?: LegacyAPI;
private readonly getLegacyAPI = () => {
if (!this.legacyAPI) {
throw new Error('Legacy API is not registered!');
}
return this.legacyAPI;
};
private spacesAuditLogger?: SpacesAuditLogger;
private readonly getSpacesAuditLogger = () => {
if (!this.spacesAuditLogger) {
this.spacesAuditLogger = new SpacesAuditLogger(
this.getLegacyAPI().auditLogger.create(this.pluginId)
);
}
return this.spacesAuditLogger;
};
constructor(initializerContext: PluginInitializerContext) {
this.config$ = initializerContext.config.create<ConfigType>();
this.log = initializerContext.logger.get();
}
public async start() {}
public async setup(core: CoreSetup, plugins: PluginsSetup): Promise<SpacesPluginSetup> {
const service = new SpacesService(this.log, this.getLegacyAPI);
const spacesService = await service.setup({
http: core.http,
elasticsearch: core.elasticsearch,
authorization: plugins.security ? plugins.security.authz : null,
getSpacesAuditLogger: this.getSpacesAuditLogger,
config$: this.config$,
});
const externalRouter = core.http.createRouter();
initExternalSpacesApi({
externalRouter,
log: this.log,
getSavedObjects: () => this.getLegacyAPI().savedObjects,
spacesService,
});
const internalRouter = core.http.createRouter();
initInternalSpacesApi({
internalRouter,
spacesService,
});
initSpacesRequestInterceptors({
http: core.http,
log: this.log,
getLegacyAPI: this.getLegacyAPI,
spacesService,
features: plugins.features,
});
core.capabilities.registerSwitcher(async (request, uiCapabilities) => {
try {
const activeSpace = await spacesService.getActiveSpace(request);
const features = plugins.features.getFeatures();
return toggleUICapabilities(features, uiCapabilities, activeSpace);
} catch (e) {
return uiCapabilities;
}
});
if (plugins.security) {
plugins.security.registerSpacesService(spacesService);
}
if (plugins.home) {
plugins.home.tutorials.addScopedTutorialContextFactory(
createSpacesTutorialContextFactory(spacesService)
);
}
return {
spacesService,
__legacyCompat: {
registerLegacyAPI: (legacyAPI: LegacyAPI) => {
this.legacyAPI = legacyAPI;
this.setupLegacyComponents(
spacesService,
plugins.features,
plugins.licensing,
plugins.usageCollection
);
},
createDefaultSpace: async () => {
const esClient = await core.elasticsearch.adminClient$.pipe(take(1)).toPromise();
return createDefaultSpace({
esClient,
savedObjects: this.getLegacyAPI().savedObjects,
});
},
},
};
}
public stop() {}
private setupLegacyComponents(
spacesService: SpacesServiceSetup,
featuresSetup: FeaturesPluginSetup,
licensingSetup: LicensingPluginSetup,
usageCollectionSetup?: UsageCollectionSetup
) {
const legacyAPI = this.getLegacyAPI();
const { addScopedSavedObjectsClientWrapperFactory, types } = legacyAPI.savedObjects;
addScopedSavedObjectsClientWrapperFactory(
Number.MIN_SAFE_INTEGER,
'spaces',
spacesSavedObjectsClientWrapperFactory(spacesService, types)
);
legacyAPI.tutorial.addScopedTutorialContextFactory(
createSpacesTutorialContextFactory(spacesService)
);
// Register a function with server to manage the collection of usage stats
registerSpacesUsageCollector(usageCollectionSetup, {
kibanaIndex: legacyAPI.legacyConfig.kibanaIndex,
features: featuresSetup,
licensing: licensingSetup,
});
}
}