[Custom Branding] Plugin skeleton (#145225)

## Summary

This is a skeleton plugin for custom branding. It contains license
checking so far, but not much else.


### Checklist

Delete any items that are not applicable to this PR.

- [X] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [X]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
~- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios~
~- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard
accessibility](https://webaim.org/techniques/keyboard/))~
~- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~
~- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~
~- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))~
~- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Maja Grubic 2022-11-22 15:04:18 +01:00 committed by GitHub
parent 2e178f8f45
commit 0c178e4b80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 306 additions and 0 deletions

View file

@ -464,6 +464,11 @@ The plugin exposes the static DefaultEditorController class to consume.
|You can run a local cluster and simulate a remote cluster within a single Kibana directory.
|{kib-repo}blob/{branch}/x-pack/plugins/custom_branding/README.md[customBranding]
|This is a plugin to configure custom branding.
This plugin is currently under active development; do not use.
|<<dashboard-enhanced-plugin>>
|Adds drilldown capabilities to dashboard. Owned by the Kibana App team.

View file

@ -20,6 +20,7 @@ pageLoadAssetSize:
controls: 40000
core: 435325
crossClusterReplication: 65408
customBranding: 16693
customIntegrations: 22034
dashboard: 82025
dashboardEnhanced: 65646

View file

@ -1050,6 +1050,8 @@
"@kbn/cloud-plugin/*": ["x-pack/plugins/cloud/*"],
"@kbn/cross-cluster-replication-plugin": ["x-pack/plugins/cross_cluster_replication"],
"@kbn/cross-cluster-replication-plugin/*": ["x-pack/plugins/cross_cluster_replication/*"],
"@kbn/custom-branding-plugin": ["x-pack/plugins/custom_branding"],
"@kbn/custom-branding-plugin/*": ["x-pack/plugins/custom_branding/*"],
"@kbn/dashboard-enhanced-plugin": ["x-pack/plugins/dashboard_enhanced"],
"@kbn/dashboard-enhanced-plugin/*": ["x-pack/plugins/dashboard_enhanced/*"],
"@kbn/data-visualizer-plugin": ["x-pack/plugins/data_visualizer"],

View file

@ -13,6 +13,7 @@
"xpack.cloudChat": "plugins/cloud_integrations/cloud_chat",
"xpack.cloudLinks": "plugins/cloud_integrations/cloud_links",
"xpack.csp": "plugins/cloud_security_posture",
"xpack.customBranding": "plugins/custom_branding",
"xpack.dashboard": "plugins/dashboard_enhanced",
"xpack.discover": "plugins/discover_enhanced",
"xpack.crossClusterReplication": "plugins/cross_cluster_replication",

View file

@ -0,0 +1,10 @@
# customBranding
## !! UNDER DEVELOPMENT !!
This is a plugin to configure custom branding.
This plugin is currently under active development; do not use.
---
## Development
See the [kibana contributing guide](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md) for instructions setting up your development environment.

View file

