diff --git a/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.getall.md b/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.getall.md new file mode 100644 index 00000000000000..004979977376e6 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.getall.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) > [getAll](./kibana-plugin-core-public.iuisettingsclient.getall.md) + +## IUiSettingsClient.getAll property + +Gets the metadata about all uiSettings, including the type, default value, and user value for each key. + +Signature: + +```typescript +getAll: () => Readonly>; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.md b/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.md new file mode 100644 index 00000000000000..87ef5784a6c6d6 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.iuisettingsclient.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) + +## IUiSettingsClient interface + +Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) + +Signature: + +```typescript +export interface IUiSettingsClient +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [get](./kibana-plugin-core-public.iuisettingsclient.get.md) | <T = any>(key: string, defaultOverride?: T) => T | Gets the value for a specific uiSetting. If this setting has no user-defined value then the defaultOverride parameter is returned (and parsed if setting is of type "json" or "number). If the parameter is not defined and the key is not registered by any plugin then an error is thrown, otherwise reads the default value defined by a plugin. | +| [get$](./kibana-plugin-core-public.iuisettingsclient.get_.md) | <T = any>(key: string, defaultOverride?: T) => Observable<T> | Gets an observable of the current value for a config key, and all updates to that config key in the future. Providing a defaultOverride argument behaves the same as it does in \#get() | +| [getAll](./kibana-plugin-core-public.iuisettingsclient.getall.md) | () => Readonly<Record<string, PublicUiSettingsParams & UserProvidedValues>> | Gets the metadata about all uiSettings, including the type, default value, and user value for each key. | +| [getSaved$](./kibana-plugin-core-public.iuisettingsclient.getsaved_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | +| [getUpdate$](./kibana-plugin-core-public.iuisettingsclient.getupdate_.md) | <T = any>() => Observable<{
key: string;
newValue: T;
oldValue: T;
}> | Returns an Observable that notifies subscribers of each update to the uiSettings, including the key, newValue, and oldValue of the setting that changed. | +| [getUpdateErrors$](./kibana-plugin-core-public.iuisettingsclient.getupdateerrors_.md) | () => Observable<Error> | Returns an Observable that notifies subscribers of each error while trying to update the settings, containing the actual Error class. | +| [isCustom](./kibana-plugin-core-public.iuisettingsclient.iscustom.md) | (key: string) => boolean | Returns true if the setting wasn't registered by any plugin, but was either added directly via set(), or is an unknown setting found in the uiSettings saved object | +| [isDeclared](./kibana-plugin-core-public.iuisettingsclient.isdeclared.md) | (key: string) => boolean | Returns true if the key is a "known" uiSetting, meaning it is either registered by any plugin or was previously added as a custom setting via the set() method. | +| [isDefault](./kibana-plugin-core-public.iuisettingsclient.isdefault.md) | (key: string) => boolean | Returns true if the setting has no user-defined value or is unknown | +| [isOverridden](./kibana-plugin-core-public.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | +| [overrideLocalDefault](./kibana-plugin-core-public.iuisettingsclient.overridelocaldefault.md) | (key: string, newDefault: any) => void | Overrides the default value for a setting in this specific browser tab. If the page is reloaded the default override is lost. | +| [remove](./kibana-plugin-core-public.iuisettingsclient.remove.md) | (key: string) => Promise<boolean> | Removes the user-defined value for a setting, causing it to revert to the default. This method behaves the same as calling set(key, null), including the synchronization, custom setting, and error behavior of that method. | +| [set](./kibana-plugin-core-public.iuisettingsclient.set.md) | (key: string, value: any) => Promise<boolean> | Sets the value for a uiSetting. If the setting is not registered by any plugin it will be stored as a custom setting. The new value will be synchronously available via the get() method and sent to the server in the background. If the request to the server fails then a updateErrors$ will be notified and the setting will be reverted to its value before set() was called. | + diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md new file mode 100644 index 00000000000000..a9fbaa25ea150a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -0,0 +1,163 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) + +## kibana-plugin-core-public package + +The Kibana Core APIs for client-side plugins. + +A plugin's `public/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-core-public.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-core-public.plugin.md). + +The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-core-public.coresetup.md) or [CoreStart](./kibana-plugin-core-public.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. + +## Classes + +| Class | Description | +| --- | --- | +| [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state. The client-side SavedObjectsClient is a thin convenience library around the SavedObjects HTTP API for interacting with Saved Objects. | +| [ScopedHistory](./kibana-plugin-core-public.scopedhistory.md) | A wrapper around a History instance that is scoped to a particular base path of the history stack. Behaves similarly to the basename option except that this wrapper hides any history stack entries from outside the scope of this base path.This wrapper also allows Core and Plugins to share a single underlying global History instance without exposing the history of other applications.The [createSubHistory](./kibana-plugin-core-public.scopedhistory.createsubhistory.md) method is particularly useful for applications that contain any number of "sub-apps" which should not have access to the main application's history or basePath. | +| [SimpleSavedObject](./kibana-plugin-core-public.simplesavedobject.md) | This class is a very simple wrapper for SavedObjects loaded from the server with the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md).It provides basic functionality for creating/saving/deleting saved objects, but doesn't include any type-specific implementations. | +| [ToastsApi](./kibana-plugin-core-public.toastsapi.md) | Methods for adding and removing global toast messages. | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [AppLeaveActionType](./kibana-plugin-core-public.appleaveactiontype.md) | Possible type of actions on application leave. | +| [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | Status of the application's navLink. | +| [AppStatus](./kibana-plugin-core-public.appstatus.md) | Accessibility status of an application. | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [App](./kibana-plugin-core-public.app.md) | Extension of [common app properties](./kibana-plugin-core-public.appbase.md) with the mount function. | +| [AppBase](./kibana-plugin-core-public.appbase.md) | | +| [AppCategory](./kibana-plugin-core-public.appcategory.md) | A category definition for nav links to know where to sort them in the left hand nav | +| [AppLeaveConfirmAction](./kibana-plugin-core-public.appleaveconfirmaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md) to show a confirmation message when trying to leave an application.See | +| [AppLeaveDefaultAction](./kibana-plugin-core-public.appleavedefaultaction.md) | Action to return from a [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md) to execute the default behaviour when leaving the application.See | +| [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | | +| [ApplicationStart](./kibana-plugin-core-public.applicationstart.md) | | +| [AppMountContext](./kibana-plugin-core-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-core-public.coresetup.getstartservices.md). | +| [AppMountParameters](./kibana-plugin-core-public.appmountparameters.md) | | +| [Capabilities](./kibana-plugin-core-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | +| [ChromeBadge](./kibana-plugin-core-public.chromebadge.md) | | +| [ChromeBrand](./kibana-plugin-core-public.chromebrand.md) | | +| [ChromeDocTitle](./kibana-plugin-core-public.chromedoctitle.md) | APIs for accessing and updating the document title. | +| [ChromeHelpExtension](./kibana-plugin-core-public.chromehelpextension.md) | | +| [ChromeNavControl](./kibana-plugin-core-public.chromenavcontrol.md) | | +| [ChromeNavControls](./kibana-plugin-core-public.chromenavcontrols.md) | [APIs](./kibana-plugin-core-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | +| [ChromeNavLink](./kibana-plugin-core-public.chromenavlink.md) | | +| [ChromeNavLinks](./kibana-plugin-core-public.chromenavlinks.md) | [APIs](./kibana-plugin-core-public.chromenavlinks.md) for manipulating nav links. | +| [ChromeRecentlyAccessed](./kibana-plugin-core-public.chromerecentlyaccessed.md) | [APIs](./kibana-plugin-core-public.chromerecentlyaccessed.md) for recently accessed history. | +| [ChromeRecentlyAccessedHistoryItem](./kibana-plugin-core-public.chromerecentlyaccessedhistoryitem.md) | | +| [ChromeStart](./kibana-plugin-core-public.chromestart.md) | ChromeStart allows plugins to customize the global chrome header UI and enrich the UX with additional information about the current location of the browser. | +| [ContextSetup](./kibana-plugin-core-public.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | +| [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | +| [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | +| [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | +| [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) | | +| [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | +| [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | +| [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) | All options that may be used with a [HttpHandler](./kibana-plugin-core-public.httphandler.md). | +| [HttpFetchOptionsWithPath](./kibana-plugin-core-public.httpfetchoptionswithpath.md) | Similar to [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) but with the URL path included. | +| [HttpFetchQuery](./kibana-plugin-core-public.httpfetchquery.md) | | +| [HttpHandler](./kibana-plugin-core-public.httphandler.md) | A function for making an HTTP requests to Kibana's backend. See [HttpFetchOptions](./kibana-plugin-core-public.httpfetchoptions.md) for options and [HttpResponse](./kibana-plugin-core-public.httpresponse.md) for the response. | +| [HttpHeadersInit](./kibana-plugin-core-public.httpheadersinit.md) | Headers to append to the request. Any headers that begin with kbn- are considered private to Core and will cause [HttpHandler](./kibana-plugin-core-public.httphandler.md) to throw an error. | +| [HttpInterceptor](./kibana-plugin-core-public.httpinterceptor.md) | An object that may define global interceptor functions for different parts of the request and response lifecycle. See [IHttpInterceptController](./kibana-plugin-core-public.ihttpinterceptcontroller.md). | +| [HttpInterceptorRequestError](./kibana-plugin-core-public.httpinterceptorrequesterror.md) | | +| [HttpInterceptorResponseError](./kibana-plugin-core-public.httpinterceptorresponseerror.md) | | +| [HttpRequestInit](./kibana-plugin-core-public.httprequestinit.md) | Fetch API options available to [HttpHandler](./kibana-plugin-core-public.httphandler.md)s. | +| [HttpResponse](./kibana-plugin-core-public.httpresponse.md) | | +| [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | +| [I18nStart](./kibana-plugin-core-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. | +| [IAnonymousPaths](./kibana-plugin-core-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication | +| [IBasePath](./kibana-plugin-core-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. | +| [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | +| [IHttpFetchError](./kibana-plugin-core-public.ihttpfetcherror.md) | | +| [IHttpInterceptController](./kibana-plugin-core-public.ihttpinterceptcontroller.md) | Used to halt a request Promise chain in a [HttpInterceptor](./kibana-plugin-core-public.httpinterceptor.md). | +| [IHttpResponseInterceptorOverrides](./kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. | +| [ImageValidation](./kibana-plugin-core-public.imagevalidation.md) | | +| [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) | +| [LegacyCoreSetup](./kibana-plugin-core-public.legacycoresetup.md) | Setup interface exposed to the legacy platform via the ui/new_platform module. | +| [LegacyCoreStart](./kibana-plugin-core-public.legacycorestart.md) | Start interface exposed to the legacy platform via the ui/new_platform module. | +| [LegacyNavLink](./kibana-plugin-core-public.legacynavlink.md) | | +| [NotificationsSetup](./kibana-plugin-core-public.notificationssetup.md) | | +| [NotificationsStart](./kibana-plugin-core-public.notificationsstart.md) | | +| [OverlayBannersStart](./kibana-plugin-core-public.overlaybannersstart.md) | | +| [OverlayRef](./kibana-plugin-core-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-core-public.overlaystart.md) methods for closing a mounted overlay. | +| [OverlayStart](./kibana-plugin-core-public.overlaystart.md) | | +| [PackageInfo](./kibana-plugin-core-public.packageinfo.md) | | +| [Plugin](./kibana-plugin-core-public.plugin.md) | The interface that should be returned by a PluginInitializer. | +| [PluginInitializerContext](./kibana-plugin-core-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer | +| [SavedObject](./kibana-plugin-core-public.savedobject.md) | | +| [SavedObjectAttributes](./kibana-plugin-core-public.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectReference](./kibana-plugin-core-public.savedobjectreference.md) | A reference to another saved object. | +| [SavedObjectsBaseOptions](./kibana-plugin-core-public.savedobjectsbaseoptions.md) | | +| [SavedObjectsBatchResponse](./kibana-plugin-core-public.savedobjectsbatchresponse.md) | | +| [SavedObjectsBulkCreateObject](./kibana-plugin-core-public.savedobjectsbulkcreateobject.md) | | +| [SavedObjectsBulkCreateOptions](./kibana-plugin-core-public.savedobjectsbulkcreateoptions.md) | | +| [SavedObjectsBulkUpdateObject](./kibana-plugin-core-public.savedobjectsbulkupdateobject.md) | | +| [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-public.savedobjectsbulkupdateoptions.md) | | +| [SavedObjectsCreateOptions](./kibana-plugin-core-public.savedobjectscreateoptions.md) | | +| [SavedObjectsFindOptions](./kibana-plugin-core-public.savedobjectsfindoptions.md) | | +| [SavedObjectsFindResponsePublic](./kibana-plugin-core-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | +| [SavedObjectsImportConflictError](./kibana-plugin-core-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | +| [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportMissingReferencesError](./kibana-plugin-core-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | +| [SavedObjectsImportResponse](./kibana-plugin-core-public.savedobjectsimportresponse.md) | The response describing the result of an import. | +| [SavedObjectsImportRetry](./kibana-plugin-core-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | +| [SavedObjectsImportUnknownError](./kibana-plugin-core-public.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | +| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-core-public.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | +| [SavedObjectsMigrationVersion](./kibana-plugin-core-public.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [SavedObjectsStart](./kibana-plugin-core-public.savedobjectsstart.md) | | +| [SavedObjectsUpdateOptions](./kibana-plugin-core-public.savedobjectsupdateoptions.md) | | +| [StringValidationRegex](./kibana-plugin-core-public.stringvalidationregex.md) | StringValidation with regex object | +| [StringValidationRegexString](./kibana-plugin-core-public.stringvalidationregexstring.md) | StringValidation as regex string | +| [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | +| [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | +| [UserProvidedValues](./kibana-plugin-core-public.userprovidedvalues.md) | Describes the values explicitly set by user. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AppLeaveAction](./kibana-plugin-core-public.appleaveaction.md) | Possible actions to return from a [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md)See [AppLeaveConfirmAction](./kibana-plugin-core-public.appleaveconfirmaction.md) and [AppLeaveDefaultAction](./kibana-plugin-core-public.appleavedefaultaction.md) | +| [AppLeaveHandler](./kibana-plugin-core-public.appleavehandler.md) | A handler that will be executed before leaving the application, either when going to another application or when closing the browser tab or manually changing the url. Should return confirm to to prompt a message to the user before leaving the page, or default to keep the default behavior (doing nothing).See [AppMountParameters](./kibana-plugin-core-public.appmountparameters.md) for detailed usage examples. | +| [AppMount](./kibana-plugin-core-public.appmount.md) | A mount function called when the user navigates to this app's route. | +| [AppMountDeprecated](./kibana-plugin-core-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. | +| [AppUnmount](./kibana-plugin-core-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. | +| [AppUpdatableFields](./kibana-plugin-core-public.appupdatablefields.md) | Defines the list of fields that can be updated via an [AppUpdater](./kibana-plugin-core-public.appupdater.md). | +| [AppUpdater](./kibana-plugin-core-public.appupdater.md) | Updater for applications. see [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | +| [ChromeBreadcrumb](./kibana-plugin-core-public.chromebreadcrumb.md) | | +| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-core-public.chromehelpextensionmenucustomlink.md) | | +| [ChromeHelpExtensionMenuDiscussLink](./kibana-plugin-core-public.chromehelpextensionmenudiscusslink.md) | | +| [ChromeHelpExtensionMenuDocumentationLink](./kibana-plugin-core-public.chromehelpextensionmenudocumentationlink.md) | | +| [ChromeHelpExtensionMenuGitHubLink](./kibana-plugin-core-public.chromehelpextensionmenugithublink.md) | | +| [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | +| [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | +| [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-core-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md). | +| [HttpStart](./kibana-plugin-core-public.httpstart.md) | See [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | +| [IContextProvider](./kibana-plugin-core-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | +| [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | +| [MountPoint](./kibana-plugin-core-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | +| [PluginInitializer](./kibana-plugin-core-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. | +| [PluginOpaqueId](./kibana-plugin-core-public.pluginopaqueid.md) | | +| [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | +| [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) | | +| [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | +| [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | +| [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | +| [StringValidation](./kibana-plugin-core-public.stringvalidation.md) | Allows regex objects or a regex string | +| [Toast](./kibana-plugin-core-public.toast.md) | | +| [ToastInput](./kibana-plugin-core-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | +| [ToastInputFields](./kibana-plugin-core-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-core-public.toastinput.md). | +| [ToastsSetup](./kibana-plugin-core-public.toastssetup.md) | [IToasts](./kibana-plugin-core-public.itoasts.md) | +| [ToastsStart](./kibana-plugin-core-public.toastsstart.md) | [IToasts](./kibana-plugin-core-public.itoasts.md) | +| [UiSettingsType](./kibana-plugin-core-public.uisettingstype.md) | UI element type to represent the settings. | +| [UnmountCallback](./kibana-plugin-core-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-core-public.mountpoint.md) | + diff --git a/docs/development/core/public/kibana-plugin-core-public.publicuisettingsparams.md b/docs/development/core/public/kibana-plugin-core-public.publicuisettingsparams.md new file mode 100644 index 00000000000000..678a69289ff235 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.publicuisettingsparams.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) + +## PublicUiSettingsParams type + +A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. + +Signature: + +```typescript +export declare type PublicUiSettingsParams = Omit; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md new file mode 100644 index 00000000000000..e7facb4a109cd8 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) + +## UiSettingsParams interface + +UiSettings parameters defined by the plugins. + +Signature: + +```typescript +export interface UiSettingsParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./kibana-plugin-core-public.uisettingsparams.category.md) | string[] | used to group the configured setting in the UI | +| [deprecation](./kibana-plugin-core-public.uisettingsparams.deprecation.md) | DeprecationSettings | optional deprecation information. Used to generate a deprecation warning. | +| [description](./kibana-plugin-core-public.uisettingsparams.description.md) | string | description provided to a user in UI | +| [name](./kibana-plugin-core-public.uisettingsparams.name.md) | string | title in the UI | +| [optionLabels](./kibana-plugin-core-public.uisettingsparams.optionlabels.md) | Record<string, string> | text labels for 'select' type UI element | +| [options](./kibana-plugin-core-public.uisettingsparams.options.md) | string[] | array of permitted values for this setting | +| [readonly](./kibana-plugin-core-public.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | +| [requiresPageReload](./kibana-plugin-core-public.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | +| [schema](./kibana-plugin-core-public.uisettingsparams.schema.md) | Type<T> | | +| [type](./kibana-plugin-core-public.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-core-public.uisettingstype.md) | +| [validation](./kibana-plugin-core-public.uisettingsparams.validation.md) | ImageValidation | StringValidation | | +| [value](./kibana-plugin-core-public.uisettingsparams.value.md) | T | default value to fall back to if a user doesn't provide any | + diff --git a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.schema.md b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.schema.md new file mode 100644 index 00000000000000..f90d5161f96a92 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.schema.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) > [schema](./kibana-plugin-core-public.uisettingsparams.schema.md) + +## UiSettingsParams.schema property + +Signature: + +```typescript +schema: Type; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.value.md b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.value.md new file mode 100644 index 00000000000000..2740f169eeecb3 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.uisettingsparams.value.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) > [value](./kibana-plugin-core-public.uisettingsparams.value.md) + +## UiSettingsParams.value property + +default value to fall back to if a user doesn't provide any + +Signature: + +```typescript +value?: T; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.getregistered.md b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.getregistered.md new file mode 100644 index 00000000000000..71a2bbf88472e1 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.getregistered.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) > [getRegistered](./kibana-plugin-core-server.iuisettingsclient.getregistered.md) + +## IUiSettingsClient.getRegistered property + +Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) + +Signature: + +```typescript +getRegistered: () => Readonly>; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md new file mode 100644 index 00000000000000..af99b5e5bb215e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) + +## IUiSettingsClient interface + +Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. + +Signature: + +```typescript +export interface IUiSettingsClient +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [get](./kibana-plugin-core-server.iuisettingsclient.get.md) | <T = any>(key: string) => Promise<T> | Retrieves uiSettings values set by the user with fallbacks to default values if not specified. | +| [getAll](./kibana-plugin-core-server.iuisettingsclient.getall.md) | <T = any>() => Promise<Record<string, T>> | Retrieves a set of all uiSettings values set by the user with fallbacks to default values if not specified. | +| [getRegistered](./kibana-plugin-core-server.iuisettingsclient.getregistered.md) | () => Readonly<Record<string, PublicUiSettingsParams>> | Returns registered uiSettings values [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | +| [getUserProvided](./kibana-plugin-core-server.iuisettingsclient.getuserprovided.md) | <T = any>() => Promise<Record<string, UserProvidedValues<T>>> | Retrieves a set of all uiSettings values set by the user. | +| [isOverridden](./kibana-plugin-core-server.iuisettingsclient.isoverridden.md) | (key: string) => boolean | Shows whether the uiSettings value set by the user. | +| [remove](./kibana-plugin-core-server.iuisettingsclient.remove.md) | (key: string) => Promise<void> | Removes uiSettings value by key. | +| [removeMany](./kibana-plugin-core-server.iuisettingsclient.removemany.md) | (keys: string[]) => Promise<void> | Removes multiple uiSettings values by keys. | +| [set](./kibana-plugin-core-server.iuisettingsclient.set.md) | (key: string, value: any) => Promise<void> | Writes uiSettings value and marks it as set by the user. | +| [setMany](./kibana-plugin-core-server.iuisettingsclient.setmany.md) | (changes: Record<string, any>) => Promise<void> | Writes multiple uiSettings values and marks them as set by the user. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md new file mode 100644 index 00000000000000..54cf496b2d6af4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -0,0 +1,264 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) + +## kibana-plugin-core-server package + +The Kibana Core APIs for server-side plugins. + +A plugin requires a `kibana.json` file at it's root directory that follows [the manfiest schema](./kibana-plugin-core-server.pluginmanifest.md) to define static plugin information required to load the plugin. + +A plugin's `server/index` file must contain a named import, `plugin`, that implements [PluginInitializer](./kibana-plugin-core-server.plugininitializer.md) which returns an object that implements [Plugin](./kibana-plugin-core-server.plugin.md). + +The plugin integrates with the core system via lifecycle events: `setup`, `start`, and `stop`. In each lifecycle method, the plugin will receive the corresponding core services available (either [CoreSetup](./kibana-plugin-core-server.coresetup.md) or [CoreStart](./kibana-plugin-core-server.corestart.md)) and any interfaces returned by dependency plugins' lifecycle method. Anything returned by the plugin's lifecycle method will be exposed to downstream dependencies when their corresponding lifecycle methods are invoked. + +## Classes + +| Class | Description | +| --- | --- | +| [BasePath](./kibana-plugin-core-server.basepath.md) | Access or manipulate the Kibana base path | +| [ClusterClient](./kibana-plugin-core-server.clusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | +| [CspConfig](./kibana-plugin-core-server.cspconfig.md) | CSP configuration for use in Kibana. | +| [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) | Wrapper of config schema. | +| [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | +| [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | +| [RouteValidationError](./kibana-plugin-core-server.routevalidationerror.md) | Error to return when the validation is not successful. | +| [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) | | +| [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | | +| [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | +| [SavedObjectsSerializer](./kibana-plugin-core-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-core-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) documents to the other kind. | +| [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) | Registry holding information about all the registered [saved object types](./kibana-plugin-core-server.savedobjectstype.md). | +| [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [AuthResultType](./kibana-plugin-core-server.authresulttype.md) | | +| [AuthStatus](./kibana-plugin-core-server.authstatus.md) | Status indicating an outcome of the authentication. | + +## Functions + +| Function | Description | +| --- | --- | +| [exportSavedObjectsToStream({ types, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | +| [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, savedObjectsClient, supportedTypes, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | +| [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, supportedTypes, namespace, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [APICaller](./kibana-plugin-core-server.apicaller.md) | | +| [AssistanceAPIResponse](./kibana-plugin-core-server.assistanceapiresponse.md) | | +| [AssistantAPIClientParams](./kibana-plugin-core-server.assistantapiclientparams.md) | | +| [Authenticated](./kibana-plugin-core-server.authenticated.md) | | +| [AuthNotHandled](./kibana-plugin-core-server.authnothandled.md) | | +| [AuthRedirected](./kibana-plugin-core-server.authredirected.md) | | +| [AuthRedirectedParams](./kibana-plugin-core-server.authredirectedparams.md) | Result of auth redirection. | +| [AuthResultParams](./kibana-plugin-core-server.authresultparams.md) | Result of successful authentication. | +| [AuthToolkit](./kibana-plugin-core-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | +| [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | +| [Capabilities](./kibana-plugin-core-server.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | +| [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | APIs to manage the [Capabilities](./kibana-plugin-core-server.capabilities.md) that will be used by the application.Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the registerProvider method.Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the registerSwitcher method.Refers to the methods documentation for complete description and examples. | +| [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md) | APIs to access the application [Capabilities](./kibana-plugin-core-server.capabilities.md). | +| [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) | Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md).See methods documentation for more detailed examples. | +| [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | +| [CoreSetup](./kibana-plugin-core-server.coresetup.md) | Context passed to the plugins setup method. | +| [CoreStart](./kibana-plugin-core-server.corestart.md) | Context passed to the plugins start method. | +| [CustomHttpResponseOptions](./kibana-plugin-core-server.customhttpresponseoptions.md) | HTTP response parameters for a response with adjustable status code. | +| [DeprecationAPIClientParams](./kibana-plugin-core-server.deprecationapiclientparams.md) | | +| [DeprecationAPIResponse](./kibana-plugin-core-server.deprecationapiresponse.md) | | +| [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | +| [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | +| [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | +| [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) | | +| [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | +| [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | +| [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) | | +| [ErrorHttpResponseOptions](./kibana-plugin-core-server.errorhttpresponseoptions.md) | HTTP response parameters | +| [FakeRequest](./kibana-plugin-core-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | +| [HttpResponseOptions](./kibana-plugin-core-server.httpresponseoptions.md) | HTTP response parameters | +| [HttpServerInfo](./kibana-plugin-core-server.httpserverinfo.md) | | +| [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to hapi server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. | +| [HttpServiceStart](./kibana-plugin-core-server.httpservicestart.md) | | +| [IContextContainer](./kibana-plugin-core-server.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | +| [ICspConfig](./kibana-plugin-core-server.icspconfig.md) | CSP configuration for use in Kibana. | +| [IKibanaResponse](./kibana-plugin-core-server.ikibanaresponse.md) | A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution | +| [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | +| [ImageValidation](./kibana-plugin-core-server.imagevalidation.md) | | +| [IndexSettingsDeprecationInfo](./kibana-plugin-core-server.indexsettingsdeprecationinfo.md) | | +| [IRenderOptions](./kibana-plugin-core-server.irenderoptions.md) | | +| [IRouter](./kibana-plugin-core-server.irouter.md) | Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-core-server.routeconfig.md) and [RequestHandler](./kibana-plugin-core-server.requesthandler.md) for more information about arguments to route registrations. | +| [IScopedRenderingClient](./kibana-plugin-core-server.iscopedrenderingclient.md) | | +| [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) | Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. | +| [KibanaRequestEvents](./kibana-plugin-core-server.kibanarequestevents.md) | Request events. | +| [KibanaRequestRoute](./kibana-plugin-core-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | +| [LegacyRequest](./kibana-plugin-core-server.legacyrequest.md) | | +| [LegacyServiceSetupDeps](./kibana-plugin-core-server.legacyservicesetupdeps.md) | | +| [LegacyServiceStartDeps](./kibana-plugin-core-server.legacyservicestartdeps.md) | | +| [Logger](./kibana-plugin-core-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. | +| [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) | The single purpose of LoggerFactory interface is to define a way to retrieve a context-based logger instance. | +| [LogMeta](./kibana-plugin-core-server.logmeta.md) | Contextual metadata | +| [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) | APIs to retrieves metrics gathered and exposed by the core platform. | +| [OnPostAuthToolkit](./kibana-plugin-core-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. | +| [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | +| [OnPreResponseExtensions](./kibana-plugin-core-server.onpreresponseextensions.md) | Additional data to extend a response. | +| [OnPreResponseInfo](./kibana-plugin-core-server.onpreresponseinfo.md) | Response status code. | +| [OnPreResponseToolkit](./kibana-plugin-core-server.onpreresponsetoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | +| [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) | Regroups metrics gathered by all the collectors. This contains metrics about the os/runtime, the kibana process and the http server. | +| [OpsOsMetrics](./kibana-plugin-core-server.opsosmetrics.md) | OS related metrics | +| [OpsProcessMetrics](./kibana-plugin-core-server.opsprocessmetrics.md) | Process related metrics | +| [OpsServerMetrics](./kibana-plugin-core-server.opsservermetrics.md) | server related metrics | +| [PackageInfo](./kibana-plugin-core-server.packageinfo.md) | | +| [Plugin](./kibana-plugin-core-server.plugin.md) | The interface that should be returned by a PluginInitializer. | +| [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | +| [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | +| [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | +| [PluginsServiceSetup](./kibana-plugin-core-server.pluginsservicesetup.md) | | +| [PluginsServiceStart](./kibana-plugin-core-server.pluginsservicestart.md) | | +| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [rendering](./kibana-plugin-core-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.dataClient](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | +| [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. | +| [RouteConfigOptions](./kibana-plugin-core-server.routeconfigoptions.md) | Additional route options. | +| [RouteConfigOptionsBody](./kibana-plugin-core-server.routeconfigoptionsbody.md) | Additional body options for a route | +| [RouteValidationResultFactory](./kibana-plugin-core-server.routevalidationresultfactory.md) | Validation result factory to be used in the custom validation function to return the valid data or validation errorsSee [RouteValidationFunction](./kibana-plugin-core-server.routevalidationfunction.md). | +| [RouteValidatorConfig](./kibana-plugin-core-server.routevalidatorconfig.md) | The configuration object to the RouteValidator class. Set params, query and/or body to specify the validation logic to follow for that property. | +| [RouteValidatorOptions](./kibana-plugin-core-server.routevalidatoroptions.md) | Additional options for the RouteValidator class to modify its default behaviour. | +| [SavedObject](./kibana-plugin-core-server.savedobject.md) | | +| [SavedObjectAttributes](./kibana-plugin-core-server.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectMigrationContext](./kibana-plugin-core-server.savedobjectmigrationcontext.md) | Migration context provided when invoking a [migration handler](./kibana-plugin-core-server.savedobjectmigrationfn.md) | +| [SavedObjectMigrationMap](./kibana-plugin-core-server.savedobjectmigrationmap.md) | A map of [migration functions](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used for a given type. The map's keys must be valid semver versions.For a given document, only migrations with a higher version number than that of the document will be applied. Migrations are executed in order, starting from the lowest version and ending with the highest one. | +| [SavedObjectReference](./kibana-plugin-core-server.savedobjectreference.md) | A reference to another saved object. | +| [SavedObjectsBaseOptions](./kibana-plugin-core-server.savedobjectsbaseoptions.md) | | +| [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) | | +| [SavedObjectsBulkGetObject](./kibana-plugin-core-server.savedobjectsbulkgetobject.md) | | +| [SavedObjectsBulkResponse](./kibana-plugin-core-server.savedobjectsbulkresponse.md) | | +| [SavedObjectsBulkUpdateObject](./kibana-plugin-core-server.savedobjectsbulkupdateobject.md) | | +| [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-server.savedobjectsbulkupdateoptions.md) | | +| [SavedObjectsBulkUpdateResponse](./kibana-plugin-core-server.savedobjectsbulkupdateresponse.md) | | +| [SavedObjectsClientProviderOptions](./kibana-plugin-core-server.savedobjectsclientprovideroptions.md) | Options to control the creation of the Saved Objects Client. | +| [SavedObjectsClientWrapperOptions](./kibana-plugin-core-server.savedobjectsclientwrapperoptions.md) | Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. | +| [SavedObjectsComplexFieldMapping](./kibana-plugin-core-server.savedobjectscomplexfieldmapping.md) | See [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) for documentation. | +| [SavedObjectsCoreFieldMapping](./kibana-plugin-core-server.savedobjectscorefieldmapping.md) | See [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) for documentation. | +| [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md) | | +| [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-core-server.savedobjectsdeletebynamespaceoptions.md) | | +| [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | +| [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) | Options controlling the export operation. | +| [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | +| [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) | | +| [SavedObjectsFindResponse](./kibana-plugin-core-server.savedobjectsfindresponse.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | +| [SavedObjectsImportConflictError](./kibana-plugin-core-server.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | +| [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportMissingReferencesError](./kibana-plugin-core-server.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | +| [SavedObjectsImportOptions](./kibana-plugin-core-server.savedobjectsimportoptions.md) | Options to control the import operation. | +| [SavedObjectsImportResponse](./kibana-plugin-core-server.savedobjectsimportresponse.md) | The response describing the result of an import. | +| [SavedObjectsImportRetry](./kibana-plugin-core-server.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | +| [SavedObjectsImportUnknownError](./kibana-plugin-core-server.savedobjectsimportunknownerror.md) | Represents a failure to import due to an unknown reason. | +| [SavedObjectsImportUnsupportedTypeError](./kibana-plugin-core-server.savedobjectsimportunsupportedtypeerror.md) | Represents a failure to import due to having an unsupported saved object type. | +| [SavedObjectsIncrementCounterOptions](./kibana-plugin-core-server.savedobjectsincrementcounteroptions.md) | | +| [SavedObjectsMappingProperties](./kibana-plugin-core-server.savedobjectsmappingproperties.md) | Describe the fields of a [saved object type](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md). | +| [SavedObjectsMigrationLogger](./kibana-plugin-core-server.savedobjectsmigrationlogger.md) | | +| [SavedObjectsMigrationVersion](./kibana-plugin-core-server.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [SavedObjectsRawDoc](./kibana-plugin-core-server.savedobjectsrawdoc.md) | A raw document as represented directly in the saved object index. | +| [SavedObjectsRepositoryFactory](./kibana-plugin-core-server.savedobjectsrepositoryfactory.md) | Factory provided when invoking a [client factory provider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) See [SavedObjectsServiceSetup.setClientFactoryProvider](./kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | +| [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. | +| [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for registering Saved Object types, creating and registering Saved Object client wrappers and factories. | +| [SavedObjectsServiceStart](./kibana-plugin-core-server.savedobjectsservicestart.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. | +| [SavedObjectsType](./kibana-plugin-core-server.savedobjectstype.md) | | +| [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) | Configuration options for the [type](./kibana-plugin-core-server.savedobjectstype.md)'s management section. | +| [SavedObjectsTypeMappingDefinition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) | Describe a saved object type mapping. | +| [SavedObjectsUpdateOptions](./kibana-plugin-core-server.savedobjectsupdateoptions.md) | | +| [SavedObjectsUpdateResponse](./kibana-plugin-core-server.savedobjectsupdateresponse.md) | | +| [SessionCookieValidationResult](./kibana-plugin-core-server.sessioncookievalidationresult.md) | Return type from a function to validate cookie contents. | +| [SessionStorage](./kibana-plugin-core-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. | +| [SessionStorageCookieOptions](./kibana-plugin-core-server.sessionstoragecookieoptions.md) | Configuration used to create HTTP session storage based on top of cookie mechanism. | +| [SessionStorageFactory](./kibana-plugin-core-server.sessionstoragefactory.md) | SessionStorage factory to bind one to an incoming request | +| [StringValidationRegex](./kibana-plugin-core-server.stringvalidationregex.md) | StringValidation with regex object | +| [StringValidationRegexString](./kibana-plugin-core-server.stringvalidationregexstring.md) | StringValidation as regex string | +| [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | +| [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) | | +| [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | | +| [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. | +| [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) | APIs to access the application's instance uuid. | + +## Variables + +| Variable | Description | +| --- | --- | +| [kibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Set of helpers used to create KibanaResponse to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution. | +| [validBodyOutput](./kibana-plugin-core-server.validbodyoutput.md) | The set of valid body.output | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AuthenticationHandler](./kibana-plugin-core-server.authenticationhandler.md) | See [AuthToolkit](./kibana-plugin-core-server.authtoolkit.md). | +| [AuthHeaders](./kibana-plugin-core-server.authheaders.md) | Auth Headers map | +| [AuthResult](./kibana-plugin-core-server.authresult.md) | | +| [CapabilitiesProvider](./kibana-plugin-core-server.capabilitiesprovider.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | +| [CapabilitiesSwitcher](./kibana-plugin-core-server.capabilitiesswitcher.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | +| [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) | Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. | +| [ConfigDeprecationLogger](./kibana-plugin-core-server.configdeprecationlogger.md) | Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) | +| [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) | A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md).See [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) for more usage examples. | +| [ConfigPath](./kibana-plugin-core-server.configpath.md) | | +| [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | +| [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | | +| [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | +| [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | +| [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) to represent the type of the context. | +| [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-server.icontextcontainer.md) | +| [HandlerParameters](./kibana-plugin-core-server.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md). | +| [Headers](./kibana-plugin-core-server.headers.md) | Http request headers to read. | +| [HttpResponsePayload](./kibana-plugin-core-server.httpresponsepayload.md) | Data send to the client as a response payload. | +| [IBasePath](./kibana-plugin-core-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-core-server.basepath.md) | +| [IClusterClient](./kibana-plugin-core-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | +| [IContextProvider](./kibana-plugin-core-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | +| [ICustomClusterClient](./kibana-plugin-core-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | +| [IsAuthenticated](./kibana-plugin-core-server.isauthenticated.md) | Returns authentication status for a request. | +| [ISavedObjectsRepository](./kibana-plugin-core-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | +| [ISavedObjectTypeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) | See [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) for documentation. | +| [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | +| [KibanaRequestRouteOptions](./kibana-plugin-core-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | +| [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | +| [KnownHeaders](./kibana-plugin-core-server.knownheaders.md) | Set of well-known HTTP headers. | +| [LifecycleResponseFactory](./kibana-plugin-core-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | +| [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-core-server.migration_assistance_index_action.md) | | +| [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-core-server.migration_deprecation_level.md) | | +| [MutatingOperationRefreshSetting](./kibana-plugin-core-server.mutatingoperationrefreshsetting.md) | Elasticsearch Refresh setting for mutating operation | +| [OnPostAuthHandler](./kibana-plugin-core-server.onpostauthhandler.md) | See [OnPostAuthToolkit](./kibana-plugin-core-server.onpostauthtoolkit.md). | +| [OnPreAuthHandler](./kibana-plugin-core-server.onpreauthhandler.md) | See [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md). | +| [OnPreResponseHandler](./kibana-plugin-core-server.onpreresponsehandler.md) | See [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md). | +| [PluginConfigSchema](./kibana-plugin-core-server.pluginconfigschema.md) | Dedicated type for plugin configuration schema. | +| [PluginInitializer](./kibana-plugin-core-server.plugininitializer.md) | The plugin export at the root of a plugin's server directory should conform to this interface. | +| [PluginName](./kibana-plugin-core-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | +| [PluginOpaqueId](./kibana-plugin-core-server.pluginopaqueid.md) | | +| [PublicUiSettingsParams](./kibana-plugin-core-server.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) exposed to the client-side. | +| [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) | | +| [RedirectResponseOptions](./kibana-plugin-core-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | +| [RequestHandler](./kibana-plugin-core-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) functions. | +| [RequestHandlerContextContainer](./kibana-plugin-core-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | +| [RequestHandlerContextProvider](./kibana-plugin-core-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. | +| [ResponseError](./kibana-plugin-core-server.responseerror.md) | Error message and optional data send to the client in case of error. | +| [ResponseErrorAttributes](./kibana-plugin-core-server.responseerrorattributes.md) | Additional data to provide error details. | +| [ResponseHeaders](./kibana-plugin-core-server.responseheaders.md) | Http response headers to set. | +| [RouteContentType](./kibana-plugin-core-server.routecontenttype.md) | The set of supported parseable Content-Types | +| [RouteMethod](./kibana-plugin-core-server.routemethod.md) | The set of common HTTP methods supported by Kibana routing. | +| [RouteRegistrar](./kibana-plugin-core-server.routeregistrar.md) | Route handler common definition | +| [RouteValidationFunction](./kibana-plugin-core-server.routevalidationfunction.md) | The custom validation function if @kbn/config-schema is not a valid solution for your specific plugin requirements. | +| [RouteValidationSpec](./kibana-plugin-core-server.routevalidationspec.md) | Allowed property validation options: either @kbn/config-schema validations or custom validation functionsSee [RouteValidationFunction](./kibana-plugin-core-server.routevalidationfunction.md) for custom validation. | +| [RouteValidatorFullConfig](./kibana-plugin-core-server.routevalidatorfullconfig.md) | Route validations config and options merged into one object | +| [SafeRouteMethod](./kibana-plugin-core-server.saferoutemethod.md) | Set of HTTP methods not changing the state of the server. | +| [SavedObjectAttribute](./kibana-plugin-core-server.savedobjectattribute.md) | Type definition for a Saved Object attribute value | +| [SavedObjectAttributeSingle](./kibana-plugin-core-server.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-server.savedobjectattribute.md) | +| [SavedObjectMigrationFn](./kibana-plugin-core-server.savedobjectmigrationfn.md) | A migration function for a [saved object type](./kibana-plugin-core-server.savedobjectstype.md) used to migrate it to a given version | +| [SavedObjectSanitizedDoc](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) | | +| [SavedObjectsClientContract](./kibana-plugin-core-server.savedobjectsclientcontract.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing plugin state.\#\# SavedObjectsClient errorsSince the SavedObjectsClient has its hands in everything we are a little paranoid about the way we present errors back to to application code. Ideally, all errors will be either:1. Caused by bad implementation (ie. undefined is not a function) and as such unpredictable 2. An error that has been classified and decorated appropriately by the decorators in [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md)Type 1 errors are inevitable, but since all expected/handle-able errors should be Type 2 the isXYZError() helpers exposed at SavedObjectsErrorHelpers should be used to understand and manage error responses from the SavedObjectsClient.Type 2 errors are decorated versions of the source error, so if the elasticsearch client threw an error it will be decorated based on its type. That means that rather than looking for error.body.error.type or doing substring checks on error.body.error.reason, just use the helpers to understand the meaning of the error:\`\`\`js if (SavedObjectsErrorHelpers.isNotFoundError(error)) { // handle 404 }if (SavedObjectsErrorHelpers.isNotAuthorizedError(error)) { // 401 handling should be automatic, but in case you wanted to know }// always rethrow the error unless you handle it throw error; \`\`\`\#\#\# 404s from missing indexFrom the perspective of application code and APIs the SavedObjectsClient is a black box that persists objects. One of the internal details that users have no control over is that we use an elasticsearch index for persistance and that index might be missing.At the time of writing we are in the process of transitioning away from the operating assumption that the SavedObjects index is always available. Part of this transition is handling errors resulting from an index missing. These used to trigger a 500 error in most cases, and in others cause 404s with different error messages.From my (Spencer) perspective, a 404 from the SavedObjectsApi is a 404; The object the request/call was targeting could not be found. This is why \#14141 takes special care to ensure that 404 errors are generic and don't distinguish between index missing or document missing.\#\#\# 503s from missing indexUnlike all other methods, create requests are supposed to succeed even when the Kibana index does not exist because it will be automatically created by elasticsearch. When that is not the case it is because Elasticsearch's action.auto_create_index setting prevents it from being created automatically so we throw a special 503 with the intention of informing the user that their Elasticsearch settings need to be updated.See [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) See [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | +| [SavedObjectsClientFactory](./kibana-plugin-core-server.savedobjectsclientfactory.md) | Describes the factory used to create instances of the Saved Objects Client. | +| [SavedObjectsClientFactoryProvider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) | Provider to invoke to retrieve a [SavedObjectsClientFactory](./kibana-plugin-core-server.savedobjectsclientfactory.md). | +| [SavedObjectsClientWrapperFactory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. | +| [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) | Describe a [saved object type mapping](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) field.Please refer to [elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html) For the mapping documentation | +| [ScopeableRequest](./kibana-plugin-core-server.scopeablerequest.md) | A user credentials container. It accommodates the necessary auth credentials to impersonate the current user.See [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md). | +| [SharedGlobalConfig](./kibana-plugin-core-server.sharedglobalconfig.md) | | +| [StringValidation](./kibana-plugin-core-server.stringvalidation.md) | Allows regex objects or a regex string | +| [UiSettingsType](./kibana-plugin-core-server.uisettingstype.md) | UI element type to represent the settings. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.publicuisettingsparams.md b/docs/development/core/server/kibana-plugin-core-server.publicuisettingsparams.md new file mode 100644 index 00000000000000..4ccc91fbe1f742 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.publicuisettingsparams.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PublicUiSettingsParams](./kibana-plugin-core-server.publicuisettingsparams.md) + +## PublicUiSettingsParams type + +A sub-set of [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) exposed to the client-side. + +Signature: + +```typescript +export declare type PublicUiSettingsParams = Omit; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md new file mode 100644 index 00000000000000..f134decb5102bd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) + +## UiSettingsParams interface + +UiSettings parameters defined by the plugins. + +Signature: + +```typescript +export interface UiSettingsParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./kibana-plugin-core-server.uisettingsparams.category.md) | string[] | used to group the configured setting in the UI | +| [deprecation](./kibana-plugin-core-server.uisettingsparams.deprecation.md) | DeprecationSettings | optional deprecation information. Used to generate a deprecation warning. | +| [description](./kibana-plugin-core-server.uisettingsparams.description.md) | string | description provided to a user in UI | +| [name](./kibana-plugin-core-server.uisettingsparams.name.md) | string | title in the UI | +| [optionLabels](./kibana-plugin-core-server.uisettingsparams.optionlabels.md) | Record<string, string> | text labels for 'select' type UI element | +| [options](./kibana-plugin-core-server.uisettingsparams.options.md) | string[] | array of permitted values for this setting | +| [readonly](./kibana-plugin-core-server.uisettingsparams.readonly.md) | boolean | a flag indicating that value cannot be changed | +| [requiresPageReload](./kibana-plugin-core-server.uisettingsparams.requirespagereload.md) | boolean | a flag indicating whether new value applying requires page reloading | +| [schema](./kibana-plugin-core-server.uisettingsparams.schema.md) | Type<T> | | +| [type](./kibana-plugin-core-server.uisettingsparams.type.md) | UiSettingsType | defines a type of UI element [UiSettingsType](./kibana-plugin-core-server.uisettingstype.md) | +| [validation](./kibana-plugin-core-server.uisettingsparams.validation.md) | ImageValidation | StringValidation | | +| [value](./kibana-plugin-core-server.uisettingsparams.value.md) | T | default value to fall back to if a user doesn't provide any | + diff --git a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.schema.md b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.schema.md new file mode 100644 index 00000000000000..f181fbd309b7fa --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.schema.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) > [schema](./kibana-plugin-core-server.uisettingsparams.schema.md) + +## UiSettingsParams.schema property + +Signature: + +```typescript +schema: Type; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.value.md b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.value.md new file mode 100644 index 00000000000000..78c8f0c8fcf8d5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.uisettingsparams.value.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) > [value](./kibana-plugin-core-server.uisettingsparams.value.md) + +## UiSettingsParams.value property + +default value to fall back to if a user doesn't provide any + +Signature: + +```typescript +value?: T; +``` diff --git a/packages/kbn-config-schema/src/errors/validation_error.ts b/packages/kbn-config-schema/src/errors/validation_error.ts index d688d022da85cd..2a4f887bc43498 100644 --- a/packages/kbn-config-schema/src/errors/validation_error.ts +++ b/packages/kbn-config-schema/src/errors/validation_error.ts @@ -44,5 +44,8 @@ export class ValidationError extends SchemaError { constructor(error: SchemaTypeError, namespace?: string) { super(ValidationError.extractMessage(error, namespace), error); + + // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, ValidationError.prototype); } } diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts index ad01dea624c3c6..dbfa87e70032bf 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts +++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts @@ -67,7 +67,7 @@ export class KbnClientUiSettings { * Replace all uiSettings with the `doc` values, `doc` is merged * with some defaults */ - async replace(doc: UiSettingValues) { + async replace(doc: UiSettingValues, { retries = 5 }: { retries?: number } = {}) { this.log.debug('replacing kibana config doc: %j', doc); const changes: Record = { @@ -85,7 +85,7 @@ export class KbnClientUiSettings { method: 'POST', path: '/api/kibana/settings', body: { changes }, - retries: 5, + retries, }); } diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3d5971b636e9ba..69bdea42283c9e 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -43920,7 +43920,7 @@ class KbnClientUiSettings { * Replace all uiSettings with the `doc` values, `doc` is merged * with some defaults */ - async replace(doc) { + async replace(doc, { retries = 5 } = {}) { this.log.debug('replacing kibana config doc: %j', doc); const changes = { ...this.defaults, @@ -43935,7 +43935,7 @@ class KbnClientUiSettings { method: 'POST', path: '/api/kibana/settings', body: { changes }, - retries: 5, + retries, }); } /** diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 9c97993d7c2a61..0574d6e3070ae4 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -172,7 +172,7 @@ export { ErrorToastOptions, } from './notifications'; -export { MountPoint, UnmountCallback } from './types'; +export { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; /** * Core services exposed to the `Plugin` setup lifecycle diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 69668176a397e7..46667230edc3b8 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -16,10 +16,11 @@ import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; +import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; import React from 'react'; import * as Rx from 'rxjs'; import { ShallowPromise } from '@kbn/utility-types'; -import { UiSettingsParams as UiSettingsParams_2 } from 'src/core/server/types'; +import { Type } from '@kbn/config-schema'; import { UnregisterCallback } from 'history'; import { UserProvidedValues as UserProvidedValues_2 } from 'src/core/server/types'; @@ -784,7 +785,7 @@ export type IToasts = Pick(key: string, defaultOverride?: T) => Observable; get: (key: string, defaultOverride?: T) => T; - getAll: () => Readonly>; + getAll: () => Readonly>; getSaved$: () => Observable<{ key: string; newValue: T; @@ -933,6 +934,9 @@ export interface PluginInitializerContext // @public (undocumented) export type PluginOpaqueId = symbol; +// @public +export type PublicUiSettingsParams = Omit; + // Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts // // @public (undocumented) @@ -1291,7 +1295,7 @@ export type ToastsSetup = IToasts; export type ToastsStart = IToasts; // @public -export interface UiSettingsParams { +export interface UiSettingsParams { category?: string[]; // Warning: (ae-forgotten-export) The symbol "DeprecationSettings" needs to be exported by the entry point index.d.ts deprecation?: DeprecationSettings; @@ -1301,16 +1305,18 @@ export interface UiSettingsParams { options?: string[]; readonly?: boolean; requiresPageReload?: boolean; + // (undocumented) + schema: Type; type?: UiSettingsType; // (undocumented) validation?: ImageValidation | StringValidation; - value?: SavedObjectAttribute; + value?: T; } // @public (undocumented) export interface UiSettingsState { // (undocumented) - [key: string]: UiSettingsParams_2 & UserProvidedValues_2; + [key: string]: PublicUiSettingsParams_2 & UserProvidedValues_2; } // @public diff --git a/src/core/public/types.ts b/src/core/public/types.ts index 267a9e9f7e0145..26f1e46836378e 100644 --- a/src/core/public/types.ts +++ b/src/core/public/types.ts @@ -19,6 +19,7 @@ export { UiSettingsParams, + PublicUiSettingsParams, UserProvidedValues, UiSettingsType, ImageValidation, diff --git a/src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap b/src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap index cd55c77526d529..b737c04a5f269e 100644 --- a/src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap +++ b/src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap @@ -84,21 +84,21 @@ Array [ exports[`#batchSet rejects all promises for batched requests that fail: promise rejections 1`] = ` Array [ Object { - "error": [Error: Request failed with status code: 400], + "error": [Error: invalid], "isRejected": true, }, Object { - "error": [Error: Request failed with status code: 400], + "error": [Error: invalid], "isRejected": true, }, Object { - "error": [Error: Request failed with status code: 400], + "error": [Error: invalid], "isRejected": true, }, ] `; -exports[`#batchSet rejects on 301 1`] = `"Request failed with status code: 301"`; +exports[`#batchSet rejects on 301 1`] = `"Moved Permanently"`; exports[`#batchSet rejects on 404 response 1`] = `"Request failed with status code: 404"`; diff --git a/src/core/public/ui_settings/types.ts b/src/core/public/ui_settings/types.ts index 19fd91924f247d..d92c033ae8c8c4 100644 --- a/src/core/public/ui_settings/types.ts +++ b/src/core/public/ui_settings/types.ts @@ -18,11 +18,11 @@ */ import { Observable } from 'rxjs'; -import { UiSettingsParams, UserProvidedValues } from 'src/core/server/types'; +import { PublicUiSettingsParams, UserProvidedValues } from 'src/core/server/types'; /** @public */ export interface UiSettingsState { - [key: string]: UiSettingsParams & UserProvidedValues; + [key: string]: PublicUiSettingsParams & UserProvidedValues; } /** @@ -53,7 +53,7 @@ export interface IUiSettingsClient { * Gets the metadata about all uiSettings, including the type, default value, and user value * for each key. */ - getAll: () => Readonly>; + getAll: () => Readonly>; /** * Sets the value for a uiSetting. If the setting is not registered by any plugin diff --git a/src/core/public/ui_settings/ui_settings_api.test.ts b/src/core/public/ui_settings/ui_settings_api.test.ts index 1170c42cea704c..9a462e05413472 100644 --- a/src/core/public/ui_settings/ui_settings_api.test.ts +++ b/src/core/public/ui_settings/ui_settings_api.test.ts @@ -148,7 +148,7 @@ describe('#batchSet', () => { '*', { status: 400, - body: 'invalid', + body: { message: 'invalid' }, }, { overwriteRoutes: false, diff --git a/src/core/public/ui_settings/ui_settings_api.ts b/src/core/public/ui_settings/ui_settings_api.ts index 33b43107acf1bc..c5efced0a41e3f 100644 --- a/src/core/public/ui_settings/ui_settings_api.ts +++ b/src/core/public/ui_settings/ui_settings_api.ts @@ -152,10 +152,14 @@ export class UiSettingsApi { }, }); } catch (err) { - if (err.response && err.response.status >= 300) { - throw new Error(`Request failed with status code: ${err.response.status}`); + if (err.response) { + if (err.response.status === 400) { + throw new Error(err.body.message); + } + if (err.response.status > 400) { + throw new Error(`Request failed with status code: ${err.response.status}`); + } } - throw err; } finally { this.loadingCount$.next(this.loadingCount$.getValue() - 1); diff --git a/src/core/public/ui_settings/ui_settings_client.ts b/src/core/public/ui_settings/ui_settings_client.ts index f0071ed08435c8..f5596b1bc34fc2 100644 --- a/src/core/public/ui_settings/ui_settings_client.ts +++ b/src/core/public/ui_settings/ui_settings_client.ts @@ -21,14 +21,14 @@ import { cloneDeep, defaultsDeep } from 'lodash'; import { Observable, Subject, concat, defer, of } from 'rxjs'; import { filter, map } from 'rxjs/operators'; -import { UiSettingsParams, UserProvidedValues } from 'src/core/server/types'; +import { UserProvidedValues, PublicUiSettingsParams } from 'src/core/server/types'; import { IUiSettingsClient, UiSettingsState } from './types'; import { UiSettingsApi } from './ui_settings_api'; interface UiSettingsClientParams { api: UiSettingsApi; - defaults: Record; + defaults: Record; initialSettings?: UiSettingsState; done$: Observable; } @@ -39,8 +39,8 @@ export class UiSettingsClient implements IUiSettingsClient { private readonly updateErrors$ = new Subject(); private readonly api: UiSettingsApi; - private readonly defaults: Record; - private cache: Record; + private readonly defaults: Record; + private cache: Record; constructor(params: UiSettingsClientParams) { this.api = params.api; diff --git a/src/core/server/core_app/core_app.ts b/src/core/server/core_app/core_app.ts new file mode 100644 index 00000000000000..2f8c85f47a76e4 --- /dev/null +++ b/src/core/server/core_app/core_app.ts @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { InternalCoreSetup } from '../internal_types'; +import { CoreContext } from '../core_context'; +import { Logger } from '../logging'; + +/** @internal */ +export class CoreApp { + private readonly logger: Logger; + constructor(core: CoreContext) { + this.logger = core.logger.get('core-app'); + } + setup(coreSetup: InternalCoreSetup) { + this.logger.debug('Setting up core app.'); + this.registerDefaultRoutes(coreSetup); + } + + private registerDefaultRoutes(coreSetup: InternalCoreSetup) { + const httpSetup = coreSetup.http; + const router = httpSetup.createRouter('/'); + router.get({ path: '/', validate: false }, async (context, req, res) => { + const defaultRoute = await context.core.uiSettings.client.get('defaultRoute'); + const basePath = httpSetup.basePath.get(req); + const url = `${basePath}${defaultRoute}`; + + return res.redirected({ + headers: { + location: url, + }, + }); + }); + router.get({ path: '/core', validate: false }, async (context, req, res) => + res.ok({ body: { version: '0.0.1' } }) + ); + } +} diff --git a/src/core/server/core_app/index.ts b/src/core/server/core_app/index.ts new file mode 100644 index 00000000000000..342ed43f1ff8a2 --- /dev/null +++ b/src/core/server/core_app/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { CoreApp } from './core_app'; diff --git a/src/core/server/core_app/integration_tests/default_route_provider_config.test.ts b/src/core/server/core_app/integration_tests/default_route_provider_config.test.ts new file mode 100644 index 00000000000000..221e6fa42471cd --- /dev/null +++ b/src/core/server/core_app/integration_tests/default_route_provider_config.test.ts @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import * as kbnTestServer from '../../../../test_utils/kbn_server'; +import { Root } from '../../root'; + +const { startES } = kbnTestServer.createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), +}); +let esServer: kbnTestServer.TestElasticsearchUtils; + +describe('default route provider', () => { + let root: Root; + + beforeAll(async () => { + esServer = await startES(); + root = kbnTestServer.createRootWithCorePlugins({ + server: { + basePath: '/hello', + }, + }); + + await root.setup(); + await root.start(); + }); + + afterAll(async () => { + await esServer.stop(); + await root.shutdown(); + }); + + it('redirects to the configured default route respecting basePath', async function() { + const { status, header } = await kbnTestServer.request.get(root, '/'); + + expect(status).toEqual(302); + expect(header).toMatchObject({ + location: '/hello/app/kibana', + }); + }); + + it('ignores invalid values', async function() { + const invalidRoutes = [ + 'http://not-your-kibana.com', + '///example.com', + '//example.com', + ' //example.com', + ]; + + for (const url of invalidRoutes) { + await kbnTestServer.request + .post(root, '/api/kibana/settings/defaultRoute') + .send({ value: url }) + .expect(400); + } + + const { status, header } = await kbnTestServer.request.get(root, '/'); + expect(status).toEqual(302); + expect(header).toMatchObject({ + location: '/hello/app/kibana', + }); + }); + + it('consumes valid values', async function() { + await kbnTestServer.request + .post(root, '/api/kibana/settings/defaultRoute') + .send({ value: '/valid' }) + .expect(200); + + const { status, header } = await kbnTestServer.request.get(root, '/'); + expect(status).toEqual(302); + expect(header).toMatchObject({ + location: '/hello/valid', + }); + }); +}); diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 4a1ac8988e4e5e..89fee92a7ef027 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -250,6 +250,7 @@ export { export { IUiSettingsClient, UiSettingsParams, + PublicUiSettingsParams, UiSettingsType, UiSettingsServiceSetup, UiSettingsServiceStart, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 9cd0c26ea24975..84fe081adaae6b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -998,7 +998,7 @@ export interface IScopedRenderingClient { export interface IUiSettingsClient { get: (key: string) => Promise; getAll: () => Promise>; - getRegistered: () => Readonly>; + getRegistered: () => Readonly>; getUserProvided: () => Promise>>; isOverridden: (key: string) => boolean; remove: (key: string) => Promise; @@ -1443,6 +1443,9 @@ export interface PluginsServiceStart { contracts: Map; } +// @public +export type PublicUiSettingsParams = Omit; + // Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts // // @public (undocumented) @@ -2284,7 +2287,7 @@ export interface StringValidationRegexString { } // @public -export interface UiSettingsParams { +export interface UiSettingsParams { category?: string[]; deprecation?: DeprecationSettings; description?: string; @@ -2293,10 +2296,12 @@ export interface UiSettingsParams { options?: string[]; readonly?: boolean; requiresPageReload?: boolean; + // (undocumented) + schema: Type; type?: UiSettingsType; // (undocumented) validation?: ImageValidation | StringValidation; - value?: SavedObjectAttribute; + value?: T; } // @public (undocumented) diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 2402504f717ca4..09a1328f346d89 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -26,8 +26,9 @@ import { RawConfigurationProvider, coreDeprecationProvider, } from './config'; +import { CoreApp } from './core_app'; import { ElasticsearchService } from './elasticsearch'; -import { HttpService, InternalHttpServiceSetup } from './http'; +import { HttpService } from './http'; import { RenderingService, RenderingServiceSetup } from './rendering'; import { LegacyService, ensureValidConfiguration } from './legacy'; import { Logger, LoggerFactory } from './logging'; @@ -69,6 +70,7 @@ export class Server { private readonly uiSettings: UiSettingsService; private readonly uuid: UuidService; private readonly metrics: MetricsService; + private readonly coreApp: CoreApp; private coreStart?: InternalCoreStart; @@ -92,6 +94,7 @@ export class Server { this.capabilities = new CapabilitiesService(core); this.uuid = new UuidService(core); this.metrics = new MetricsService(core); + this.coreApp = new CoreApp(core); } public async setup() { @@ -122,8 +125,6 @@ export class Server { context: contextServiceSetup, }); - this.registerDefaultRoute(httpSetup); - const capabilitiesSetup = this.capabilities.setup({ http: httpSetup }); const elasticsearchServiceSetup = await this.elasticsearch.setup({ @@ -168,6 +169,7 @@ export class Server { }); this.registerCoreContext(coreSetup, renderingSetup); + this.coreApp.setup(coreSetup); return coreSetup; } @@ -216,13 +218,6 @@ export class Server { await this.metrics.stop(); } - private registerDefaultRoute(httpSetup: InternalHttpServiceSetup) { - const router = httpSetup.createRouter('/core'); - router.get({ path: '/', validate: false }, async (context, req, res) => - res.ok({ body: { version: '0.0.1' } }) - ); - } - private registerCoreContext(coreSetup: InternalCoreSetup, rendering: RenderingServiceSetup) { coreSetup.http.registerRouteHandlerContext( coreId, diff --git a/src/core/server/ui_settings/index.ts b/src/core/server/ui_settings/index.ts index ddb66df3ffcbe1..b11f398d59fa83 100644 --- a/src/core/server/ui_settings/index.ts +++ b/src/core/server/ui_settings/index.ts @@ -27,6 +27,7 @@ export { UiSettingsServiceStart, IUiSettingsClient, UiSettingsParams, + PublicUiSettingsParams, InternalUiSettingsServiceSetup, InternalUiSettingsServiceStart, UiSettingsType, diff --git a/src/core/server/ui_settings/integration_tests/routes.test.ts b/src/core/server/ui_settings/integration_tests/routes.test.ts new file mode 100644 index 00000000000000..c1261bc7c13506 --- /dev/null +++ b/src/core/server/ui_settings/integration_tests/routes.test.ts @@ -0,0 +1,66 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import * as kbnTestServer from '../../../../test_utils/kbn_server'; + +describe('ui settings service', () => { + describe('routes', () => { + let root: ReturnType; + beforeAll(async () => { + root = kbnTestServer.createRoot(); + + const { uiSettings } = await root.setup(); + uiSettings.register({ + custom: { + value: '42', + schema: schema.string(), + }, + }); + + await root.start(); + }, 30000); + afterAll(async () => await root.shutdown()); + + describe('set', () => { + it('validates value', async () => { + const response = await kbnTestServer.request + .post(root, '/api/kibana/settings/custom') + .send({ value: 100 }) + .expect(400); + + expect(response.body.message).toBe( + '[validation [custom]]: expected value of type [string] but got [number]' + ); + }); + }); + describe('set many', () => { + it('validates value', async () => { + const response = await kbnTestServer.request + .post(root, '/api/kibana/settings') + .send({ changes: { custom: 100, foo: 'bar' } }) + .expect(400); + + expect(response.body.message).toBe( + '[validation [custom]]: expected value of type [string] but got [number]' + ); + }); + }); + }); +}); diff --git a/src/core/server/ui_settings/routes/set.ts b/src/core/server/ui_settings/routes/set.ts index 51ad256b51335f..e5158e274245cd 100644 --- a/src/core/server/ui_settings/routes/set.ts +++ b/src/core/server/ui_settings/routes/set.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { schema } from '@kbn/config-schema'; +import { schema, ValidationError } from '@kbn/config-schema'; import { IRouter } from '../../http'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; @@ -56,7 +56,7 @@ export function registerSetRoute(router: IRouter) { }); } - if (error instanceof CannotOverrideError) { + if (error instanceof CannotOverrideError || error instanceof ValidationError) { return response.badRequest({ body: error }); } diff --git a/src/core/server/ui_settings/routes/set_many.ts b/src/core/server/ui_settings/routes/set_many.ts index 3794eba004beea..5623c3fe11b807 100644 --- a/src/core/server/ui_settings/routes/set_many.ts +++ b/src/core/server/ui_settings/routes/set_many.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { schema } from '@kbn/config-schema'; +import { schema, ValidationError } from '@kbn/config-schema'; import { IRouter } from '../../http'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; @@ -50,7 +50,7 @@ export function registerSetManyRoute(router: IRouter) { }); } - if (error instanceof CannotOverrideError) { + if (error instanceof CannotOverrideError || error instanceof ValidationError) { return response.badRequest({ body: error }); } diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts index f3eb1f5a6859cc..076e1de4458d76 100644 --- a/src/core/server/ui_settings/types.ts +++ b/src/core/server/ui_settings/types.ts @@ -17,9 +17,10 @@ * under the License. */ import { SavedObjectsClientContract } from '../saved_objects/types'; -import { UiSettingsParams, UserProvidedValues } from '../../types'; +import { UiSettingsParams, UserProvidedValues, PublicUiSettingsParams } from '../../types'; export { UiSettingsParams, + PublicUiSettingsParams, StringValidationRegexString, StringValidationRegex, StringValidation, @@ -41,7 +42,7 @@ export interface IUiSettingsClient { /** * Returns registered uiSettings values {@link UiSettingsParams} */ - getRegistered: () => Readonly>; + getRegistered: () => Readonly>; /** * Retrieves uiSettings values set by the user with fallbacks to default values if not specified. */ diff --git a/src/core/server/ui_settings/ui_settings_client.test.ts b/src/core/server/ui_settings/ui_settings_client.test.ts index b8aa57291dccf6..4ce33eed267a34 100644 --- a/src/core/server/ui_settings/ui_settings_client.test.ts +++ b/src/core/server/ui_settings/ui_settings_client.test.ts @@ -18,6 +18,7 @@ */ import Chance from 'chance'; +import { schema } from '@kbn/config-schema'; import { loggingServiceMock } from '../logging/logging_service.mock'; import { createOrUpgradeSavedConfigMock } from './create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.mock'; @@ -145,6 +146,22 @@ describe('ui settings', () => { expect(error.message).toBe('Unable to update "foo" because it is overridden'); } }); + + it('validates value if a schema presents', async () => { + const defaults = { foo: { schema: schema.string() } }; + const { uiSettings, savedObjectsClient } = setup({ defaults }); + + await expect( + uiSettings.setMany({ + bar: 2, + foo: 1, + }) + ).rejects.toMatchInlineSnapshot( + `[Error: [validation [foo]]: expected value of type [string] but got [number]]` + ); + + expect(savedObjectsClient.update).toHaveBeenCalledTimes(0); + }); }); describe('#set()', () => { @@ -163,6 +180,17 @@ describe('ui settings', () => { }); }); + it('validates value if a schema presents', async () => { + const defaults = { foo: { schema: schema.string() } }; + const { uiSettings, savedObjectsClient } = setup({ defaults }); + + await expect(uiSettings.set('foo', 1)).rejects.toMatchInlineSnapshot( + `[Error: [validation [foo]]: expected value of type [string] but got [number]]` + ); + + expect(savedObjectsClient.update).toHaveBeenCalledTimes(0); + }); + it('throws CannotOverrideError if the key is overridden', async () => { const { uiSettings } = setup({ overrides: { @@ -193,6 +221,20 @@ describe('ui settings', () => { expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { one: null }); }); + it('does not fail validation', async () => { + const defaults = { + foo: { + schema: schema.string(), + value: '1', + }, + }; + const { uiSettings, savedObjectsClient } = setup({ defaults }); + + await uiSettings.remove('foo'); + + expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); + }); + it('throws CannotOverrideError if the key is overridden', async () => { const { uiSettings } = setup({ overrides: { @@ -235,6 +277,20 @@ describe('ui settings', () => { }); }); + it('does not fail validation', async () => { + const defaults = { + foo: { + schema: schema.string(), + value: '1', + }, + }; + const { uiSettings, savedObjectsClient } = setup({ defaults }); + + await uiSettings.removeMany(['foo', 'bar']); + + expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); + }); + it('throws CannotOverrideError if any key is overridden', async () => { const { uiSettings } = setup({ overrides: { @@ -256,7 +312,13 @@ describe('ui settings', () => { const value = chance.word(); const defaults = { key: { value } }; const { uiSettings } = setup({ defaults }); - expect(uiSettings.getRegistered()).toBe(defaults); + expect(uiSettings.getRegistered()).toEqual(defaults); + }); + it('does not leak validation schema outside', () => { + const value = chance.word(); + const defaults = { key: { value, schema: schema.string() } }; + const { uiSettings } = setup({ defaults }); + expect(uiSettings.getRegistered()).toStrictEqual({ key: { value } }); }); }); @@ -274,7 +336,7 @@ describe('ui settings', () => { const { uiSettings } = setup({ esDocSource }); const result = await uiSettings.getUserProvided(); - expect(result).toEqual({ + expect(result).toStrictEqual({ user: { userValue: 'customized', }, @@ -286,7 +348,7 @@ describe('ui settings', () => { const { uiSettings } = setup({ esDocSource }); const result = await uiSettings.getUserProvided(); - expect(result).toEqual({ + expect(result).toStrictEqual({ user: { userValue: 'customized', }, @@ -296,6 +358,32 @@ describe('ui settings', () => { }); }); + it('ignores user-configured value if it fails validation', async () => { + const esDocSource = { user: 'foo', id: 'bar' }; + const defaults = { + id: { + value: 42, + schema: schema.number(), + }, + }; + const { uiSettings } = setup({ esDocSource, defaults }); + const result = await uiSettings.getUserProvided(); + + expect(result).toStrictEqual({ + user: { + userValue: 'foo', + }, + }); + + expect(loggingServiceMock.collect(logger).warn).toMatchInlineSnapshot(` + Array [ + Array [ + "Ignore invalid UiSettings value. Error: [validation [id]]: expected value of type [number] but got [string].", + ], + ] + `); + }); + it('automatically creates the savedConfig if it is missing and returns empty object', async () => { const { uiSettings, savedObjectsClient, createOrUpgradeSavedConfig } = setup(); savedObjectsClient.get = jest @@ -303,7 +391,7 @@ describe('ui settings', () => { .mockRejectedValueOnce(SavedObjectsClient.errors.createGenericNotFoundError()) .mockResolvedValueOnce({ attributes: {} }); - expect(await uiSettings.getUserProvided()).toEqual({}); + expect(await uiSettings.getUserProvided()).toStrictEqual({}); expect(savedObjectsClient.get).toHaveBeenCalledTimes(2); @@ -320,7 +408,7 @@ describe('ui settings', () => { SavedObjectsClient.errors.createGenericNotFoundError() ); - expect(await uiSettings.getUserProvided()).toEqual({ foo: { userValue: 'bar ' } }); + expect(await uiSettings.getUserProvided()).toStrictEqual({ foo: { userValue: 'bar ' } }); }); it('returns an empty object on Forbidden responses', async () => { @@ -329,7 +417,7 @@ describe('ui settings', () => { const error = SavedObjectsClient.errors.decorateForbiddenError(new Error()); savedObjectsClient.get.mockRejectedValue(error); - expect(await uiSettings.getUserProvided()).toEqual({}); + expect(await uiSettings.getUserProvided()).toStrictEqual({}); expect(createOrUpgradeSavedConfig).toHaveBeenCalledTimes(0); }); @@ -339,7 +427,7 @@ describe('ui settings', () => { const error = SavedObjectsClient.errors.decorateEsUnavailableError(new Error()); savedObjectsClient.get.mockRejectedValue(error); - expect(await uiSettings.getUserProvided()).toEqual({}); + expect(await uiSettings.getUserProvided()).toStrictEqual({}); expect(createOrUpgradeSavedConfig).toHaveBeenCalledTimes(0); }); @@ -382,7 +470,7 @@ describe('ui settings', () => { }; const { uiSettings } = setup({ esDocSource, overrides }); - expect(await uiSettings.getUserProvided()).toEqual({ + expect(await uiSettings.getUserProvided()).toStrictEqual({ user: { userValue: 'customized', }, @@ -404,15 +492,40 @@ describe('ui settings', () => { expect(savedObjectsClient.get).toHaveBeenCalledWith(TYPE, ID); }); - it(`returns defaults when es doc is empty`, async () => { + it('returns defaults when es doc is empty', async () => { const esDocSource = {}; const defaults = { foo: { value: 'bar' } }; const { uiSettings } = setup({ esDocSource, defaults }); - expect(await uiSettings.getAll()).toEqual({ + expect(await uiSettings.getAll()).toStrictEqual({ foo: 'bar', }); }); + it('ignores user-configured value if it fails validation', async () => { + const esDocSource = { user: 'foo', id: 'bar' }; + const defaults = { + id: { + value: 42, + schema: schema.number(), + }, + }; + const { uiSettings } = setup({ esDocSource, defaults }); + const result = await uiSettings.getAll(); + + expect(result).toStrictEqual({ + id: 42, + user: 'foo', + }); + + expect(loggingServiceMock.collect(logger).warn).toMatchInlineSnapshot(` + Array [ + Array [ + "Ignore invalid UiSettings value. Error: [validation [id]]: expected value of type [number] but got [string].", + ], + ] + `); + }); + it(`merges user values, including ones without defaults, into key value pairs`, async () => { const esDocSource = { foo: 'user-override', @@ -427,7 +540,7 @@ describe('ui settings', () => { const { uiSettings } = setup({ esDocSource, defaults }); - expect(await uiSettings.getAll()).toEqual({ + expect(await uiSettings.getAll()).toStrictEqual({ foo: 'user-override', bar: 'user-provided', }); @@ -451,7 +564,7 @@ describe('ui settings', () => { const { uiSettings } = setup({ esDocSource, defaults, overrides }); - expect(await uiSettings.getAll()).toEqual({ + expect(await uiSettings.getAll()).toStrictEqual({ foo: 'bax', bar: 'user-provided', }); @@ -518,6 +631,28 @@ describe('ui settings', () => { expect(await uiSettings.get('dateFormat')).toBe('foo'); }); + + it('returns the default value if user-configured value fails validation', async () => { + const esDocSource = { id: 'bar' }; + const defaults = { + id: { + value: 42, + schema: schema.number(), + }, + }; + + const { uiSettings } = setup({ esDocSource, defaults }); + + expect(await uiSettings.get('id')).toBe(42); + + expect(loggingServiceMock.collect(logger).warn).toMatchInlineSnapshot(` + Array [ + Array [ + "Ignore invalid UiSettings value. Error: [validation [id]]: expected value of type [number] but got [string].", + ], + ] + `); + }); }); describe('#isOverridden()', () => { diff --git a/src/core/server/ui_settings/ui_settings_client.ts b/src/core/server/ui_settings/ui_settings_client.ts index a7e55d2b2da65e..76c8284175f119 100644 --- a/src/core/server/ui_settings/ui_settings_client.ts +++ b/src/core/server/ui_settings/ui_settings_client.ts @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { defaultsDeep } from 'lodash'; +import { defaultsDeep, omit } from 'lodash'; import { SavedObjectsErrorHelpers } from '../saved_objects'; import { SavedObjectsClientContract } from '../saved_objects/types'; import { Logger } from '../logging'; import { createOrUpgradeSavedConfig } from './create_or_upgrade_saved_config'; -import { IUiSettingsClient, UiSettingsParams } from './types'; +import { IUiSettingsClient, UiSettingsParams, PublicUiSettingsParams } from './types'; import { CannotOverrideError } from './ui_settings_errors'; export interface UiSettingsServiceOptions { @@ -40,14 +40,14 @@ interface ReadOptions { autoCreateOrUpgradeIfMissing?: boolean; } -interface UserProvidedValue { +interface UserProvidedValue { userValue?: T; isOverridden?: boolean; } type UiSettingsRawValue = UiSettingsParams & UserProvidedValue; -type UserProvided = Record>; +type UserProvided = Record>; type UiSettingsRaw = Record; export class UiSettingsClient implements IUiSettingsClient { @@ -72,7 +72,11 @@ export class UiSettingsClient implements IUiSettingsClient { } getRegistered() { - return this.defaults; + const copiedDefaults: Record = {}; + for (const [key, value] of Object.entries(this.defaults)) { + copiedDefaults[key] = omit(value, 'schema'); + } + return copiedDefaults; } async get(key: string): Promise { @@ -90,29 +94,21 @@ export class UiSettingsClient implements IUiSettingsClient { }, {} as Record); } - async getUserProvided(): Promise> { - const userProvided: UserProvided = {}; - - // write the userValue for each key stored in the saved object that is not overridden - for (const [key, userValue] of Object.entries(await this.read())) { - if (userValue !== null && !this.isOverridden(key)) { - userProvided[key] = { - userValue, - }; - } - } + async getUserProvided(): Promise> { + const userProvided: UserProvided = this.onReadHook(await this.read()); // write all overridden keys, dropping the userValue is override is null and // adding keys for overrides that are not in saved object - for (const [key, userValue] of Object.entries(this.overrides)) { + for (const [key, value] of Object.entries(this.overrides)) { userProvided[key] = - userValue === null ? { isOverridden: true } : { isOverridden: true, userValue }; + value === null ? { isOverridden: true } : { isOverridden: true, userValue: value }; } return userProvided; } async setMany(changes: Record) { + this.onWriteHook(changes); await this.write({ changes }); } @@ -147,6 +143,43 @@ export class UiSettingsClient implements IUiSettingsClient { return defaultsDeep(userProvided, this.defaults); } + private validateKey(key: string, value: unknown) { + const definition = this.defaults[key]; + if (value === null || definition === undefined) return; + if (definition.schema) { + definition.schema.validate(value, {}, `validation [${key}]`); + } + } + + private onWriteHook(changes: Record) { + for (const key of Object.keys(changes)) { + this.assertUpdateAllowed(key); + } + + for (const [key, value] of Object.entries(changes)) { + this.validateKey(key, value); + } + } + + private onReadHook(values: Record) { + // write the userValue for each key stored in the saved object that is not overridden + // validate value read from saved objects as it can be changed via SO API + const filteredValues: UserProvided = {}; + for (const [key, userValue] of Object.entries(values)) { + if (userValue === null || this.isOverridden(key)) continue; + try { + this.validateKey(key, userValue); + filteredValues[key] = { + userValue: userValue as T, + }; + } catch (error) { + this.log.warn(`Ignore invalid UiSettings value. ${error}.`); + } + } + + return filteredValues; + } + private async write({ changes, autoCreateOrUpgradeIfMissing = true, @@ -154,10 +187,6 @@ export class UiSettingsClient implements IUiSettingsClient { changes: Record; autoCreateOrUpgradeIfMissing?: boolean; }) { - for (const key of Object.keys(changes)) { - this.assertUpdateAllowed(key); - } - try { await this.savedObjectsClient.update(this.type, this.id, changes); } catch (error) { diff --git a/src/core/server/ui_settings/ui_settings_service.test.ts b/src/core/server/ui_settings/ui_settings_service.test.ts index 11766713b3be0a..08400f56ad2811 100644 --- a/src/core/server/ui_settings/ui_settings_service.test.ts +++ b/src/core/server/ui_settings/ui_settings_service.test.ts @@ -17,6 +17,8 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import { schema } from '@kbn/config-schema'; + import { MockUiSettingsClientConstructor } from './ui_settings_service.test.mock'; import { UiSettingsService, SetupDeps } from './ui_settings_service'; import { httpServiceMock } from '../http/http_service.mock'; @@ -35,6 +37,7 @@ const defaults = { value: 'bar', category: [], description: '', + schema: schema.string(), }, }; @@ -104,6 +107,45 @@ describe('uiSettings', () => { }); describe('#start', () => { + describe('validation', () => { + it('validates registered definitions', async () => { + const { register } = await service.setup(setupDeps); + register({ + custom: { + value: 42, + schema: schema.string(), + }, + }); + + await expect(service.start()).rejects.toMatchInlineSnapshot( + `[Error: [ui settings defaults [custom]]: expected value of type [string] but got [number]]` + ); + }); + + it('validates overrides', async () => { + const coreContext = mockCoreContext.create(); + coreContext.configService.atPath.mockReturnValueOnce( + new BehaviorSubject({ + overrides: { + custom: 42, + }, + }) + ); + const customizedService = new UiSettingsService(coreContext); + const { register } = await customizedService.setup(setupDeps); + register({ + custom: { + value: '42', + schema: schema.string(), + }, + }); + + await expect(customizedService.start()).rejects.toMatchInlineSnapshot( + `[Error: [ui settings overrides [custom]]: expected value of type [string] but got [number]]` + ); + }); + }); + describe('#asScopedToClient', () => { it('passes saved object type "config" to UiSettingsClient', async () => { await service.setup(setupDeps); diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts index de2cc9d510e0c6..83e66cf6dd06da 100644 --- a/src/core/server/ui_settings/ui_settings_service.ts +++ b/src/core/server/ui_settings/ui_settings_service.ts @@ -70,6 +70,9 @@ export class UiSettingsService } public async start(): Promise { + this.validatesDefinitions(); + this.validatesOverrides(); + return { asScopedToClient: this.getScopedClientFactory(), }; @@ -101,4 +104,21 @@ export class UiSettingsService this.uiSettingsDefaults.set(key, value); }); } + + private validatesDefinitions() { + for (const [key, definition] of this.uiSettingsDefaults) { + if (definition.schema) { + definition.schema.validate(definition.value, {}, `ui settings defaults [${key}]`); + } + } + } + + private validatesOverrides() { + for (const [key, value] of Object.entries(this.overrides)) { + const definition = this.uiSettingsDefaults.get(key); + if (definition?.schema) { + definition.schema.validate(value, {}, `ui settings overrides [${key}]`); + } + } + } } diff --git a/src/core/types/ui_settings.ts b/src/core/types/ui_settings.ts index eccd3f9616af07..ed1076b5719603 100644 --- a/src/core/types/ui_settings.ts +++ b/src/core/types/ui_settings.ts @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -import { SavedObjectAttribute } from './saved_objects'; +import { Type } from '@kbn/config-schema'; /** * UI element type to represent the settings. @@ -49,11 +48,11 @@ export interface DeprecationSettings { * UiSettings parameters defined by the plugins. * @public * */ -export interface UiSettingsParams { +export interface UiSettingsParams { /** title in the UI */ name?: string; /** default value to fall back to if a user doesn't provide any */ - value?: SavedObjectAttribute; + value?: T; /** description provided to a user in UI */ description?: string; /** used to group the configured setting in the UI */ @@ -73,10 +72,22 @@ export interface UiSettingsParams { /* * Allows defining a custom validation applicable to value change on the client. * @deprecated + * Use schema instead. */ validation?: ImageValidation | StringValidation; + /* + * Value validation schema + * Used to validate value on write and read. + */ + schema: Type; } +/** + * A sub-set of {@link UiSettingsParams} exposed to the client-side. + * @public + * */ +export type PublicUiSettingsParams = Omit; + /** * Allows regex objects or a regex string * @public diff --git a/src/core/utils/url.test.ts b/src/core/utils/url.test.ts index 3c35ba44455bc4..419c0cda2b8cb5 100644 --- a/src/core/utils/url.test.ts +++ b/src/core/utils/url.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { modifyUrl } from './url'; +import { modifyUrl, isRelativeUrl } from './url'; describe('modifyUrl()', () => { test('throws an error with invalid input', () => { @@ -69,3 +69,17 @@ describe('modifyUrl()', () => { ).toEqual('mail:localhost'); }); }); + +describe('isRelativeUrl()', () => { + test('returns "true" for a relative URL', () => { + expect(isRelativeUrl('good')).toBe(true); + expect(isRelativeUrl('/good')).toBe(true); + expect(isRelativeUrl('/good/even/better')).toBe(true); + }); + test('returns "false" for a non-relative URL', () => { + expect(isRelativeUrl('http://evil.com')).toBe(false); + expect(isRelativeUrl('//evil.com')).toBe(false); + expect(isRelativeUrl('///evil.com')).toBe(false); + expect(isRelativeUrl(' //evil.com')).toBe(false); + }); +}); diff --git a/src/core/utils/url.ts b/src/core/utils/url.ts index 31de7e18140380..c2bf80ce3f86f2 100644 --- a/src/core/utils/url.ts +++ b/src/core/utils/url.ts @@ -99,3 +99,19 @@ export function modifyUrl( slashes: modifiedParts.slashes, } as UrlObject); } + +export function isRelativeUrl(candidatePath: string) { + // validate that `candidatePath` is not attempting a redirect to somewhere + // outside of this Kibana install + const all = parseUrl(candidatePath, false /* parseQueryString */, true /* slashesDenoteHost */); + const { protocol, hostname, port } = all; + // We should explicitly compare `protocol`, `port` and `hostname` to null to make sure these are not + // detected in the URL at all. For example `hostname` can be empty string for Node URL parser, but + // browser (because of various bwc reasons) processes URL differently (e.g. `///abc.com` - for browser + // hostname is `abc.com`, but for Node hostname is an empty string i.e. everything between schema (`//`) + // and the first slash that belongs to path. + if (protocol !== null || hostname !== null || port !== null) { + return false; + } + return true; +} diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index 3e2915e48d5308..fecc098ca65576 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -16,11 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - import moment from 'moment-timezone'; import numeralLanguages from '@elastic/numeral/languages'; import { i18n } from '@kbn/i18n'; +import { schema } from '@kbn/config-schema'; + import { DEFAULT_QUERY_LANGUAGE } from '../../../plugins/data/common'; +import { isRelativeUrl } from '../../../core/utils'; export function getUiSettingDefaults() { const weekdays = moment.weekdays().slice(); @@ -67,17 +69,23 @@ export function getUiSettingDefaults() { defaultMessage: 'Default route', }), value: '/app/kibana', - validation: { - regexString: '^/', - message: i18n.translate('kbn.advancedSettings.defaultRoute.defaultRouteValidationMessage', { - defaultMessage: 'The route must start with a slash ("/")', - }), - }, + schema: schema.string({ + validate(value) { + if (!value.startsWith('/') || !isRelativeUrl(value)) { + return i18n.translate( + 'kbn.advancedSettings.defaultRoute.defaultRouteIsRelativeValidationMessage', + { + defaultMessage: 'Must be a relative URL.', + } + ); + } + }, + }), description: i18n.translate('kbn.advancedSettings.defaultRoute.defaultRouteText', { defaultMessage: 'This setting specifies the default route when opening Kibana. ' + 'You can use this setting to modify the landing page when opening Kibana. ' + - 'The route must start with a slash ("/").', + 'The route must be a relative URL.', }), }, 'query:queryString:options': { diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js index 57adf730f3dd96..3e3dc284671da0 100644 --- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js +++ b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import { Type } from '@kbn/config-schema'; import pkg from '../../../../package.json'; export const createTestEntryTemplate = defaultUiSettings => bundle => ` @@ -87,7 +87,14 @@ const coreSystem = new CoreSystem({ buildNum: 1234, devMode: true, uiSettings: { - defaults: ${JSON.stringify(defaultUiSettings, null, 2) + defaults: ${JSON.stringify( + defaultUiSettings, + (key, value) => { + if (value instanceof Type) return null; + return value; + }, + 2 + ) .split('\n') .join('\n ')}, user: {} diff --git a/src/legacy/server/http/index.js b/src/legacy/server/http/index.js index 265d71e95b301f..d616afb533d0a8 100644 --- a/src/legacy/server/http/index.js +++ b/src/legacy/server/http/index.js @@ -24,15 +24,12 @@ import Boom from 'boom'; import { registerHapiPlugins } from './register_hapi_plugins'; import { setupBasePathProvider } from './setup_base_path_provider'; -import { setupDefaultRouteProvider } from './setup_default_route_provider'; export default async function(kbnServer, server, config) { server = kbnServer.server; setupBasePathProvider(kbnServer); - setupDefaultRouteProvider(server); - await registerHapiPlugins(server); // provide a simple way to expose static directories @@ -60,14 +57,6 @@ export default async function(kbnServer, server, config) { }); }); - server.route({ - path: '/', - method: 'GET', - async handler(req, h) { - return h.redirect(await req.getDefaultRoute()); - }, - }); - server.route({ method: 'GET', path: '/{p*}', diff --git a/src/legacy/server/http/integration_tests/default_route_provider.test.ts b/src/legacy/server/http/integration_tests/default_route_provider.test.ts deleted file mode 100644 index d91438d904558b..00000000000000 --- a/src/legacy/server/http/integration_tests/default_route_provider.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -jest.mock('../../../ui/ui_settings/ui_settings_mixin', () => { - return jest.fn(); -}); - -import * as kbnTestServer from '../../../../test_utils/kbn_server'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { Root } from '../../../../core/server/root'; - -let mockDefaultRouteSetting: any = ''; - -describe('default route provider', () => { - let root: Root; - beforeAll(async () => { - root = kbnTestServer.createRoot({ migrations: { skip: true } }); - - await root.setup(); - await root.start(); - - const kbnServer = kbnTestServer.getKbnServer(root); - - kbnServer.server.decorate('request', 'getUiSettingsService', function() { - return { - get: (key: string) => { - if (key === 'defaultRoute') { - return Promise.resolve(mockDefaultRouteSetting); - } - throw Error(`unsupported ui setting: ${key}`); - }, - getRegistered: () => { - return { - defaultRoute: { - value: '/app/kibana', - }, - }; - }, - }; - }); - }, 30000); - - afterAll(async () => await root.shutdown()); - - it('redirects to the configured default route', async function() { - mockDefaultRouteSetting = '/app/some/default/route'; - - const { status, header } = await kbnTestServer.request.get(root, '/'); - expect(status).toEqual(302); - expect(header).toMatchObject({ - location: '/app/some/default/route', - }); - }); - - const invalidRoutes = [ - 'http://not-your-kibana.com', - '///example.com', - '//example.com', - ' //example.com', - ]; - for (const route of invalidRoutes) { - it(`falls back to /app/kibana when the configured route (${route}) is not a valid relative path`, async function() { - mockDefaultRouteSetting = route; - - const { status, header } = await kbnTestServer.request.get(root, '/'); - expect(status).toEqual(302); - expect(header).toMatchObject({ - location: '/app/kibana', - }); - }); - } -}); diff --git a/src/legacy/server/http/integration_tests/default_route_provider_config.test.ts b/src/legacy/server/http/integration_tests/default_route_provider_config.test.ts deleted file mode 100644 index 8365941cbeb10e..00000000000000 --- a/src/legacy/server/http/integration_tests/default_route_provider_config.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import * as kbnTestServer from '../../../../test_utils/kbn_server'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { Root } from '../../../../core/server/root'; - -describe('default route provider', () => { - let root: Root; - - afterEach(async () => await root.shutdown()); - - it('redirects to the configured default route', async function() { - root = kbnTestServer.createRoot({ - server: { - defaultRoute: '/app/some/default/route', - }, - migrations: { skip: true }, - }); - - await root.setup(); - await root.start(); - - const kbnServer = kbnTestServer.getKbnServer(root); - - kbnServer.server.decorate('request', 'getSavedObjectsClient', function() { - return { - get: (type: string, id: string) => ({ attributes: {} }), - }; - }); - - const { status, header } = await kbnTestServer.request.get(root, '/'); - - expect(status).toEqual(302); - expect(header).toMatchObject({ - location: '/app/some/default/route', - }); - }); -}); diff --git a/src/legacy/server/http/setup_default_route_provider.ts b/src/legacy/server/http/setup_default_route_provider.ts deleted file mode 100644 index 9a580dd1c59bdc..00000000000000 --- a/src/legacy/server/http/setup_default_route_provider.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Legacy } from 'kibana'; -import { parse } from 'url'; - -export function setupDefaultRouteProvider(server: Legacy.Server) { - server.decorate('request', 'getDefaultRoute', async function() { - // @ts-ignore - const request: Legacy.Request = this; - - const serverBasePath: string = server.config().get('server.basePath'); - - const uiSettings = request.getUiSettingsService(); - - const defaultRoute = await uiSettings.get('defaultRoute'); - const qualifiedDefaultRoute = `${request.getBasePath()}${defaultRoute}`; - - if (isRelativePath(qualifiedDefaultRoute, serverBasePath)) { - return qualifiedDefaultRoute; - } else { - server.log( - ['http', 'warn'], - `Ignoring configured default route of '${defaultRoute}', as it is malformed.` - ); - - const fallbackRoute = uiSettings.getRegistered().defaultRoute.value; - - const qualifiedFallbackRoute = `${request.getBasePath()}${fallbackRoute}`; - return qualifiedFallbackRoute; - } - }); - - function isRelativePath(candidatePath: string, basePath = '') { - // validate that `candidatePath` is not attempting a redirect to somewhere - // outside of this Kibana install - const { protocol, hostname, port, pathname } = parse( - candidatePath, - false /* parseQueryString */, - true /* slashesDenoteHost */ - ); - - // We should explicitly compare `protocol`, `port` and `hostname` to null to make sure these are not - // detected in the URL at all. For example `hostname` can be empty string for Node URL parser, but - // browser (because of various bwc reasons) processes URL differently (e.g. `///abc.com` - for browser - // hostname is `abc.com`, but for Node hostname is an empty string i.e. everything between schema (`//`) - // and the first slash that belongs to path. - if (protocol !== null || hostname !== null || port !== null) { - return false; - } - - if (!String(pathname).startsWith(basePath)) { - return false; - } - - return true; - } -} diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 676c9dc27db6dd..e4aa832a8894bc 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -92,7 +92,6 @@ declare module 'hapi' { interface Request { getSavedObjectsClient(options?: SavedObjectsClientProviderOptions): SavedObjectsClientContract; getBasePath(): string; - getDefaultRoute(): Promise; getUiSettingsService(): IUiSettingsClient; } diff --git a/src/plugins/advanced_settings/public/management_app/advanced_settings.test.tsx b/src/plugins/advanced_settings/public/management_app/advanced_settings.test.tsx index 7a2ab648ec2586..6103041cf0a4c8 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.test.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.test.tsx @@ -22,7 +22,11 @@ import { Observable } from 'rxjs'; import { ReactWrapper } from 'enzyme'; import { mountWithI18nProvider } from 'test_utils/enzyme_helpers'; import dedent from 'dedent'; -import { UiSettingsParams, UserProvidedValues, UiSettingsType } from '../../../../core/public'; +import { + PublicUiSettingsParams, + UserProvidedValues, + UiSettingsType, +} from '../../../../core/public'; import { FieldSetting } from './types'; import { AdvancedSettingsComponent } from './advanced_settings'; import { notificationServiceMock, docLinksServiceMock } from '../../../../core/public/mocks'; @@ -68,7 +72,7 @@ function mockConfig() { remove: (key: string) => Promise.resolve(true), isCustom: (key: string) => false, isOverridden: (key: string) => Boolean(config.getAll()[key].isOverridden), - getRegistered: () => ({} as Readonly>), + getRegistered: () => ({} as Readonly>), overrideLocalDefault: (key: string, value: any) => {}, getUpdate$: () => new Observable<{ @@ -89,7 +93,7 @@ function mockConfig() { getUpdateErrors$: () => new Observable(), get: (key: string, defaultOverride?: any): any => config.getAll()[key] || defaultOverride, get$: (key: string) => new Observable(config.get(key)), - getAll: (): Readonly> => { + getAll: (): Readonly> => { return { 'test:array:setting': { ...defaultConfig, diff --git a/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.test.ts b/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.test.ts index 881a2eb003cc81..7ac9b281eb99aa 100644 --- a/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.test.ts +++ b/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { UiSettingsParams, StringValidationRegex } from 'src/core/public'; +import { PublicUiSettingsParams, StringValidationRegex } from 'src/core/public'; import expect from '@kbn/expect'; import { toEditableConfig } from './to_editable_config'; @@ -30,7 +30,7 @@ function invoke({ name = 'woah', value = 'forreal', }: { - def?: UiSettingsParams & { isOverridden?: boolean }; + def?: PublicUiSettingsParams & { isOverridden?: boolean }; name?: string; value?: any; }) { @@ -55,7 +55,7 @@ describe('Settings', function() { }); describe('when given a setting definition object', function() { - let def: UiSettingsParams & { isOverridden?: boolean }; + let def: PublicUiSettingsParams & { isOverridden?: boolean }; beforeEach(function() { def = { value: 'the original', diff --git a/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.ts b/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.ts index 2c27d72f7f645a..406bc35f826e84 100644 --- a/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.ts +++ b/src/plugins/advanced_settings/public/management_app/lib/to_editable_config.ts @@ -18,7 +18,7 @@ */ import { - UiSettingsParams, + PublicUiSettingsParams, UserProvidedValues, StringValidationRegexString, SavedObjectAttribute, @@ -40,7 +40,7 @@ export function toEditableConfig({ isCustom, isOverridden, }: { - def: UiSettingsParams & UserProvidedValues; + def: PublicUiSettingsParams & UserProvidedValues; name: string; value: SavedObjectAttribute; isCustom: boolean; diff --git a/src/plugins/advanced_settings/public/management_app/types.ts b/src/plugins/advanced_settings/public/management_app/types.ts index d44a05ce36f5d2..ee9b9b0535b794 100644 --- a/src/plugins/advanced_settings/public/management_app/types.ts +++ b/src/plugins/advanced_settings/public/management_app/types.ts @@ -17,17 +17,12 @@ * under the License. */ -import { - UiSettingsType, - StringValidation, - ImageValidation, - SavedObjectAttribute, -} from '../../../../core/public'; +import { UiSettingsType, StringValidation, ImageValidation } from '../../../../core/public'; export interface FieldSetting { displayName: string; name: string; - value: SavedObjectAttribute; + value: unknown; description?: string; options?: string[]; optionLabels?: Record; @@ -36,7 +31,7 @@ export interface FieldSetting { category: string[]; ariaName: string; isOverridden: boolean; - defVal: SavedObjectAttribute; + defVal: unknown; isCustom: boolean; validation?: StringValidation | ImageValidation; readOnly?: boolean; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 333b13eedc17aa..783411bbf27e2e 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -38,6 +38,7 @@ import { Observable } from 'rxjs'; import { Plugin as Plugin_2 } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import { PopoverAnchorPosition } from '@elastic/eui'; +import { PublicUiSettingsParams } from 'src/core/server/types'; import React from 'react'; import * as React_2 from 'react'; import { Required } from '@kbn/utility-types'; @@ -49,7 +50,6 @@ import { SearchResponse as SearchResponse_2 } from 'elasticsearch'; import { SimpleSavedObject } from 'src/core/public'; import { UiActionsSetup } from 'src/plugins/ui_actions/public'; import { UiActionsStart } from 'src/plugins/ui_actions/public'; -import { UiSettingsParams } from 'src/core/server/types'; import { Unit } from '@elastic/datemath'; import { UnregisterCallback } from 'history'; import { UserProvidedValues } from 'src/core/server/types'; diff --git a/src/test_utils/kbn_server.ts b/src/test_utils/kbn_server.ts index f6140ea57ed057..28bce2d97ef4e8 100644 --- a/src/test_utils/kbn_server.ts +++ b/src/test_utils/kbn_server.ts @@ -50,6 +50,7 @@ const DEFAULTS_SETTINGS = { logging: { silent: true }, plugins: {}, optimize: { enabled: false }, + migrations: { skip: true }, }; const DEFAULT_SETTINGS_WITH_CORE_PLUGINS = { diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js index 8cdbbf8e74a3de..57e9120773f33c 100644 --- a/test/api_integration/apis/index.js +++ b/test/api_integration/apis/index.js @@ -33,6 +33,5 @@ export default function({ loadTestFile }) { loadTestFile(require.resolve('./status')); loadTestFile(require.resolve('./stats')); loadTestFile(require.resolve('./ui_metric')); - loadTestFile(require.resolve('./core')); }); } diff --git a/test/plugin_functional/plugins/ui_settings_plugin/server/plugin.ts b/test/plugin_functional/plugins/ui_settings_plugin/server/plugin.ts index c32e8a75d95da5..3801d3bbce055b 100644 --- a/test/plugin_functional/plugins/ui_settings_plugin/server/plugin.ts +++ b/test/plugin_functional/plugins/ui_settings_plugin/server/plugin.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import { schema } from '@kbn/config-schema'; import { Plugin, CoreSetup } from 'kibana/server'; export class UiSettingsPlugin implements Plugin { @@ -27,6 +27,7 @@ export class UiSettingsPlugin implements Plugin { description: 'just for testing', value: '2', category: ['any'], + schema: schema.string(), }, }); diff --git a/x-pack/legacy/plugins/spaces/server/routes/views/enter_space.ts b/x-pack/legacy/plugins/spaces/server/routes/views/enter_space.ts index 337faa2a18fb6b..60ae3a1fa77bbe 100644 --- a/x-pack/legacy/plugins/spaces/server/routes/views/enter_space.ts +++ b/x-pack/legacy/plugins/spaces/server/routes/views/enter_space.ts @@ -14,7 +14,13 @@ export function initEnterSpaceView(server: Legacy.Server) { path: ENTER_SPACE_PATH, async handler(request, h) { try { - return h.redirect(await request.getDefaultRoute()); + const uiSettings = request.getUiSettingsService(); + const defaultRoute = await uiSettings.get('defaultRoute'); + + const basePath = server.newPlatform.setup.core.http.basePath.get(request); + const url = `${basePath}${defaultRoute}`; + + return h.redirect(url); } catch (e) { server.log(['spaces', 'error'], `Error navigating to space: ${e}`); return wrapError(e); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0e0e40b58643fd..16e255263e088d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -833,7 +833,6 @@ "kbn.advancedSettings.defaultIndexTitle": "デフォルトのインデックス", "kbn.advancedSettings.defaultRoute.defaultRouteText": "この設定は、Kibana 起動時のデフォルトのルートを設定します。この設定で、Kibana 起動時のランディングページを変更できます。ルートはスラッシュ (\"/\") で始まる必要があります。", "kbn.advancedSettings.defaultRoute.defaultRouteTitle": "デフォルトのルート", - "kbn.advancedSettings.defaultRoute.defaultRouteValidationMessage": "ルートはスラッシュ (\"/\") で始まる必要があります。", "kbn.advancedSettings.disableAnimationsText": "Kibana UI の不要なアニメーションをオフにします。変更を適用するにはページを更新してください。", "kbn.advancedSettings.disableAnimationsTitle": "アニメーションを無効にする", "kbn.advancedSettings.discover.aggsTermsSizeText": "「可視化」ボタンをクリックした際に、フィールドドロップダウンやディスカバリサイドバーに可視化される用語の数を設定します。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2aabeb13154350..200fc8b703b49f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -833,7 +833,6 @@ "kbn.advancedSettings.defaultIndexTitle": "默认索引", "kbn.advancedSettings.defaultRoute.defaultRouteText": "此设置指定打开 Kibana 时的默认路由。您可以使用此设置修改打开 Kibana 时的登陆页面。路由必须以正斜杠(“/”)开头。", "kbn.advancedSettings.defaultRoute.defaultRouteTitle": "默认路由", - "kbn.advancedSettings.defaultRoute.defaultRouteValidationMessage": "路由必须以正斜杠(“/”)开头", "kbn.advancedSettings.disableAnimationsText": "在 Kibana UI 中关闭所有没有必要的动画。刷新页面以应用更改。", "kbn.advancedSettings.disableAnimationsTitle": "禁用动画", "kbn.advancedSettings.discover.aggsTermsSizeText": "确定在单击“可视化”按钮时将在发现侧边栏的字段下拉列表中可视化多少个词。", diff --git a/x-pack/test/functional/apps/spaces/enter_space.ts b/x-pack/test/functional/apps/spaces/enter_space.ts index e0b1ec544d4602..38220c15cb266b 100644 --- a/x-pack/test/functional/apps/spaces/enter_space.ts +++ b/x-pack/test/functional/apps/spaces/enter_space.ts @@ -10,7 +10,6 @@ export default function enterSpaceFunctonalTests({ getPageObjects, }: FtrProviderContext) { const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['security', 'spaceSelector']); describe('Enter Space', function() { @@ -25,8 +24,8 @@ export default function enterSpaceFunctonalTests({ await PageObjects.security.forceLogout(); }); - it('allows user to navigate to different spaces, respecting the configured default route', async () => { - const spaceId = 'another-space'; + it('falls back to the default home page when the configured default route is malformed', async () => { + const spaceId = 'default'; await PageObjects.security.login(null, null, { expectSpaceSelector: true, @@ -34,22 +33,11 @@ export default function enterSpaceFunctonalTests({ await PageObjects.spaceSelector.clickSpaceCard(spaceId); - await PageObjects.spaceSelector.expectRoute(spaceId, '/app/kibana/#/dashboard'); - - await PageObjects.spaceSelector.openSpacesNav(); - - // change spaces - - await PageObjects.spaceSelector.clickSpaceAvatar('default'); - - await PageObjects.spaceSelector.expectRoute('default', '/app/canvas'); + await PageObjects.spaceSelector.expectHomePage(spaceId); }); - it('falls back to the default home page when the configured default route is malformed', async () => { - await kibanaServer.uiSettings.replace({ defaultRoute: 'http://example.com/evil' }); - - // This test only works with the default space, as other spaces have an enforced relative url of `${serverBasePath}/s/space-id/${defaultRoute}` - const spaceId = 'default'; + it('allows user to navigate to different spaces, respecting the configured default route', async () => { + const spaceId = 'another-space'; await PageObjects.security.login(null, null, { expectSpaceSelector: true, @@ -57,7 +45,15 @@ export default function enterSpaceFunctonalTests({ await PageObjects.spaceSelector.clickSpaceCard(spaceId); - await PageObjects.spaceSelector.expectHomePage(spaceId); + await PageObjects.spaceSelector.expectRoute(spaceId, '/app/canvas'); + + await PageObjects.spaceSelector.openSpacesNav(); + + // change spaces + const newSpaceId = 'default'; + await PageObjects.spaceSelector.clickSpaceAvatar(newSpaceId); + + await PageObjects.spaceSelector.expectHomePage(newSpaceId); }); }); } diff --git a/x-pack/test/functional/es_archives/spaces/enter_space/data.json b/x-pack/test/functional/es_archives/spaces/enter_space/data.json index 462a2a1ee38fe1..475fc14e96e6a3 100644 --- a/x-pack/test/functional/es_archives/spaces/enter_space/data.json +++ b/x-pack/test/functional/es_archives/spaces/enter_space/data.json @@ -7,7 +7,7 @@ "config": { "buildNum": 8467, "dateFormat:tz": "UTC", - "defaultRoute": "/app/canvas" + "defaultRoute": "http://example.com/evil" }, "type": "config" } @@ -24,7 +24,7 @@ "config": { "buildNum": 8467, "dateFormat:tz": "UTC", - "defaultRoute": "/app/kibana/#dashboard" + "defaultRoute": "/app/canvas" }, "type": "config" }