@ -0,0 +1,18 @@
/*
* 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 type { LicenseType } from '@kbn/licensing-plugin/common/types';
export const PLUGIN = {
ID: 'customBranding',
MINIMUM_LICENSE_REQUIRED: 'enterprise' as LicenseType,
getI18nName: (i18n: any): string => {
return i18n.translate('xpack.customBranding.appName', {
defaultMessage: 'Custom Branding',
});
},
};

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
export interface CustomBrandingInfoResponse {
allowed: boolean;
}

View file

@ -0,0 +1,14 @@
{
"id": "customBranding",
"version": "1.0.0",
"kibanaVersion": "kibana",
"owner": {
"name": "global-experience",
"githubTeam": "kibana-global-experience"
},
"description": " Enables customization of Kibana",
"server": true,
"ui": true,
"requiredPlugins": ["licensing", "licenseApiGuard"],
"optionalPlugins": []
}

View file

@ -0,0 +1,23 @@
/*
* 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 React from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreStart } from '@kbn/core/public';
import { CustomBrandingApp } from './components/app';
export const renderApp = (
{ notifications, http }: CoreStart,
{ appBasePath, element }: AppMountParameters
) => {
ReactDOM.render(
<CustomBrandingApp basename={appBasePath} notifications={notifications} http={http} />,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
};

View file

@ -0,0 +1,20 @@
/*
* 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 React from 'react';
import { CoreStart } from '@kbn/core/public';
interface CustomBrandingAppDeps {
basename: string;
notifications: CoreStart['notifications'];
http: CoreStart['http'];
}
export const CustomBrandingApp = (props: CustomBrandingAppDeps) => {
return <div>Hello</div>;
};

View file

@ -0,0 +1,14 @@
/*
* 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 { CustomBrandingPlugin } from './plugin';
// This exports static code and TypeScript types,
// as well as, Kibana Platform `plugin()` initializer.
export function plugin() {
return new CustomBrandingPlugin();
}

View file

@ -0,0 +1,23 @@
/*
* 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, Plugin } from '@kbn/core/public';
import { CustomBrandingPluginSetup, CustomBrandingPluginStart } from './types';
export class CustomBrandingPlugin
implements Plugin<CustomBrandingPluginSetup, CustomBrandingPluginStart>
{
public setup(core: CoreSetup): CustomBrandingPluginSetup {
return {};
}
public start(core: CoreStart): CustomBrandingPluginStart {
return {};
}
public stop() {}
}

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CustomBrandingPluginSetup {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CustomBrandingPluginStart {}

View file

@ -0,0 +1,14 @@
/*
* 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 { PluginInitializerContext } from '@kbn/core/server';
import { CustomBrandingPlugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new CustomBrandingPlugin(initializerContext);
}

View file

@ -0,0 +1,48 @@
/*
* 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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server';
import { i18n } from '@kbn/i18n';
import { License } from '@kbn/license-api-guard-plugin/server';
import { PLUGIN } from '../common/constants';
import { Dependencies } from './types';
import { registerRoutes } from './routes';
import type { CustomBrandingRequestHandlerContext } from './types';
export class CustomBrandingPlugin implements Plugin {
private readonly license: License;
private readonly logger: Logger;
constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
this.license = new License();
}
public setup(core: CoreSetup) {
this.logger.debug('customBranding: Setup');
this.license.setup({
pluginName: PLUGIN.getI18nName(i18n),
logger: this.logger,
});
const router = core.http.createRouter<CustomBrandingRequestHandlerContext>();
registerRoutes(router);
return {};
}
public start(core: CoreStart, { licensing }: Dependencies) {
this.logger.debug('customBranding: Started');
this.license.start({
pluginId: PLUGIN.ID,
minimumLicenseType: PLUGIN.MINIMUM_LICENSE_REQUIRED,
licensing,
});
return {};
}
public stop() {}
}

View file

@ -0,0 +1,13 @@
/*
* 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 { registerInfoRoute } from './info';
import { CustomBrandingRouter } from '../types';
export const registerRoutes = (router: CustomBrandingRouter) => {
registerInfoRoute(router);
};

View file

@ -0,0 +1,39 @@
/*
* 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 { ILicense } from '@kbn/licensing-plugin/server';
import { CustomBrandingInfoResponse } from '../../common/types';
import { CustomBrandingRouter } from '../types';
export const registerInfoRoute = (router: CustomBrandingRouter) => {
router.get(
{
path: '/api/custom_branding/info',
validate: false,
options: {
authRequired: 'optional',
},
},
async (ctx, req, res) => {
const allowed = isValidLicense((await ctx.licensing).license);
if (!allowed) {
return res.forbidden();
}
return res.ok({
body: {
allowed,
} as CustomBrandingInfoResponse,
});
}
);
};
const isValidLicense = (license: ILicense): boolean => {
return license.hasAtLeast('enterprise');
};

View file

@ -0,0 +1,22 @@
/*
* 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 {
LicensingApiRequestHandlerContext,
LicensingPluginStart,
} from '@kbn/licensing-plugin/server';
import { CustomRequestHandlerContext } from '@kbn/core-http-request-handler-context-server';
import { IRouter } from '@kbn/core/server';
export interface Dependencies {
licensing: LicensingPluginStart;
}
export type CustomBrandingRequestHandlerContext = CustomRequestHandlerContext<{
licensing: LicensingApiRequestHandlerContext;
}>;
export type CustomBrandingRouter = IRouter<CustomBrandingRequestHandlerContext>;

View file

@ -0,0 +1,19 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./target/types",
"emitDeclarationOnly": true,
"declaration": true,
"isolatedModules": true,
},
"include": [
"public/**/*",
"server/**/*",
"common/**/*"
],
"kbn_references": [
{ "path": "../../../src/core/tsconfig.json" },
{ "path": "../licensing/tsconfig.json" },
{ "path": "../license_api_guard/tsconfig.json" }
]
}