mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* move context to server part. couple with RequestHandlerContext Context implementation will be simplified in follow-up. * adopt core code * adopt bfetch code * adopt data code * adopt search examples * adopt vis_type_timelion * adopt vis_type_timeseries * adopt plugin functional tests * adopt actions * adopt alerting plugin * adopt APM plugin * adopt beats_management * adopt case plugin * adopt cross_cluster_replication * adopt data_enhanced * adopt event_log * adopt global_search * adopt index_management * adopt infra * adopt licensing * adopt lists * adopt logstash * adopt reporting * adopt observability * adopt monitoring * adopt rollup * adopt so tagging * adopt security * adopt security_solutions * adopt watcher * adopt uptime * adopt spaces * adopt snapshot_restore * adopt features changes * mute error when null used to extend context * update docs * small cleanup * add type safety for return type * refactor registerRouteHandlerContext type * update docs * update license header * update docs * fix type error. fetch body does not accept array of strings * fix telemetry test * remove unnecessary ts-ignore * address comments * update docs # Conflicts: # docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md # src/plugins/data/server/server.api.md # x-pack/plugins/monitoring/server/plugin.ts
This commit is contained in:
parent
d8ef1b4adb
commit
99cd66f72d
382 changed files with 2306 additions and 1872 deletions
|
@ -421,29 +421,25 @@ the request handler context:
|
|||
|
||||
[source,typescript]
|
||||
----
|
||||
import type { CoreSetup, IScopedClusterClient } from 'kibana/server';
|
||||
import type { CoreSetup, RequestHandlerContext, IScopedClusterClient } from 'kibana/server';
|
||||
|
||||
export interface MyPluginContext {
|
||||
client: IScopedClusterClient;
|
||||
}
|
||||
|
||||
// extend RequestHandlerContext when a dependent plugin imports MyPluginContext from the file
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
myPlugin?: MyPluginContext;
|
||||
}
|
||||
interface MyRequestHandlerContext extends RequestHandlerContext {
|
||||
myPlugin: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
}
|
||||
|
||||
class MyPlugin {
|
||||
setup(core: CoreSetup) {
|
||||
const client = core.elasticsearch.createClient('myClient');
|
||||
core.http.registerRouteHandlerContext('myPlugin', (context, req, res) => {
|
||||
core.http.registerRouteHandlerContext<MyRequestHandlerContext, 'myPlugin'>('myPlugin', (context, req, res) => {
|
||||
return { client: client.asScoped(req) };
|
||||
});
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<MyRequestHandlerContext>();
|
||||
router.get(
|
||||
{ path: '/api/my-plugin/', validate: … },
|
||||
async (context, req, res) => {
|
||||
// context type is inferred as MyPluginContext
|
||||
const data = await context.myPlugin.client.asCurrentUser('endpoint');
|
||||
}
|
||||
);
|
||||
|
|
|
@ -16,5 +16,5 @@ export interface HttpResources
|
|||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [register](./kibana-plugin-core-server.httpresources.register.md) | <code><P, Q, B>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B>) => void</code> | To register a route handler executing passed function to form response. |
|
||||
| [register](./kibana-plugin-core-server.httpresources.register.md) | <code><P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B, Context>) => void</code> | To register a route handler executing passed function to form response. |
|
||||
|
||||
|
|
|
@ -9,5 +9,5 @@ To register a route handler executing passed function to form response.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
register: <P, Q, B>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B>) => void;
|
||||
register: <P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B, Context>) => void;
|
||||
```
|
||||
|
|
|
@ -9,7 +9,7 @@ Extended version of [RequestHandler](./kibana-plugin-core-server.requesthandler.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type HttpResourcesRequestHandler<P = unknown, Q = unknown, B = unknown> = RequestHandler<P, Q, B, 'get', KibanaResponseFactory & HttpResourcesServiceToolkit>;
|
||||
export declare type HttpResourcesRequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext = RequestHandlerContext> = RequestHandler<P, Q, B, Context, 'get', KibanaResponseFactory & HttpResourcesServiceToolkit>;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
|
@ -9,7 +9,7 @@ Provides ability to declare a handler function for a particular path and HTTP re
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
createRouter: () => IRouter;
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>() => IRouter<Context>;
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
|
|
@ -84,7 +84,7 @@ async (context, request, response) => {
|
|||
| [auth](./kibana-plugin-core-server.httpservicesetup.auth.md) | <code>HttpAuth</code> | Auth status. See [HttpAuth](./kibana-plugin-core-server.httpauth.md) |
|
||||
| [basePath](./kibana-plugin-core-server.httpservicesetup.basepath.md) | <code>IBasePath</code> | Access or manipulate the Kibana base path See [IBasePath](./kibana-plugin-core-server.ibasepath.md)<!-- -->. |
|
||||
| [createCookieSessionStorageFactory](./kibana-plugin-core-server.httpservicesetup.createcookiesessionstoragefactory.md) | <code><T>(cookieOptions: SessionStorageCookieOptions<T>) => Promise<SessionStorageFactory<T>></code> | Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-core-server.sessionstoragefactory.md) |
|
||||
| [createRouter](./kibana-plugin-core-server.httpservicesetup.createrouter.md) | <code>() => IRouter</code> | Provides ability to declare a handler function for a particular path and HTTP request method. |
|
||||
| [createRouter](./kibana-plugin-core-server.httpservicesetup.createrouter.md) | <code><Context extends RequestHandlerContext = RequestHandlerContext>() => IRouter<Context></code> | Provides ability to declare a handler function for a particular path and HTTP request method. |
|
||||
| [csp](./kibana-plugin-core-server.httpservicesetup.csp.md) | <code>ICspConfig</code> | The CSP config used for Kibana. |
|
||||
| [getServerInfo](./kibana-plugin-core-server.httpservicesetup.getserverinfo.md) | <code>() => HttpServerInfo</code> | Provides common [information](./kibana-plugin-core-server.httpserverinfo.md) about the running http server. |
|
||||
| [registerAuth](./kibana-plugin-core-server.httpservicesetup.registerauth.md) | <code>(handler: AuthenticationHandler) => void</code> | To define custom authentication and/or authorization mechanism for incoming requests. |
|
||||
|
@ -92,5 +92,5 @@ async (context, request, response) => {
|
|||
| [registerOnPreAuth](./kibana-plugin-core-server.httpservicesetup.registeronpreauth.md) | <code>(handler: OnPreAuthHandler) => void</code> | To define custom logic to perform for incoming requests before the Auth interceptor performs a check that user has access to requested resources. |
|
||||
| [registerOnPreResponse](./kibana-plugin-core-server.httpservicesetup.registeronpreresponse.md) | <code>(handler: OnPreResponseHandler) => void</code> | To define custom logic to perform for the server response. |
|
||||
| [registerOnPreRouting](./kibana-plugin-core-server.httpservicesetup.registeronprerouting.md) | <code>(handler: OnPreRoutingHandler) => void</code> | To define custom logic to perform for incoming requests before server performs a route lookup. |
|
||||
| [registerRouteHandlerContext](./kibana-plugin-core-server.httpservicesetup.registerroutehandlercontext.md) | <code><T extends keyof RequestHandlerContext>(contextName: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer</code> | Register a context provider for a route handler. |
|
||||
| [registerRouteHandlerContext](./kibana-plugin-core-server.httpservicesetup.registerroutehandlercontext.md) | <code><Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer</code> | Register a context provider for a route handler. |
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Register a context provider for a route handler.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(contextName: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer;
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
@ -17,7 +17,10 @@ registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(contextName
|
|||
|
||||
```ts
|
||||
// my-plugin.ts
|
||||
deps.http.registerRouteHandlerContext(
|
||||
interface MyRequestHandlerContext extends RequestHandlerContext {
|
||||
myApp: { search(id: string): Promise<Result> };
|
||||
}
|
||||
deps.http.registerRouteHandlerContext<MyRequestHandlerContext, 'myApp'>(
|
||||
'myApp',
|
||||
(context, req) => {
|
||||
async function search (id: string) {
|
||||
|
@ -28,6 +31,8 @@ registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(contextName
|
|||
);
|
||||
|
||||
// my-route-handler.ts
|
||||
import type { MyRequestHandlerContext } from './my-plugin.ts';
|
||||
const router = createRouter<MyRequestHandlerContext>();
|
||||
router.get({ path: '/', validate: false }, async (context, req, res) => {
|
||||
const response = await context.myApp.search(...);
|
||||
return res.ok(response);
|
||||
|
|
|
@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface IContextContainer<THandler extends HandlerFunction<any>>
|
||||
export interface IContextContainer<THandler extends RequestHandler>
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
|
|
@ -9,7 +9,7 @@ Register a new context provider.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
registerContext<TContextName extends keyof HandlerContextType<THandler>>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider<THandler, TContextName>): this;
|
||||
registerContext<Context extends RequestHandlerContext, ContextName extends keyof Context>(pluginOpaqueId: PluginOpaqueId, contextName: ContextName, provider: IContextProvider<Context, ContextName>): this;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
@ -17,8 +17,8 @@ registerContext<TContextName extends keyof HandlerContextType<THandler>>(pluginO
|
|||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| pluginOpaqueId | <code>PluginOpaqueId</code> | The plugin opaque ID for the plugin that registers this context. |
|
||||
| contextName | <code>TContextName</code> | The key of the <code>TContext</code> object this provider supplies the value for. |
|
||||
| provider | <code>IContextProvider<THandler, TContextName></code> | A [IContextProvider](./kibana-plugin-core-server.icontextprovider.md) to be called each time a new context is created. |
|
||||
| contextName | <code>ContextName</code> | The key of the <code>TContext</code> object this provider supplies the value for. |
|
||||
| provider | <code>IContextProvider<Context, ContextName></code> | A [IContextProvider](./kibana-plugin-core-server.icontextprovider.md) to be called each time a new context is created. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type IContextProvider<THandler extends HandlerFunction<any>, TContextName extends keyof HandlerContextType<THandler>> = (context: PartialExceptFor<HandlerContextType<THandler>, 'core'>, ...rest: HandlerParameters<THandler>) => Promise<HandlerContextType<THandler>[TContextName]> | HandlerContextType<THandler>[TContextName];
|
||||
export declare type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
|
|
@ -9,5 +9,5 @@ Register a route handler for `DELETE` request.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
delete: RouteRegistrar<'delete'>;
|
||||
delete: RouteRegistrar<'delete', Context>;
|
||||
```
|
||||
|
|
|
@ -9,5 +9,5 @@ Register a route handler for `GET` request.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
get: RouteRegistrar<'get'>;
|
||||
get: RouteRegistrar<'get', Context>;
|
||||
```
|
||||
|
|
|
@ -9,18 +9,18 @@ Registers route handlers for specified resource path and method. See [RouteConfi
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface IRouter
|
||||
export interface IRouter<Context extends RequestHandlerContext = RequestHandlerContext>
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [delete](./kibana-plugin-core-server.irouter.delete.md) | <code>RouteRegistrar<'delete'></code> | Register a route handler for <code>DELETE</code> request. |
|
||||
| [get](./kibana-plugin-core-server.irouter.get.md) | <code>RouteRegistrar<'get'></code> | Register a route handler for <code>GET</code> request. |
|
||||
| [delete](./kibana-plugin-core-server.irouter.delete.md) | <code>RouteRegistrar<'delete', Context></code> | Register a route handler for <code>DELETE</code> request. |
|
||||
| [get](./kibana-plugin-core-server.irouter.get.md) | <code>RouteRegistrar<'get', Context></code> | Register a route handler for <code>GET</code> request. |
|
||||
| [handleLegacyErrors](./kibana-plugin-core-server.irouter.handlelegacyerrors.md) | <code>RequestHandlerWrapper</code> | Wrap a router handler to catch and converts legacy boom errors to proper custom errors. |
|
||||
| [patch](./kibana-plugin-core-server.irouter.patch.md) | <code>RouteRegistrar<'patch'></code> | Register a route handler for <code>PATCH</code> request. |
|
||||
| [post](./kibana-plugin-core-server.irouter.post.md) | <code>RouteRegistrar<'post'></code> | Register a route handler for <code>POST</code> request. |
|
||||
| [put](./kibana-plugin-core-server.irouter.put.md) | <code>RouteRegistrar<'put'></code> | Register a route handler for <code>PUT</code> request. |
|
||||
| [patch](./kibana-plugin-core-server.irouter.patch.md) | <code>RouteRegistrar<'patch', Context></code> | Register a route handler for <code>PATCH</code> request. |
|
||||
| [post](./kibana-plugin-core-server.irouter.post.md) | <code>RouteRegistrar<'post', Context></code> | Register a route handler for <code>POST</code> request. |
|
||||
| [put](./kibana-plugin-core-server.irouter.put.md) | <code>RouteRegistrar<'put', Context></code> | Register a route handler for <code>PUT</code> request. |
|
||||
| [routerPath](./kibana-plugin-core-server.irouter.routerpath.md) | <code>string</code> | Resulted path |
|
||||
|
||||
|
|
|
@ -9,5 +9,5 @@ Register a route handler for `PATCH` request.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
patch: RouteRegistrar<'patch'>;
|
||||
patch: RouteRegistrar<'patch', Context>;
|
||||
```
|
||||
|
|
|
@ -9,5 +9,5 @@ Register a route handler for `POST` request.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
post: RouteRegistrar<'post'>;
|
||||
post: RouteRegistrar<'post', Context>;
|
||||
```
|
||||
|
|
|
@ -9,5 +9,5 @@ Register a route handler for `PUT` request.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
put: RouteRegistrar<'put'>;
|
||||
put: RouteRegistrar<'put', Context>;
|
||||
```
|
||||
|
|
|
@ -9,7 +9,7 @@ A function executed when route path matched requested resource path. Request han
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type RequestHandler<P = unknown, Q = unknown, B = unknown, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: RequestHandlerContext, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
export declare type RequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: Context, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
|
@ -9,5 +9,5 @@ An object that handles registration of http request context providers.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type RequestHandlerContextContainer = IContextContainer<RequestHandler<any, any, any>>;
|
||||
export declare type RequestHandlerContextContainer = IContextContainer<RequestHandler>;
|
||||
```
|
||||
|
|
|
@ -9,5 +9,5 @@ Context provider for request handler. Extends request context object with provid
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type RequestHandlerContextProvider<TContextName extends keyof RequestHandlerContext> = IContextProvider<RequestHandler<any, any, any>, TContextName>;
|
||||
export declare type RequestHandlerContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = IContextProvider<Context, ContextName>;
|
||||
```
|
||||
|
|
|
@ -9,7 +9,7 @@ Type-safe wrapper for [RequestHandler](./kibana-plugin-core-server.requesthandle
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type RequestHandlerWrapper = <P, Q, B, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory>(handler: RequestHandler<P, Q, B, Method, ResponseFactory>) => RequestHandler<P, Q, B, Method, ResponseFactory>;
|
||||
export declare type RequestHandlerWrapper = <P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory>(handler: RequestHandler<P, Q, B, Context, Method, ResponseFactory>) => RequestHandler<P, Q, B, Context, Method, ResponseFactory>;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
|
@ -9,5 +9,5 @@ Route handler common definition
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type RouteRegistrar<Method extends RouteMethod> = <P, Q, B>(route: RouteConfig<P, Q, B, Method>, handler: RequestHandler<P, Q, B, Method>) => void;
|
||||
export declare type RouteRegistrar<Method extends RouteMethod, Context extends RequestHandlerContext = RequestHandlerContext> = <P, Q, B>(route: RouteConfig<P, Q, B, Method>, handler: RequestHandler<P, Q, B, Context, Method>) => void;
|
||||
```
|
||||
|
|
|
@ -15,13 +15,13 @@ Using `createSearchSource`<!-- -->, the instance can be re-created.
|
|||
```typescript
|
||||
serialize(): {
|
||||
searchSourceJSON: string;
|
||||
references: import("src/core/server").SavedObjectReference[];
|
||||
references: import("../../../../../core/types").SavedObjectReference[];
|
||||
};
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
`{
|
||||
searchSourceJSON: string;
|
||||
references: import("src/core/server").SavedObjectReference[];
|
||||
references: import("../../../../../core/types").SavedObjectReference[];
|
||||
}`
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [DataApiRequestHandlerContext](./kibana-plugin-plugins-data-server.dataapirequesthandlercontext.md)
|
||||
|
||||
## DataApiRequestHandlerContext interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface DataApiRequestHandlerContext extends ISearchClient
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [session](./kibana-plugin-plugins-data-server.dataapirequesthandlercontext.session.md) | <code>IScopedSessionService</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [DataApiRequestHandlerContext](./kibana-plugin-plugins-data-server.dataapirequesthandlercontext.md) > [session](./kibana-plugin-plugins-data-server.dataapirequesthandlercontext.session.md)
|
||||
|
||||
## DataApiRequestHandlerContext.session property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
session: IScopedSessionService;
|
||||
```
|
|
@ -45,6 +45,7 @@
|
|||
| --- | --- |
|
||||
| [AggFunctionsMapping](./kibana-plugin-plugins-data-server.aggfunctionsmapping.md) | A global list of the expression function definitions for each agg type function. |
|
||||
| [AggParamOption](./kibana-plugin-plugins-data-server.aggparamoption.md) | |
|
||||
| [DataApiRequestHandlerContext](./kibana-plugin-plugins-data-server.dataapirequesthandlercontext.md) | |
|
||||
| [EsQueryConfig](./kibana-plugin-plugins-data-server.esqueryconfig.md) | |
|
||||
| [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) | |
|
||||
| [FieldFormatConfig](./kibana-plugin-plugins-data-server.fieldformatconfig.md) | |
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
```typescript
|
||||
start(core: CoreStart): {
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
indexPatterns: {
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("src/core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("../../../core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
};
|
||||
search: ISearchStart<import("./search").IEsSearchRequest, import("./search").IEsSearchResponse<any>>;
|
||||
};
|
||||
|
@ -28,10 +28,10 @@ start(core: CoreStart): {
|
|||
|
||||
`{
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
indexPatterns: {
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("src/core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("../../../core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
};
|
||||
search: ISearchStart<import("./search").IEsSearchRequest, import("./search").IEsSearchResponse<any>>;
|
||||
}`
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
import type {
|
||||
PluginInitializerContext,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
Logger,
|
||||
} from '../../../src/core/server';
|
||||
RequestHandlerContext,
|
||||
} from 'src/core/server';
|
||||
|
||||
import type { DataApiRequestHandlerContext } from 'src/plugins/data/server';
|
||||
|
||||
import {
|
||||
SearchExamplesPluginSetup,
|
||||
|
@ -42,12 +45,14 @@ export class SearchExamplesPlugin
|
|||
deps: SearchExamplesPluginSetupDeps
|
||||
) {
|
||||
this.logger.debug('search_examples: Setup');
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<
|
||||
RequestHandlerContext & { search: DataApiRequestHandlerContext }
|
||||
>();
|
||||
|
||||
core.getStartServices().then(([_, depsStart]) => {
|
||||
const myStrategy = mySearchStrategyProvider(depsStart.data);
|
||||
deps.data.search.registerSearchStrategy('myStrategy', myStrategy);
|
||||
registerRoutes(router, depsStart.data);
|
||||
registerRoutes(router);
|
||||
});
|
||||
|
||||
return {};
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { PluginStart as DataPluginStart } from 'src/plugins/data/server';
|
||||
import type { IRouter, RequestHandlerContext } from 'kibana/server';
|
||||
import { DataApiRequestHandlerContext } from 'src/plugins/data/server';
|
||||
import { registerServerSearchRoute } from './server_search_route';
|
||||
|
||||
export function registerRoutes(router: IRouter, data: DataPluginStart) {
|
||||
registerServerSearchRoute(router, data);
|
||||
export function registerRoutes(
|
||||
router: IRouter<RequestHandlerContext & { search: DataApiRequestHandlerContext }>
|
||||
) {
|
||||
registerServerSearchRoute(router);
|
||||
}
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginStart as DataPluginStart, IEsSearchRequest } from 'src/plugins/data/server';
|
||||
import { IEsSearchRequest } from 'src/plugins/data/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IEsSearchResponse } from 'src/plugins/data/common';
|
||||
import { IRouter } from '../../../../src/core/server';
|
||||
import type { DataApiRequestHandlerContext } from 'src/plugins/data/server';
|
||||
import type { IRouter, RequestHandlerContext } from 'src/core/server';
|
||||
import { SERVER_SEARCH_ROUTE_PATH } from '../../common';
|
||||
|
||||
export function registerServerSearchRoute(router: IRouter, data: DataPluginStart) {
|
||||
export function registerServerSearchRoute(
|
||||
router: IRouter<RequestHandlerContext & { search: DataApiRequestHandlerContext }>
|
||||
) {
|
||||
router.get(
|
||||
{
|
||||
path: SERVER_SEARCH_ROUTE_PATH,
|
||||
|
|
|
@ -12,6 +12,7 @@ export type ContextContainerMock = jest.Mocked<IContextContainer<any>>;
|
|||
|
||||
const createContextMock = (mockContext = {}) => {
|
||||
const contextMock: ContextContainerMock = {
|
||||
// @ts-expect-error tsc cannot infer ContextName and uses never
|
||||
registerContext: jest.fn(),
|
||||
createHandler: jest.fn(),
|
||||
};
|
319
src/core/server/context/container/context.test.ts
Normal file
319
src/core/server/context/container/context.test.ts
Normal file
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* and the Server Side Public License, v 1; you may not use this file except in
|
||||
* compliance with, at your election, the Elastic License or the Server Side
|
||||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ContextContainer } from './context';
|
||||
import { PluginOpaqueId } from '../..';
|
||||
import { httpServerMock } from '../../http/http_server.mocks';
|
||||
|
||||
const pluginA = Symbol('pluginA');
|
||||
const pluginB = Symbol('pluginB');
|
||||
const pluginC = Symbol('pluginC');
|
||||
const pluginD = Symbol('pluginD');
|
||||
const plugins: ReadonlyMap<PluginOpaqueId, PluginOpaqueId[]> = new Map([
|
||||
[pluginA, []],
|
||||
[pluginB, [pluginA]],
|
||||
[pluginC, [pluginA, pluginB]],
|
||||
[pluginD, []],
|
||||
]);
|
||||
const coreId = Symbol();
|
||||
|
||||
interface MyContext {
|
||||
core: any;
|
||||
core1: string;
|
||||
core2: number;
|
||||
ctxFromA: string;
|
||||
ctxFromB: number;
|
||||
ctxFromC: boolean;
|
||||
ctxFromD: object;
|
||||
}
|
||||
|
||||
describe('ContextContainer', () => {
|
||||
it('does not allow the same context to be registered twice', () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
coreId,
|
||||
'ctxFromA',
|
||||
() => 'aString'
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
coreId,
|
||||
'ctxFromA',
|
||||
() => 'aString'
|
||||
)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Context provider for ctxFromA has already been registered."`
|
||||
);
|
||||
});
|
||||
|
||||
describe('registerContext', () => {
|
||||
it('throws error if called with an unknown symbol', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
await expect(() =>
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
Symbol('unknown'),
|
||||
'ctxFromA',
|
||||
jest.fn()
|
||||
)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Cannot register context for unknown plugin: Symbol(unknown)"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('context building', () => {
|
||||
it('resolves dependencies', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
expect.assertions(8);
|
||||
contextContainer.registerContext<{ core1: string; core: any }, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
(context) => {
|
||||
expect(context).toEqual({});
|
||||
return 'core';
|
||||
}
|
||||
);
|
||||
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return 'aString';
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromB: number; core: any }, 'ctxFromB'>(
|
||||
pluginB,
|
||||
'ctxFromB',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core', ctxFromA: 'aString' });
|
||||
return 299;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromC: boolean; core: any }, 'ctxFromC'>(
|
||||
pluginC,
|
||||
'ctxFromC',
|
||||
(context) => {
|
||||
expect(context).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromD: {}; core: any }, 'ctxFromD'>(
|
||||
pluginD,
|
||||
'ctxFromD',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return {};
|
||||
}
|
||||
);
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const rawHandler2 = jest.fn(() => 'handler2' as any);
|
||||
const handler2 = contextContainer.createHandler(pluginD, rawHandler2);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
|
||||
await handler1(request, response);
|
||||
await handler2(request, response);
|
||||
|
||||
// Should have context from pluginC, its deps, and core
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
ctxFromC: false,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
|
||||
// Should have context from pluginD, and core
|
||||
expect(rawHandler2).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromD: {},
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
|
||||
it('exposes all core context to all providers regardless of registration order', async () => {
|
||||
expect.assertions(4);
|
||||
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
contextContainer
|
||||
.registerContext<MyContext, 'ctxFromA'>(pluginA, 'ctxFromA', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', core2: 101 });
|
||||
return `aString ${context.core1} ${context.core2}`;
|
||||
})
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', () => 'core')
|
||||
.registerContext<MyContext, 'core2'>(coreId, 'core2', () => 101)
|
||||
.registerContext<MyContext, 'ctxFromB'>(pluginB, 'ctxFromB', (context) => {
|
||||
expect(context).toEqual({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
});
|
||||
return 277;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginB, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
ctxFromB: 277,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
|
||||
it('exposes all core context to core providers', async () => {
|
||||
expect.assertions(4);
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
contextContainer
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', (context) => {
|
||||
expect(context).toEqual({});
|
||||
return 'core';
|
||||
})
|
||||
.registerContext<MyContext, 'core2'>(coreId, 'core2', (context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return 101;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
// If no context is registered for pluginA, only core contexts should be exposed
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
|
||||
it('does not expose plugin contexts to core handler', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
contextContainer
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', (context) => 'core')
|
||||
.registerContext<MyContext, 'ctxFromA'>(pluginA, 'ctxFromA', (context) => 'aString');
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(coreId, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
// pluginA context should not be present in a core handler
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
|
||||
it('passes additional arguments to providers', async () => {
|
||||
expect.assertions(6);
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
contextContainer.registerContext<MyContext, 'core1'>(coreId, 'core1', (context, req, res) => {
|
||||
expect(req).toBe(request);
|
||||
expect(res).toBe(response);
|
||||
return 'core';
|
||||
});
|
||||
|
||||
contextContainer.registerContext<MyContext, 'ctxFromB'>(
|
||||
pluginD,
|
||||
'ctxFromB',
|
||||
(context, req, res) => {
|
||||
expect(req).toBe(request);
|
||||
expect(res).toBe(response);
|
||||
return 77;
|
||||
}
|
||||
);
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginD, rawHandler1);
|
||||
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromB: 77,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createHandler', () => {
|
||||
it('throws error if called with an unknown symbol', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
await expect(() =>
|
||||
contextContainer.createHandler(Symbol('unknown'), jest.fn())
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Cannot create handler for unknown plugin: Symbol(unknown)"`
|
||||
);
|
||||
});
|
||||
|
||||
it('returns value from original handler', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
});
|
||||
|
||||
it('passes additional arguments to handlers', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
expect(rawHandler1).toHaveBeenCalledWith({}, request, response);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,13 +8,8 @@
|
|||
|
||||
import { flatten } from 'lodash';
|
||||
import { ShallowPromise } from '@kbn/utility-types';
|
||||
import { pick } from '@kbn/std';
|
||||
import type { CoreId, PluginOpaqueId } from '../server';
|
||||
|
||||
/**
|
||||
* Make all properties in T optional, except for the properties whose keys are in the union K
|
||||
*/
|
||||
type PartialExceptFor<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||
import { pick } from 'lodash';
|
||||
import type { CoreId, PluginOpaqueId, RequestHandler, RequestHandlerContext } from '../..';
|
||||
|
||||
/**
|
||||
* A function that returns a context value for a specific key of given context type.
|
||||
|
@ -30,15 +25,13 @@ type PartialExceptFor<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
|||
* @public
|
||||
*/
|
||||
export type IContextProvider<
|
||||
THandler extends HandlerFunction<any>,
|
||||
TContextName extends keyof HandlerContextType<THandler>
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
> = (
|
||||
// context.core will always be available, but plugin contexts are typed as optional
|
||||
context: PartialExceptFor<HandlerContextType<THandler>, 'core'>,
|
||||
...rest: HandlerParameters<THandler>
|
||||
) =>
|
||||
| Promise<HandlerContextType<THandler>[TContextName]>
|
||||
| HandlerContextType<THandler>[TContextName];
|
||||
context: Omit<Context, ContextName>,
|
||||
...rest: HandlerParameters<RequestHandler>
|
||||
) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
|
||||
/**
|
||||
* A function that accepts a context object and an optional number of additional arguments. Used for the generic types
|
||||
|
@ -142,7 +135,7 @@ export type HandlerParameters<T extends HandlerFunction<any>> = T extends (
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IContextContainer<THandler extends HandlerFunction<any>> {
|
||||
export interface IContextContainer<THandler extends RequestHandler> {
|
||||
/**
|
||||
* Register a new context provider.
|
||||
*
|
||||
|
@ -157,10 +150,10 @@ export interface IContextContainer<THandler extends HandlerFunction<any>> {
|
|||
* @param provider - A {@link IContextProvider} to be called each time a new context is created.
|
||||
* @returns The {@link IContextContainer} for method chaining.
|
||||
*/
|
||||
registerContext<TContextName extends keyof HandlerContextType<THandler>>(
|
||||
registerContext<Context extends RequestHandlerContext, ContextName extends keyof Context>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: TContextName,
|
||||
provider: IContextProvider<THandler, TContextName>
|
||||
contextName: ContextName,
|
||||
provider: IContextProvider<Context, ContextName>
|
||||
): this;
|
||||
|
||||
/**
|
||||
|
@ -178,21 +171,21 @@ export interface IContextContainer<THandler extends HandlerFunction<any>> {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
export class ContextContainer<THandler extends HandlerFunction<any>>
|
||||
export class ContextContainer<THandler extends RequestHandler>
|
||||
implements IContextContainer<THandler> {
|
||||
/**
|
||||
* Used to map contexts to their providers and associated plugin. In registration order which is tightly coupled to
|
||||
* plugin load order.
|
||||
*/
|
||||
private readonly contextProviders = new Map<
|
||||
keyof HandlerContextType<THandler>,
|
||||
string,
|
||||
{
|
||||
provider: IContextProvider<THandler, keyof HandlerContextType<THandler>>;
|
||||
provider: IContextProvider<any, any>;
|
||||
source: symbol;
|
||||
}
|
||||
>();
|
||||
/** Used to keep track of which plugins registered which contexts for dependency resolution. */
|
||||
private readonly contextNamesBySource: Map<symbol, Array<keyof HandlerContextType<THandler>>>;
|
||||
private readonly contextNamesBySource: Map<symbol, string[]>;
|
||||
|
||||
/**
|
||||
* @param pluginDependencies - A map of plugins to an array of their dependencies.
|
||||
|
@ -201,16 +194,18 @@ export class ContextContainer<THandler extends HandlerFunction<any>>
|
|||
private readonly pluginDependencies: ReadonlyMap<PluginOpaqueId, PluginOpaqueId[]>,
|
||||
private readonly coreId: CoreId
|
||||
) {
|
||||
this.contextNamesBySource = new Map<symbol, Array<keyof HandlerContextType<THandler>>>([
|
||||
[coreId, []],
|
||||
]);
|
||||
this.contextNamesBySource = new Map<symbol, string[]>([[coreId, []]]);
|
||||
}
|
||||
|
||||
public registerContext = <TContextName extends keyof HandlerContextType<THandler>>(
|
||||
public registerContext = <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
source: symbol,
|
||||
contextName: TContextName,
|
||||
provider: IContextProvider<THandler, TContextName>
|
||||
name: ContextName,
|
||||
provider: IContextProvider<Context, ContextName>
|
||||
): this => {
|
||||
const contextName = name as string;
|
||||
if (this.contextProviders.has(contextName)) {
|
||||
throw new Error(`Context provider for ${contextName} has already been registered.`);
|
||||
}
|
||||
|
@ -234,6 +229,7 @@ export class ContextContainer<THandler extends HandlerFunction<any>>
|
|||
|
||||
return (async (...args: HandlerParameters<THandler>) => {
|
||||
const context = await this.buildContext(source, ...args);
|
||||
// @ts-expect-error requires explicit handler arity
|
||||
return handler(context, ...args);
|
||||
}) as (...args: HandlerParameters<THandler>) => ShallowPromise<ReturnType<THandler>>;
|
||||
};
|
||||
|
@ -242,9 +238,7 @@ export class ContextContainer<THandler extends HandlerFunction<any>>
|
|||
source: symbol,
|
||||
...contextArgs: HandlerParameters<THandler>
|
||||
): Promise<HandlerContextType<THandler>> {
|
||||
const contextsToBuild: ReadonlySet<keyof HandlerContextType<THandler>> = new Set(
|
||||
this.getContextNamesForSource(source)
|
||||
);
|
||||
const contextsToBuild = new Set(this.getContextNamesForSource(source));
|
||||
|
||||
return [...this.contextProviders]
|
||||
.sort(sortByCoreFirst(this.coreId))
|
||||
|
@ -256,18 +250,17 @@ export class ContextContainer<THandler extends HandlerFunction<any>>
|
|||
// registered that provider.
|
||||
const exposedContext = pick(resolvedContext, [
|
||||
...this.getContextNamesForSource(providerSource),
|
||||
]) as PartialExceptFor<HandlerContextType<THandler>, 'core'>;
|
||||
]);
|
||||
|
||||
return {
|
||||
...resolvedContext,
|
||||
// @ts-expect-error requires explicit provider arity
|
||||
[contextName]: await provider(exposedContext, ...contextArgs),
|
||||
};
|
||||
}, Promise.resolve({}) as Promise<HandlerContextType<THandler>>);
|
||||
}
|
||||
|
||||
private getContextNamesForSource(
|
||||
source: symbol
|
||||
): ReadonlySet<keyof HandlerContextType<THandler>> {
|
||||
private getContextNamesForSource(source: symbol): ReadonlySet<string> {
|
||||
if (source === this.coreId) {
|
||||
return this.getContextNamesForCore();
|
||||
} else {
|
9
src/core/server/context/container/index.ts
Normal file
9
src/core/server/context/container/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* and the Server Side Public License, v 1; you may not use this file except in
|
||||
* compliance with, at your election, the Elastic License or the Server Side
|
||||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './context';
|
|
@ -9,7 +9,7 @@
|
|||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
|
||||
import { ContextService, ContextSetup } from './context_service';
|
||||
import { contextMock } from '../../utils/context.mock';
|
||||
import { contextMock } from './container/context.mock';
|
||||
|
||||
const createSetupContractMock = (mockContext = {}) => {
|
||||
const setupContract: jest.Mocked<ContextSetup> = {
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { contextMock } from '../../utils/context.mock';
|
||||
import { contextMock } from './container/context.mock';
|
||||
|
||||
export const MockContextConstructor = jest.fn(contextMock.create);
|
||||
jest.doMock('../../utils/context', () => ({
|
||||
jest.doMock('./container/context', () => ({
|
||||
ContextContainer: MockContextConstructor,
|
||||
}));
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { PluginOpaqueId } from '../../server';
|
||||
import { IContextContainer, ContextContainer, HandlerFunction } from '../../utils/context';
|
||||
import { IContextContainer, ContextContainer, HandlerFunction } from './container';
|
||||
import { CoreContext } from '../core_context';
|
||||
|
||||
interface SetupDeps {
|
||||
|
|
|
@ -13,4 +13,4 @@ export {
|
|||
HandlerFunction,
|
||||
HandlerContextType,
|
||||
HandlerParameters,
|
||||
} from '../../utils/context';
|
||||
} from './container';
|
||||
|
|
|
@ -89,6 +89,7 @@ const createInternalSetupContractMock = () => {
|
|||
registerOnPreAuth: jest.fn(),
|
||||
registerAuth: jest.fn(),
|
||||
registerOnPostAuth: jest.fn(),
|
||||
// @ts-expect-error tsc cannot infer ContextName and uses never
|
||||
registerRouteHandlerContext: jest.fn(),
|
||||
registerOnPreResponse: jest.fn(),
|
||||
createRouter: jest.fn().mockImplementation(() => mockRouter.create({})),
|
||||
|
@ -125,6 +126,7 @@ const createSetupContractMock = () => {
|
|||
basePath: internalMock.basePath,
|
||||
csp: CspConfig.DEFAULT,
|
||||
createRouter: jest.fn(),
|
||||
// @ts-expect-error tsc cannot infer ContextName and uses never
|
||||
registerRouteHandlerContext: jest.fn(),
|
||||
auth: {
|
||||
get: internalMock.auth.get,
|
||||
|
|
|
@ -11,6 +11,7 @@ import { first, map } from 'rxjs/operators';
|
|||
import { Server } from '@hapi/hapi';
|
||||
import { pick } from '@kbn/std';
|
||||
|
||||
import type { RequestHandlerContext } from 'src/core/server';
|
||||
import { CoreService } from '../../types';
|
||||
import { Logger, LoggerFactory } from '../logging';
|
||||
import { ContextSetup } from '../context';
|
||||
|
@ -31,7 +32,6 @@ import {
|
|||
InternalHttpServiceStart,
|
||||
} from './types';
|
||||
|
||||
import { RequestHandlerContext } from '../../server';
|
||||
import { registerCoreHandlers } from './lifecycle_handlers';
|
||||
import {
|
||||
ExternalUrlConfigType,
|
||||
|
@ -100,17 +100,23 @@ export class HttpService
|
|||
|
||||
externalUrl: new ExternalUrlConfig(config.externalUrl),
|
||||
|
||||
createRouter: (path: string, pluginId: PluginOpaqueId = this.coreContext.coreId) => {
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>(
|
||||
path: string,
|
||||
pluginId: PluginOpaqueId = this.coreContext.coreId
|
||||
) => {
|
||||
const enhanceHandler = this.requestHandlerContext!.createHandler.bind(null, pluginId);
|
||||
const router = new Router(path, this.log, enhanceHandler);
|
||||
const router = new Router<Context>(path, this.log, enhanceHandler);
|
||||
registerRouter(router);
|
||||
return router;
|
||||
},
|
||||
|
||||
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: T,
|
||||
provider: RequestHandlerContextProvider<T>
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
) => this.requestHandlerContext!.registerContext(pluginOpaqueId, contextName, provider),
|
||||
};
|
||||
|
||||
|
|
|
@ -175,19 +175,19 @@ describe('core lifecycle handlers', () => {
|
|||
});
|
||||
|
||||
destructiveMethods.forEach((method) => {
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any>)<any, any, any>(
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any, any>)<any, any, any>(
|
||||
{ path: testPath, validate: false },
|
||||
(context, req, res) => {
|
||||
return res.ok({ body: 'ok' });
|
||||
}
|
||||
);
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any>)<any, any, any>(
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any, any>)<any, any, any>(
|
||||
{ path: allowlistedTestPath, validate: false },
|
||||
(context, req, res) => {
|
||||
return res.ok({ body: 'ok' });
|
||||
}
|
||||
);
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any>)<any, any, any>(
|
||||
((router as any)[method.toLowerCase()] as RouteRegistrar<any, any>)<any, any, any>(
|
||||
{ path: xsrfDisabledTestPath, validate: false, options: { xsrfRequired: false } },
|
||||
(context, req, res) => {
|
||||
return res.ok({ body: 'ok' });
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { IRouter } from './router';
|
||||
|
||||
export type RouterMock = jest.Mocked<IRouter>;
|
||||
export type RouterMock = jest.Mocked<IRouter<any>>;
|
||||
|
||||
function create({ routerPath = '' }: { routerPath?: string } = {}): RouterMock {
|
||||
return {
|
||||
|
|
|
@ -44,9 +44,12 @@ interface RouterRoute {
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
export type RouteRegistrar<Method extends RouteMethod> = <P, Q, B>(
|
||||
export type RouteRegistrar<
|
||||
Method extends RouteMethod,
|
||||
Context extends RequestHandlerContext = RequestHandlerContext
|
||||
> = <P, Q, B>(
|
||||
route: RouteConfig<P, Q, B, Method>,
|
||||
handler: RequestHandler<P, Q, B, Method>
|
||||
handler: RequestHandler<P, Q, B, Context, Method>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
|
@ -55,7 +58,7 @@ export type RouteRegistrar<Method extends RouteMethod> = <P, Q, B>(
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
export interface IRouter {
|
||||
export interface IRouter<Context extends RequestHandlerContext = RequestHandlerContext> {
|
||||
/**
|
||||
* Resulted path
|
||||
*/
|
||||
|
@ -66,35 +69,35 @@ export interface IRouter {
|
|||
* @param route {@link RouteConfig} - a route configuration.
|
||||
* @param handler {@link RequestHandler} - a function to call to respond to an incoming request
|
||||
*/
|
||||
get: RouteRegistrar<'get'>;
|
||||
get: RouteRegistrar<'get', Context>;
|
||||
|
||||
/**
|
||||
* Register a route handler for `POST` request.
|
||||
* @param route {@link RouteConfig} - a route configuration.
|
||||
* @param handler {@link RequestHandler} - a function to call to respond to an incoming request
|
||||
*/
|
||||
post: RouteRegistrar<'post'>;
|
||||
post: RouteRegistrar<'post', Context>;
|
||||
|
||||
/**
|
||||
* Register a route handler for `PUT` request.
|
||||
* @param route {@link RouteConfig} - a route configuration.
|
||||
* @param handler {@link RequestHandler} - a function to call to respond to an incoming request
|
||||
*/
|
||||
put: RouteRegistrar<'put'>;
|
||||
put: RouteRegistrar<'put', Context>;
|
||||
|
||||
/**
|
||||
* Register a route handler for `PATCH` request.
|
||||
* @param route {@link RouteConfig} - a route configuration.
|
||||
* @param handler {@link RequestHandler} - a function to call to respond to an incoming request
|
||||
*/
|
||||
patch: RouteRegistrar<'patch'>;
|
||||
patch: RouteRegistrar<'patch', Context>;
|
||||
|
||||
/**
|
||||
* Register a route handler for `DELETE` request.
|
||||
* @param route {@link RouteConfig} - a route configuration.
|
||||
* @param handler {@link RequestHandler} - a function to call to respond to an incoming request
|
||||
*/
|
||||
delete: RouteRegistrar<'delete'>;
|
||||
delete: RouteRegistrar<'delete', Context>;
|
||||
|
||||
/**
|
||||
* Wrap a router handler to catch and converts legacy boom errors to proper custom errors.
|
||||
|
@ -110,9 +113,13 @@ export interface IRouter {
|
|||
getRoutes: () => RouterRoute[];
|
||||
}
|
||||
|
||||
export type ContextEnhancer<P, Q, B, Method extends RouteMethod> = (
|
||||
handler: RequestHandler<P, Q, B, Method>
|
||||
) => RequestHandlerEnhanced<P, Q, B, Method>;
|
||||
export type ContextEnhancer<
|
||||
P,
|
||||
Q,
|
||||
B,
|
||||
Method extends RouteMethod,
|
||||
Context extends RequestHandlerContext
|
||||
> = (handler: RequestHandler<P, Q, B, Context, Method>) => RequestHandlerEnhanced<P, Q, B, Method>;
|
||||
|
||||
function getRouteFullPath(routerPath: string, routePath: string) {
|
||||
// If router's path ends with slash and route's path starts with slash,
|
||||
|
@ -195,22 +202,23 @@ function validOptions(
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class Router implements IRouter {
|
||||
export class Router<Context extends RequestHandlerContext = RequestHandlerContext>
|
||||
implements IRouter<Context> {
|
||||
public routes: Array<Readonly<RouterRoute>> = [];
|
||||
public get: IRouter['get'];
|
||||
public post: IRouter['post'];
|
||||
public delete: IRouter['delete'];
|
||||
public put: IRouter['put'];
|
||||
public patch: IRouter['patch'];
|
||||
public get: IRouter<Context>['get'];
|
||||
public post: IRouter<Context>['post'];
|
||||
public delete: IRouter<Context>['delete'];
|
||||
public put: IRouter<Context>['put'];
|
||||
public patch: IRouter<Context>['patch'];
|
||||
|
||||
constructor(
|
||||
public readonly routerPath: string,
|
||||
private readonly log: Logger,
|
||||
private readonly enhanceWithContext: ContextEnhancer<any, any, any, any>
|
||||
private readonly enhanceWithContext: ContextEnhancer<any, any, any, any, any>
|
||||
) {
|
||||
const buildMethod = <Method extends RouteMethod>(method: Method) => <P, Q, B>(
|
||||
route: RouteConfig<P, Q, B, Method>,
|
||||
handler: RequestHandler<P, Q, B, Method>
|
||||
handler: RequestHandler<P, Q, B, Context, Method>
|
||||
) => {
|
||||
const routeSchemas = routeSchemasFromRouteConfig(route, method);
|
||||
|
||||
|
@ -300,7 +308,7 @@ type WithoutHeadArgument<T> = T extends (first: any, ...rest: infer Params) => i
|
|||
: never;
|
||||
|
||||
type RequestHandlerEnhanced<P, Q, B, Method extends RouteMethod> = WithoutHeadArgument<
|
||||
RequestHandler<P, Q, B, Method>
|
||||
RequestHandler<P, Q, B, RequestHandlerContext, Method>
|
||||
>;
|
||||
|
||||
/**
|
||||
|
@ -341,10 +349,11 @@ export type RequestHandler<
|
|||
P = unknown,
|
||||
Q = unknown,
|
||||
B = unknown,
|
||||
Context extends RequestHandlerContext = RequestHandlerContext,
|
||||
Method extends RouteMethod = any,
|
||||
ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory
|
||||
> = (
|
||||
context: RequestHandlerContext,
|
||||
context: Context,
|
||||
request: KibanaRequest<P, Q, B, Method>,
|
||||
response: ResponseFactory
|
||||
) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
|
@ -366,8 +375,9 @@ export type RequestHandlerWrapper = <
|
|||
P,
|
||||
Q,
|
||||
B,
|
||||
Context extends RequestHandlerContext = RequestHandlerContext,
|
||||
Method extends RouteMethod = any,
|
||||
ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory
|
||||
>(
|
||||
handler: RequestHandler<P, Q, B, Method, ResponseFactory>
|
||||
) => RequestHandler<P, Q, B, Method, ResponseFactory>;
|
||||
handler: RequestHandler<P, Q, B, Context, Method, ResponseFactory>
|
||||
) => RequestHandler<P, Q, B, Context, Method, ResponseFactory>;
|
||||
|
|
|
@ -21,13 +21,13 @@ import { OnPostAuthHandler } from './lifecycle/on_post_auth';
|
|||
import { OnPreResponseHandler } from './lifecycle/on_pre_response';
|
||||
import { IBasePath } from './base_path_service';
|
||||
import { ExternalUrlConfig } from '../external_url';
|
||||
import { PluginOpaqueId, RequestHandlerContext } from '..';
|
||||
import type { PluginOpaqueId, RequestHandlerContext } from '..';
|
||||
|
||||
/**
|
||||
* An object that handles registration of http request context providers.
|
||||
* @public
|
||||
*/
|
||||
export type RequestHandlerContextContainer = IContextContainer<RequestHandler<any, any, any>>;
|
||||
export type RequestHandlerContextContainer = IContextContainer<RequestHandler>;
|
||||
|
||||
/**
|
||||
* Context provider for request handler.
|
||||
|
@ -36,8 +36,9 @@ export type RequestHandlerContextContainer = IContextContainer<RequestHandler<an
|
|||
* @public
|
||||
*/
|
||||
export type RequestHandlerContextProvider<
|
||||
TContextName extends keyof RequestHandlerContext
|
||||
> = IContextProvider<RequestHandler<any, any, any>, TContextName>;
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
> = IContextProvider<Context, ContextName>;
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -230,14 +231,19 @@ export interface HttpServiceSetup {
|
|||
* ```
|
||||
* @public
|
||||
*/
|
||||
createRouter: () => IRouter;
|
||||
createRouter: <
|
||||
Context extends RequestHandlerContext = RequestHandlerContext
|
||||
>() => IRouter<Context>;
|
||||
|
||||
/**
|
||||
* Register a context provider for a route handler.
|
||||
* @example
|
||||
* ```ts
|
||||
* // my-plugin.ts
|
||||
* deps.http.registerRouteHandlerContext(
|
||||
* interface MyRequestHandlerContext extends RequestHandlerContext {
|
||||
* myApp: { search(id: string): Promise<Result> };
|
||||
* }
|
||||
* deps.http.registerRouteHandlerContext<MyRequestHandlerContext, 'myApp'>(
|
||||
* 'myApp',
|
||||
* (context, req) => {
|
||||
* async function search (id: string) {
|
||||
|
@ -248,6 +254,8 @@ export interface HttpServiceSetup {
|
|||
* );
|
||||
*
|
||||
* // my-route-handler.ts
|
||||
* import type { MyRequestHandlerContext } from './my-plugin.ts';
|
||||
* const router = createRouter<MyRequestHandlerContext>();
|
||||
* router.get({ path: '/', validate: false }, async (context, req, res) => {
|
||||
* const response = await context.myApp.search(...);
|
||||
* return res.ok(response);
|
||||
|
@ -255,9 +263,12 @@ export interface HttpServiceSetup {
|
|||
* ```
|
||||
* @public
|
||||
*/
|
||||
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(
|
||||
contextName: T,
|
||||
provider: RequestHandlerContextProvider<T>
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
) => RequestHandlerContextContainer;
|
||||
|
||||
/**
|
||||
|
@ -272,13 +283,19 @@ export interface InternalHttpServiceSetup
|
|||
auth: HttpServerSetup['auth'];
|
||||
server: HttpServerSetup['server'];
|
||||
externalUrl: ExternalUrlConfig;
|
||||
createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter;
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>(
|
||||
path: string,
|
||||
plugin?: PluginOpaqueId
|
||||
) => IRouter<Context>;
|
||||
registerStaticDir: (path: string, dirPath: string) => void;
|
||||
getAuthHeaders: GetAuthHeaders;
|
||||
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: T,
|
||||
provider: RequestHandlerContextProvider<T>
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
) => RequestHandlerContextContainer;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,12 +53,12 @@ export class HttpResourcesService implements CoreService<InternalHttpResourcesSe
|
|||
|
||||
private createRegistrar(deps: SetupDeps, router: IRouter): HttpResources {
|
||||
return {
|
||||
register: <P, Q, B>(
|
||||
register: <P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext>(
|
||||
route: RouteConfig<P, Q, B, 'get'>,
|
||||
handler: HttpResourcesRequestHandler<P, Q, B>
|
||||
handler: HttpResourcesRequestHandler<P, Q, B, Context>
|
||||
) => {
|
||||
return router.get<P, Q, B>(route, (context, request, response) => {
|
||||
return handler(context, request, {
|
||||
return handler(context as Context, request, {
|
||||
...response,
|
||||
...this.createResponseToolkit(deps, context, request, response),
|
||||
});
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
import type { RequestHandlerContext } from 'src/core/server';
|
||||
import type {
|
||||
IRouter,
|
||||
RouteConfig,
|
||||
IKibanaResponse,
|
||||
|
@ -72,13 +73,12 @@ export interface HttpResourcesServiceToolkit {
|
|||
* });
|
||||
* @public
|
||||
*/
|
||||
export type HttpResourcesRequestHandler<P = unknown, Q = unknown, B = unknown> = RequestHandler<
|
||||
P,
|
||||
Q,
|
||||
B,
|
||||
'get',
|
||||
KibanaResponseFactory & HttpResourcesServiceToolkit
|
||||
>;
|
||||
export type HttpResourcesRequestHandler<
|
||||
P = unknown,
|
||||
Q = unknown,
|
||||
B = unknown,
|
||||
Context extends RequestHandlerContext = RequestHandlerContext
|
||||
> = RequestHandler<P, Q, B, Context, 'get', KibanaResponseFactory & HttpResourcesServiceToolkit>;
|
||||
|
||||
/**
|
||||
* Allows to configure HTTP response parameters
|
||||
|
@ -98,8 +98,8 @@ export interface InternalHttpResourcesSetup {
|
|||
*/
|
||||
export interface HttpResources {
|
||||
/** To register a route handler executing passed function to form response. */
|
||||
register: <P, Q, B>(
|
||||
register: <P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext>(
|
||||
route: RouteConfig<P, Q, B, 'get'>,
|
||||
handler: HttpResourcesRequestHandler<P, Q, B>
|
||||
handler: HttpResourcesRequestHandler<P, Q, B, Context>
|
||||
) => void;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { first, map, publishReplay, tap } from 'rxjs/operators';
|
|||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { PathConfigType } from '@kbn/utils';
|
||||
|
||||
import type { RequestHandlerContext } from 'src/core/server';
|
||||
// @ts-expect-error legacy config class
|
||||
import { Config as LegacyConfigClass } from '../../../legacy/server/config';
|
||||
import { CoreService } from '../../types';
|
||||
|
@ -18,7 +19,14 @@ import { Config } from '../config';
|
|||
import { CoreContext } from '../core_context';
|
||||
import { CspConfigType, config as cspConfig } from '../csp';
|
||||
import { DevConfig, DevConfigType, config as devConfig } from '../dev';
|
||||
import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http';
|
||||
import {
|
||||
BasePathProxyServer,
|
||||
HttpConfig,
|
||||
HttpConfigType,
|
||||
config as httpConfig,
|
||||
IRouter,
|
||||
RequestHandlerContextProvider,
|
||||
} from '../http';
|
||||
import { Logger } from '../logging';
|
||||
import { LegacyServiceSetupDeps, LegacyServiceStartDeps, LegacyConfig, LegacyVars } from './types';
|
||||
import { ExternalUrlConfigType, config as externalUrlConfig } from '../external_url';
|
||||
|
@ -225,11 +233,15 @@ export class LegacyService implements CoreService {
|
|||
},
|
||||
http: {
|
||||
createCookieSessionStorageFactory: setupDeps.core.http.createCookieSessionStorageFactory,
|
||||
registerRouteHandlerContext: setupDeps.core.http.registerRouteHandlerContext.bind(
|
||||
null,
|
||||
this.legacyId
|
||||
),
|
||||
createRouter: () => router,
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
) => setupDeps.core.http.registerRouteHandlerContext(this.legacyId, contextName, provider),
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>() =>
|
||||
router as IRouter<Context>,
|
||||
resources: setupDeps.core.httpResources.createRegistrar(router),
|
||||
registerOnPreRouting: setupDeps.core.http.registerOnPreRouting,
|
||||
registerOnPreAuth: setupDeps.core.http.registerOnPreAuth,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { map, shareReplay } from 'rxjs/operators';
|
|||
import { combineLatest } from 'rxjs';
|
||||
import { PathConfigType, config as pathConfig } from '@kbn/utils';
|
||||
import { pick, deepFreeze } from '@kbn/std';
|
||||
import type { RequestHandlerContext } from 'src/core/server';
|
||||
import { CoreContext } from '../core_context';
|
||||
import { PluginWrapper } from './plugin';
|
||||
import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service';
|
||||
|
@ -24,6 +25,7 @@ import {
|
|||
ElasticsearchConfigType,
|
||||
config as elasticsearchConfig,
|
||||
} from '../elasticsearch/elasticsearch_config';
|
||||
import { IRouter, RequestHandlerContextProvider } from '../http';
|
||||
import { SavedObjectsConfigType, savedObjectsConfig } from '../saved_objects/saved_objects_config';
|
||||
import { CoreSetup, CoreStart } from '..';
|
||||
|
||||
|
@ -149,11 +151,15 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
|
|||
},
|
||||
http: {
|
||||
createCookieSessionStorageFactory: deps.http.createCookieSessionStorageFactory,
|
||||
registerRouteHandlerContext: deps.http.registerRouteHandlerContext.bind(
|
||||
null,
|
||||
plugin.opaqueId
|
||||
),
|
||||
createRouter: () => router,
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
>(
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
) => deps.http.registerRouteHandlerContext(plugin.opaqueId, contextName, provider),
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>() =>
|
||||
router as IRouter<Context>,
|
||||
resources: deps.httpResources.createRegistrar(router),
|
||||
registerOnPreRouting: deps.http.registerOnPreRouting,
|
||||
registerOnPreAuth: deps.http.registerOnPreAuth,
|
||||
|
|
|
@ -132,6 +132,7 @@ import { ReindexParams } from 'elasticsearch';
|
|||
import { ReindexRethrottleParams } from 'elasticsearch';
|
||||
import { RenderSearchTemplateParams } from 'elasticsearch';
|
||||
import { Request } from '@hapi/hapi';
|
||||
import { RequestHandlerContext as RequestHandlerContext_2 } from 'src/core/server';
|
||||
import { ResponseObject } from '@hapi/hapi';
|
||||
import { ResponseToolkit } from '@hapi/hapi';
|
||||
import { SchemaTypeError } from '@kbn/config-schema';
|
||||
|
@ -968,7 +969,7 @@ export interface HttpAuth {
|
|||
|
||||
// @public
|
||||
export interface HttpResources {
|
||||
register: <P, Q, B>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B>) => void;
|
||||
register: <P, Q, B, Context extends RequestHandlerContext_2 = RequestHandlerContext_2>(route: RouteConfig<P, Q, B, 'get'>, handler: HttpResourcesRequestHandler<P, Q, B, Context>) => void;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
@ -977,7 +978,7 @@ export interface HttpResourcesRenderOptions {
|
|||
}
|
||||
|
||||
// @public
|
||||
export type HttpResourcesRequestHandler<P = unknown, Q = unknown, B = unknown> = RequestHandler<P, Q, B, 'get', KibanaResponseFactory & HttpResourcesServiceToolkit>;
|
||||
export type HttpResourcesRequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext_2 = RequestHandlerContext_2> = RequestHandler<P, Q, B, Context, 'get', KibanaResponseFactory & HttpResourcesServiceToolkit>;
|
||||
|
||||
// @public
|
||||
export type HttpResourcesResponseOptions = HttpResponseOptions;
|
||||
|
@ -1013,7 +1014,7 @@ export interface HttpServiceSetup {
|
|||
auth: HttpAuth;
|
||||
basePath: IBasePath;
|
||||
createCookieSessionStorageFactory: <T>(cookieOptions: SessionStorageCookieOptions<T>) => Promise<SessionStorageFactory<T>>;
|
||||
createRouter: () => IRouter;
|
||||
createRouter: <Context extends RequestHandlerContext = RequestHandlerContext>() => IRouter<Context>;
|
||||
csp: ICspConfig;
|
||||
getServerInfo: () => HttpServerInfo;
|
||||
registerAuth: (handler: AuthenticationHandler) => void;
|
||||
|
@ -1021,7 +1022,7 @@ export interface HttpServiceSetup {
|
|||
registerOnPreAuth: (handler: OnPreAuthHandler) => void;
|
||||
registerOnPreResponse: (handler: OnPreResponseHandler) => void;
|
||||
registerOnPreRouting: (handler: OnPreRoutingHandler) => void;
|
||||
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(contextName: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer;
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -1047,15 +1048,13 @@ export interface IClusterClient {
|
|||
}
|
||||
|
||||
// @public
|
||||
export interface IContextContainer<THandler extends HandlerFunction<any>> {
|
||||
export interface IContextContainer<THandler extends RequestHandler> {
|
||||
createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters<THandler>) => ShallowPromise<ReturnType<THandler>>;
|
||||
registerContext<TContextName extends keyof HandlerContextType<THandler>>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider<THandler, TContextName>): this;
|
||||
registerContext<Context extends RequestHandlerContext, ContextName extends keyof Context>(pluginOpaqueId: PluginOpaqueId, contextName: ContextName, provider: IContextProvider<Context, ContextName>): this;
|
||||
}
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "PartialExceptFor" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @public
|
||||
export type IContextProvider<THandler extends HandlerFunction<any>, TContextName extends keyof HandlerContextType<THandler>> = (context: PartialExceptFor<HandlerContextType<THandler>, 'core'>, ...rest: HandlerParameters<THandler>) => Promise<HandlerContextType<THandler>[TContextName]> | HandlerContextType<THandler>[TContextName];
|
||||
export type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
|
||||
// @public
|
||||
export interface ICspConfig {
|
||||
|
@ -1140,17 +1139,17 @@ export interface IRenderOptions {
|
|||
}
|
||||
|
||||
// @public
|
||||
export interface IRouter {
|
||||
delete: RouteRegistrar<'delete'>;
|
||||
get: RouteRegistrar<'get'>;
|
||||
export interface IRouter<Context extends RequestHandlerContext = RequestHandlerContext> {
|
||||
delete: RouteRegistrar<'delete', Context>;
|
||||
get: RouteRegistrar<'get', Context>;
|
||||
// Warning: (ae-forgotten-export) The symbol "RouterRoute" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @internal
|
||||
getRoutes: () => RouterRoute[];
|
||||
handleLegacyErrors: RequestHandlerWrapper;
|
||||
patch: RouteRegistrar<'patch'>;
|
||||
post: RouteRegistrar<'post'>;
|
||||
put: RouteRegistrar<'put'>;
|
||||
patch: RouteRegistrar<'patch', Context>;
|
||||
post: RouteRegistrar<'post', Context>;
|
||||
put: RouteRegistrar<'put', Context>;
|
||||
routerPath: string;
|
||||
}
|
||||
|
||||
|
@ -1549,7 +1548,7 @@ export type LegacyElasticsearchClientConfig = Pick<ConfigOptions, 'keepAlive' |
|
|||
// @public
|
||||
export interface LegacyElasticsearchError extends Boom.Boom {
|
||||
// (undocumented)
|
||||
[code]?: string;
|
||||
[code_2]?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
@ -1891,7 +1890,7 @@ export type RedirectResponseOptions = HttpResponseOptions & {
|
|||
};
|
||||
|
||||
// @public
|
||||
export type RequestHandler<P = unknown, Q = unknown, B = unknown, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: RequestHandlerContext, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
export type RequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: Context, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
|
||||
// @public
|
||||
export interface RequestHandlerContext {
|
||||
|
@ -1916,13 +1915,13 @@ export interface RequestHandlerContext {
|
|||
}
|
||||
|
||||
// @public
|
||||
export type RequestHandlerContextContainer = IContextContainer<RequestHandler<any, any, any>>;
|
||||
export type RequestHandlerContextContainer = IContextContainer<RequestHandler>;
|
||||
|
||||
// @public
|
||||
export type RequestHandlerContextProvider<TContextName extends keyof RequestHandlerContext> = IContextProvider<RequestHandler<any, any, any>, TContextName>;
|
||||
export type RequestHandlerContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = IContextProvider<Context, ContextName>;
|
||||
|
||||
// @public
|
||||
export type RequestHandlerWrapper = <P, Q, B, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory>(handler: RequestHandler<P, Q, B, Method, ResponseFactory>) => RequestHandler<P, Q, B, Method, ResponseFactory>;
|
||||
export type RequestHandlerWrapper = <P, Q, B, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory>(handler: RequestHandler<P, Q, B, Context, Method, ResponseFactory>) => RequestHandler<P, Q, B, Context, Method, ResponseFactory>;
|
||||
|
||||
// @public
|
||||
export interface ResolveCapabilitiesOptions {
|
||||
|
@ -1975,7 +1974,7 @@ export type RouteContentType = 'application/json' | 'application/*+json' | 'appl
|
|||
export type RouteMethod = SafeRouteMethod | DestructiveRouteMethod;
|
||||
|
||||
// @public
|
||||
export type RouteRegistrar<Method extends RouteMethod> = <P, Q, B>(route: RouteConfig<P, Q, B, Method>, handler: RequestHandler<P, Q, B, Method>) => void;
|
||||
export type RouteRegistrar<Method extends RouteMethod, Context extends RequestHandlerContext = RequestHandlerContext> = <P, Q, B>(route: RouteConfig<P, Q, B, Method>, handler: RequestHandler<P, Q, B, Context, Method>) => void;
|
||||
|
||||
// @public
|
||||
export class RouteValidationError extends SchemaTypeError {
|
||||
|
|
|
@ -294,7 +294,7 @@ export class Server {
|
|||
coreSetup.http.registerRouteHandlerContext(
|
||||
coreId,
|
||||
'core',
|
||||
async (context, req, res): Promise<RequestHandlerContext['core']> => {
|
||||
(context, req, res): RequestHandlerContext['core'] => {
|
||||
return new CoreRouteHandlerContext(this.coreStart!, req);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* and the Server Side Public License, v 1; you may not use this file except in
|
||||
* compliance with, at your election, the Elastic License or the Server Side
|
||||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ContextContainer } from './context';
|
||||
import { PluginOpaqueId } from '../server';
|
||||
|
||||
const pluginA = Symbol('pluginA');
|
||||
const pluginB = Symbol('pluginB');
|
||||
const pluginC = Symbol('pluginC');
|
||||
const pluginD = Symbol('pluginD');
|
||||
const plugins: ReadonlyMap<PluginOpaqueId, PluginOpaqueId[]> = new Map([
|
||||
[pluginA, []],
|
||||
[pluginB, [pluginA]],
|
||||
[pluginC, [pluginA, pluginB]],
|
||||
[pluginD, []],
|
||||
]);
|
||||
|
||||
interface MyContext {
|
||||
core1: string;
|
||||
core2: number;
|
||||
ctxFromA: string;
|
||||
ctxFromB: number;
|
||||
ctxFromC: boolean;
|
||||
ctxFromD: object;
|
||||
}
|
||||
|
||||
const coreId = Symbol();
|
||||
|
||||
describe('ContextContainer', () => {
|
||||
it('does not allow the same context to be registered twice', () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(plugins, coreId);
|
||||
contextContainer.registerContext(coreId, 'ctxFromA', () => 'aString');
|
||||
|
||||
expect(() =>
|
||||
contextContainer.registerContext(coreId, 'ctxFromA', () => 'aString')
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Context provider for ctxFromA has already been registered."`
|
||||
);
|
||||
});
|
||||
|
||||
describe('registerContext', () => {
|
||||
it('throws error if called with an unknown symbol', async () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
await expect(() =>
|
||||
contextContainer.registerContext(Symbol('unknown'), 'ctxFromA', jest.fn())
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Cannot register context for unknown plugin: Symbol(unknown)"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('context building', () => {
|
||||
it('resolves dependencies', async () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
expect.assertions(8);
|
||||
contextContainer.registerContext(coreId, 'core1', (context) => {
|
||||
expect(context).toEqual({});
|
||||
return 'core';
|
||||
});
|
||||
|
||||
contextContainer.registerContext(pluginA, 'ctxFromA', (context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return 'aString';
|
||||
});
|
||||
contextContainer.registerContext(pluginB, 'ctxFromB', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', ctxFromA: 'aString' });
|
||||
return 299;
|
||||
});
|
||||
contextContainer.registerContext(pluginC, 'ctxFromC', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', ctxFromA: 'aString', ctxFromB: 299 });
|
||||
return false;
|
||||
});
|
||||
contextContainer.registerContext(pluginD, 'ctxFromD', (context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return {};
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn<string, []>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const rawHandler2 = jest.fn<string, []>(() => 'handler2');
|
||||
const handler2 = contextContainer.createHandler(pluginD, rawHandler2);
|
||||
|
||||
await handler1();
|
||||
await handler2();
|
||||
|
||||
// Should have context from pluginC, its deps, and core
|
||||
expect(rawHandler1).toHaveBeenCalledWith({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
ctxFromC: false,
|
||||
});
|
||||
|
||||
// Should have context from pluginD, and core
|
||||
expect(rawHandler2).toHaveBeenCalledWith({
|
||||
core1: 'core',
|
||||
ctxFromD: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes all core context to all providers regardless of registration order', async () => {
|
||||
expect.assertions(4);
|
||||
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
contextContainer
|
||||
.registerContext(pluginA, 'ctxFromA', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', core2: 101 });
|
||||
return `aString ${context.core1} ${context.core2}`;
|
||||
})
|
||||
.registerContext(coreId, 'core1', () => 'core')
|
||||
.registerContext(coreId, 'core2', () => 101)
|
||||
.registerContext(pluginB, 'ctxFromB', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', core2: 101, ctxFromA: 'aString core 101' });
|
||||
return 277;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn<string, []>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginB, rawHandler1);
|
||||
|
||||
expect(await handler1()).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
ctxFromB: 277,
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes all core context to core providers', async () => {
|
||||
expect.assertions(4);
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
|
||||
contextContainer
|
||||
.registerContext(coreId, 'core1', (context) => {
|
||||
expect(context).toEqual({});
|
||||
return 'core';
|
||||
})
|
||||
.registerContext(coreId, 'core2', (context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
return 101;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn<string, []>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
expect(await handler1()).toEqual('handler1');
|
||||
|
||||
// If no context is registered for pluginA, only core contexts should be exposed
|
||||
expect(rawHandler1).toHaveBeenCalledWith({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not expose plugin contexts to core handler', async () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
|
||||
contextContainer
|
||||
.registerContext(coreId, 'core1', (context) => 'core')
|
||||
.registerContext(pluginA, 'ctxFromA', (context) => 'aString');
|
||||
|
||||
const rawHandler1 = jest.fn<string, []>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(coreId, rawHandler1);
|
||||
|
||||
expect(await handler1()).toEqual('handler1');
|
||||
// pluginA context should not be present in a core handler
|
||||
expect(rawHandler1).toHaveBeenCalledWith({
|
||||
core1: 'core',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes additional arguments to providers', async () => {
|
||||
expect.assertions(6);
|
||||
const contextContainer = new ContextContainer<
|
||||
(context: MyContext, arg1: string, arg2: number) => string
|
||||
>(plugins, coreId);
|
||||
|
||||
contextContainer.registerContext(coreId, 'core1', (context, str, num) => {
|
||||
expect(str).toEqual('passed string');
|
||||
expect(num).toEqual(77);
|
||||
return `core ${str}`;
|
||||
});
|
||||
|
||||
contextContainer.registerContext(pluginD, 'ctxFromD', (context, str, num) => {
|
||||
expect(str).toEqual('passed string');
|
||||
expect(num).toEqual(77);
|
||||
return {
|
||||
num: 77,
|
||||
};
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn<string, [MyContext, string, number]>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginD, rawHandler1);
|
||||
|
||||
expect(await handler1('passed string', 77)).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core passed string',
|
||||
ctxFromD: {
|
||||
num: 77,
|
||||
},
|
||||
},
|
||||
'passed string',
|
||||
77
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createHandler', () => {
|
||||
it('throws error if called with an unknown symbol', async () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
await expect(() =>
|
||||
contextContainer.createHandler(Symbol('unknown'), jest.fn())
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Cannot create handler for unknown plugin: Symbol(unknown)"`
|
||||
);
|
||||
});
|
||||
|
||||
it('returns value from original handler', async () => {
|
||||
const contextContainer = new ContextContainer<(context: MyContext) => string>(
|
||||
plugins,
|
||||
coreId
|
||||
);
|
||||
const rawHandler1 = jest.fn(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
expect(await handler1()).toEqual('handler1');
|
||||
});
|
||||
|
||||
it('passes additional arguments to handlers', async () => {
|
||||
const contextContainer = new ContextContainer<
|
||||
(context: MyContext, arg1: string, arg2: number) => string
|
||||
>(plugins, coreId);
|
||||
|
||||
const rawHandler1 = jest.fn<string, [MyContext, string, number]>(() => 'handler1');
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
await handler1('passed string', 77);
|
||||
expect(rawHandler1).toHaveBeenCalledWith({}, 'passed string', 77);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,12 +6,4 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
export {
|
||||
ContextContainer,
|
||||
HandlerContextType,
|
||||
HandlerFunction,
|
||||
HandlerParameters,
|
||||
IContextContainer,
|
||||
IContextProvider,
|
||||
} from './context';
|
||||
export { DEFAULT_APP_CATEGORIES } from './default_app_categories';
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
import type {
|
||||
CoreStart,
|
||||
PluginInitializerContext,
|
||||
CoreSetup,
|
||||
|
@ -15,6 +15,7 @@ import {
|
|||
KibanaRequest,
|
||||
RouteMethod,
|
||||
RequestHandler,
|
||||
RequestHandlerContext,
|
||||
} from 'src/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { Subject } from 'rxjs';
|
||||
|
@ -77,9 +78,16 @@ export interface BfetchServerSetup {
|
|||
*
|
||||
* @param streamHandler
|
||||
*/
|
||||
createStreamingRequestHandler: <Response, P, Q, B, Method extends RouteMethod = any>(
|
||||
createStreamingRequestHandler: <
|
||||
Response,
|
||||
P,
|
||||
Q,
|
||||
B,
|
||||
Context extends RequestHandlerContext = RequestHandlerContext,
|
||||
Method extends RouteMethod = any
|
||||
>(
|
||||
streamHandler: StreamingRequestHandler<Response, P, Q, B, Method>
|
||||
) => RequestHandler<P, Q, B, Method>;
|
||||
) => RequestHandler<P, Q, B, Context, Method>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
|
|
|
@ -2388,7 +2388,7 @@ export class SearchSource {
|
|||
removeField<K extends keyof SearchSourceFields>(field: K): this;
|
||||
serialize(): {
|
||||
searchSourceJSON: string;
|
||||
references: import("src/core/server").SavedObjectReference[];
|
||||
references: import("../../../../../core/types").SavedObjectReference[];
|
||||
};
|
||||
setField<K extends keyof SearchSourceFields>(field: K, value: SearchSourceFields[K]): this;
|
||||
setFields(newFields: SearchSourceFields): this;
|
||||
|
|
|
@ -235,6 +235,8 @@ export {
|
|||
SearchUsage,
|
||||
SessionService,
|
||||
ISessionService,
|
||||
DataApiRequestHandlerContext,
|
||||
DataRequestHandlerContext,
|
||||
} from './search';
|
||||
|
||||
// Search namespace
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { RequestHandler, RouteMethod } from 'src/core/server';
|
||||
import type { RequestHandler, RouteMethod, RequestHandlerContext } from 'src/core/server';
|
||||
import { ErrorIndexPatternNotFound } from '../../error';
|
||||
|
||||
interface ErrorResponseBody {
|
||||
|
@ -29,9 +29,15 @@ interface ErrorWithData {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
export const handleErrors = <P, Q, B, Method extends RouteMethod>(
|
||||
handler: RequestHandler<P, Q, B, Method>
|
||||
): RequestHandler<P, Q, B, Method> => async (context, request, response) => {
|
||||
export const handleErrors = <
|
||||
P,
|
||||
Q,
|
||||
B,
|
||||
Context extends RequestHandlerContext,
|
||||
Method extends RouteMethod
|
||||
>(
|
||||
handler: RequestHandler<P, Q, B, Context, Method>
|
||||
): RequestHandler<P, Q, B, Context, Method> => async (context, request, response) => {
|
||||
try {
|
||||
return await handler(context, request, response);
|
||||
} catch (error) {
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { IRouter } from 'src/core/server';
|
||||
import { SearchRouteDependencies } from '../search_service';
|
||||
|
||||
import { getCallMsearch } from './call_msearch';
|
||||
import { reportServerError } from '../../../../kibana_utils/server';
|
||||
|
||||
import type { DataPluginRouter } from '../types';
|
||||
/**
|
||||
* The msearch route takes in an array of searches, each consisting of header
|
||||
* and body json, and reformts them into a single request for the _msearch API.
|
||||
|
@ -27,7 +26,10 @@ import { reportServerError } from '../../../../kibana_utils/server';
|
|||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependencies): void {
|
||||
export function registerMsearchRoute(
|
||||
router: DataPluginRouter,
|
||||
deps: SearchRouteDependencies
|
||||
): void {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/_msearch',
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
import { first } from 'rxjs/operators';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { IRouter } from 'src/core/server';
|
||||
import { getRequestAbortedSignal } from '../../lib';
|
||||
import { shimHitsTotal } from './shim_hits_total';
|
||||
import { reportServerError } from '../../../../kibana_utils/server';
|
||||
import type { DataPluginRouter } from '../types';
|
||||
|
||||
export function registerSearchRoute(router: IRouter): void {
|
||||
export function registerSearchRoute(router: DataPluginRouter): void {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/search/{strategy}/{id?}',
|
||||
|
|
|
@ -21,12 +21,13 @@ import {
|
|||
import { catchError, first, map } from 'rxjs/operators';
|
||||
import { BfetchServerSetup } from 'src/plugins/bfetch/server';
|
||||
import { ExpressionsServerSetup } from 'src/plugins/expressions/server';
|
||||
import {
|
||||
import type {
|
||||
ISearchSetup,
|
||||
ISearchStart,
|
||||
ISearchStrategy,
|
||||
SearchEnhancements,
|
||||
SearchStrategyDependencies,
|
||||
DataRequestHandlerContext,
|
||||
} from './types';
|
||||
|
||||
import { AggsService } from './aggs';
|
||||
|
@ -64,12 +65,6 @@ import { ConfigSchema } from '../../config';
|
|||
import { SessionService, IScopedSessionService, ISessionService } from './session';
|
||||
import { KbnServerError } from '../../../kibana_utils/server';
|
||||
|
||||
declare module 'src/core/server' {
|
||||
interface RequestHandlerContext {
|
||||
search?: ISearchClient & { session: IScopedSessionService };
|
||||
}
|
||||
}
|
||||
|
||||
type StrategyMap = Record<string, ISearchStrategy<any, any>>;
|
||||
|
||||
/** @internal */
|
||||
|
@ -112,7 +107,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
): ISearchSetup {
|
||||
const usage = usageCollection ? usageProvider(core) : undefined;
|
||||
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<DataRequestHandlerContext>();
|
||||
const routeDependencies = {
|
||||
getStartServices: core.getStartServices,
|
||||
globalConfig$: this.initializerContext.config.legacy.globalConfig$,
|
||||
|
@ -124,11 +119,14 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
this.coreStart = coreStart;
|
||||
});
|
||||
|
||||
core.http.registerRouteHandlerContext('search', async (context, request) => {
|
||||
const search = this.asScopedProvider(this.coreStart!)(request);
|
||||
const session = this.sessionService.asScopedProvider(this.coreStart!)(request);
|
||||
return { ...search, session };
|
||||
});
|
||||
core.http.registerRouteHandlerContext<DataRequestHandlerContext, 'search'>(
|
||||
'search',
|
||||
async (context, request) => {
|
||||
const search = this.asScopedProvider(this.coreStart!)(request);
|
||||
const session = this.sessionService.asScopedProvider(this.coreStart!)(request);
|
||||
return { ...search, session };
|
||||
}
|
||||
);
|
||||
|
||||
this.registerSearchStrategy(
|
||||
ES_SEARCH_STRATEGY,
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
import type {
|
||||
IRouter,
|
||||
IScopedClusterClient,
|
||||
IUiSettingsClient,
|
||||
SavedObjectsClientContract,
|
||||
KibanaRequest,
|
||||
RequestHandlerContext,
|
||||
} from 'src/core/server';
|
||||
import {
|
||||
ISearchOptions,
|
||||
|
@ -23,7 +25,7 @@ import {
|
|||
import { AggsSetup, AggsStart } from './aggs';
|
||||
import { SearchUsage } from './collectors';
|
||||
import { IEsSearchRequest, IEsSearchResponse } from './es_search';
|
||||
import { ISessionService } from './session';
|
||||
import { ISessionService, IScopedSessionService } from './session';
|
||||
|
||||
export interface SearchEnhancements {
|
||||
defaultStrategy: string;
|
||||
|
@ -101,3 +103,16 @@ export interface ISearchStart<
|
|||
asScoped: (request: KibanaRequest) => Promise<ISearchStartSearchSource>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DataApiRequestHandlerContext extends ISearchClient {
|
||||
session: IScopedSessionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface DataRequestHandlerContext extends RequestHandlerContext {
|
||||
search: DataApiRequestHandlerContext;
|
||||
}
|
||||
|
||||
export type DataPluginRouter = IRouter<DataRequestHandlerContext>;
|
||||
|
|
|
@ -53,6 +53,7 @@ import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core
|
|||
import { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { RecursiveReadonly } from '@kbn/utility-types';
|
||||
import { RequestAdapter } from 'src/plugins/inspector/common';
|
||||
import { RequestHandlerContext } from 'src/core/server';
|
||||
import { RequestStatistics } from 'src/plugins/inspector/common';
|
||||
import { SavedObject } from 'src/core/server';
|
||||
import { SavedObjectsClientContract } from 'src/core/server';
|
||||
|
@ -304,6 +305,23 @@ export const castEsToKbnFieldTypeName: (esType: ES_FIELD_TYPES | string) => KBN_
|
|||
// @public (undocumented)
|
||||
export const config: PluginConfigDescriptor<ConfigSchema>;
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "ISearchClient" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "DataApiRequestHandlerContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface DataApiRequestHandlerContext extends ISearchClient {
|
||||
// Warning: (ae-forgotten-export) The symbol "IScopedSessionService" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
session: IScopedSessionService;
|
||||
}
|
||||
|
||||
// @internal (undocumented)
|
||||
export interface DataRequestHandlerContext extends RequestHandlerContext {
|
||||
// (undocumented)
|
||||
search: DataApiRequestHandlerContext;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export enum ES_FIELD_TYPES {
|
||||
// (undocumented)
|
||||
|
@ -937,8 +955,6 @@ export interface ISearchStart<SearchStrategyRequest extends IKibanaSearchRequest
|
|||
//
|
||||
// (undocumented)
|
||||
aggs: AggsStart;
|
||||
// Warning: (ae-forgotten-export) The symbol "ISearchClient" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
asScoped: (request: KibanaRequest_2) => ISearchClient;
|
||||
getSearchStrategy: (name?: string) => ISearchStrategy<SearchStrategyRequest, SearchStrategyResponse>;
|
||||
|
@ -964,8 +980,6 @@ export interface ISearchStrategy<SearchStrategyRequest extends IKibanaSearchRequ
|
|||
//
|
||||
// @public (undocumented)
|
||||
export interface ISessionService {
|
||||
// Warning: (ae-forgotten-export) The symbol "IScopedSessionService" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
asScopedProvider: (core: CoreStart) => (request: KibanaRequest) => IScopedSessionService;
|
||||
}
|
||||
|
@ -1129,10 +1143,10 @@ export class Plugin implements Plugin_2<PluginSetup, PluginStart, DataPluginSetu
|
|||
// (undocumented)
|
||||
start(core: CoreStart_2): {
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("src/core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
indexPatterns: {
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("src/core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("src/core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
indexPatternsServiceFactory: (savedObjectsClient: Pick<import("../../../core/server").SavedObjectsClient, "update" | "find" | "get" | "delete" | "errors" | "create" | "bulkCreate" | "checkConflicts" | "bulkGet" | "addToNamespaces" | "deleteFromNamespaces" | "bulkUpdate" | "removeReferencesTo">, elasticsearchClient: import("../../../core/server").ElasticsearchClient) => Promise<import("../public").IndexPatternsService>;
|
||||
};
|
||||
search: ISearchStart<import("./search").IEsSearchRequest, import("./search").IEsSearchResponse<any>>;
|
||||
};
|
||||
|
@ -1419,23 +1433,23 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
|
|||
// src/plugins/data/server/index.ts:100:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:126:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:126:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:243:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:253:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:254:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:255:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:259:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:260:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:264:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:267:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:268:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:255:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:256:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:257:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:261:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:262:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:266:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:269:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:270:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index_patterns/index_patterns_service.ts:59:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/plugin.ts:79:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/search/types.ts:101:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/search/types.ts:103:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('sendTelemetryOptInStatus', () => {
|
|||
expect(fetch).toBeCalledTimes(1);
|
||||
expect(fetch).toBeCalledWith(mockConfig.optInStatusUrl, {
|
||||
method: 'post',
|
||||
body: mockOptInStatus,
|
||||
body: '["mock_opt_in_hashed_value"]',
|
||||
headers: { 'X-Elastic-Stack-Version': mockConfig.currentKibanaVersion },
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
import { IRouter } from 'kibana/server';
|
||||
|
@ -35,7 +34,7 @@ export async function sendTelemetryOptInStatus(
|
|||
|
||||
await fetch(optInStatusUrl, {
|
||||
method: 'post',
|
||||
body: optInStatus,
|
||||
body: JSON.stringify(optInStatus),
|
||||
headers: { 'X-Elastic-Stack-Version': currentKibanaVersion },
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,8 +11,12 @@ import { first } from 'rxjs/operators';
|
|||
import { TypeOf, schema } from '@kbn/config-schema';
|
||||
import { RecursiveReadonly } from '@kbn/utility-types';
|
||||
import { deepFreeze } from '@kbn/std';
|
||||
import type { RequestHandlerContext } from 'src/core/server';
|
||||
|
||||
import { PluginStart } from '../../../../src/plugins/data/server';
|
||||
import type {
|
||||
PluginStart,
|
||||
DataApiRequestHandlerContext,
|
||||
} from '../../../../src/plugins/data/server';
|
||||
import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server';
|
||||
import { configSchema } from '../config';
|
||||
import loadFunctions from './lib/load_functions';
|
||||
|
@ -67,7 +71,9 @@ export class Plugin {
|
|||
|
||||
const logger = this.initializerContext.logger.get('timelion');
|
||||
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<
|
||||
RequestHandlerContext & { search: DataApiRequestHandlerContext }
|
||||
>();
|
||||
|
||||
const deps = {
|
||||
configManager,
|
||||
|
@ -79,7 +85,7 @@ export class Plugin {
|
|||
|
||||
functionsRoute(router, deps);
|
||||
runRoute(router, deps);
|
||||
validateEsRoute(router, core);
|
||||
validateEsRoute(router);
|
||||
|
||||
core.uiSettings.register({
|
||||
'timelion:es.timefield': {
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { IRouter, CoreSetup } from 'kibana/server';
|
||||
import { IRouter, RequestHandlerContext } from 'kibana/server';
|
||||
import type { DataApiRequestHandlerContext } from '../../../data/server';
|
||||
|
||||
export function validateEsRoute(router: IRouter, core: CoreSetup) {
|
||||
export function validateEsRoute(
|
||||
router: IRouter<RequestHandlerContext & { search: DataApiRequestHandlerContext }>
|
||||
) {
|
||||
router.get(
|
||||
{
|
||||
path: '/api/timelion/validate/es',
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
|
||||
import { uniqBy } from 'lodash';
|
||||
import { first, map } from 'rxjs/operators';
|
||||
import { KibanaRequest, RequestHandlerContext } from 'kibana/server';
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
|
||||
import { Framework } from '../plugin';
|
||||
import { IndexPatternsFetcher } from '../../../data/server';
|
||||
import { ReqFacade } from './search_strategies/strategies/abstract_search_strategy';
|
||||
import { VisTypeTimeseriesRequestHandlerContext } from '../types';
|
||||
|
||||
export async function getFields(
|
||||
requestContext: RequestHandlerContext,
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
request: KibanaRequest,
|
||||
framework: Framework,
|
||||
indexPatternString: string
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { FakeRequest, RequestHandlerContext } from 'kibana/server';
|
||||
import { FakeRequest } from 'kibana/server';
|
||||
import _ from 'lodash';
|
||||
import { first, map } from 'rxjs/operators';
|
||||
|
||||
|
@ -15,6 +15,7 @@ import { getPanelData } from './vis_data/get_panel_data';
|
|||
import { Framework } from '../plugin';
|
||||
import { ReqFacade } from './search_strategies/strategies/abstract_search_strategy';
|
||||
import { TimeseriesVisData } from '../../common/types';
|
||||
import type { VisTypeTimeseriesRequestHandlerContext } from '../types';
|
||||
|
||||
export interface GetVisDataOptions {
|
||||
timerange: {
|
||||
|
@ -30,13 +31,13 @@ export interface GetVisDataOptions {
|
|||
}
|
||||
|
||||
export type GetVisData = (
|
||||
requestContext: RequestHandlerContext,
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
options: GetVisDataOptions,
|
||||
framework: Framework
|
||||
) => Promise<TimeseriesVisData>;
|
||||
|
||||
export function getVisData(
|
||||
requestContext: RequestHandlerContext,
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
request: FakeRequest & { body: GetVisDataOptions },
|
||||
framework: Framework
|
||||
): Promise<TimeseriesVisData> {
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import type {
|
||||
RequestHandlerContext,
|
||||
FakeRequest,
|
||||
IUiSettingsClient,
|
||||
SavedObjectsClientContract,
|
||||
} from 'kibana/server';
|
||||
import type { FakeRequest, IUiSettingsClient, SavedObjectsClientContract } from 'kibana/server';
|
||||
|
||||
import type { Framework } from '../../../plugin';
|
||||
import type { IndexPatternsFetcher, IFieldType } from '../../../../../data/server';
|
||||
|
@ -19,6 +14,7 @@ import type { VisPayload } from '../../../../common/types';
|
|||
import type { IndexPatternsService } from '../../../../../data/common';
|
||||
import { indexPatterns } from '../../../../../data/server';
|
||||
import { SanitizedFieldType } from '../../../../common/types';
|
||||
import type { VisTypeTimeseriesRequestHandlerContext } from '../../../types';
|
||||
|
||||
/**
|
||||
* ReqFacade is a regular KibanaRequest object extended with additional service
|
||||
|
@ -27,7 +23,7 @@ import { SanitizedFieldType } from '../../../../common/types';
|
|||
* This will be replaced by standard KibanaRequest and RequestContext objects in a later version.
|
||||
*/
|
||||
export interface ReqFacade<T = unknown> extends FakeRequest {
|
||||
requestContext: RequestHandlerContext;
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext;
|
||||
framework: Framework;
|
||||
payload: T;
|
||||
pre: {
|
||||
|
@ -58,8 +54,8 @@ export abstract class AbstractSearchStrategy {
|
|||
|
||||
bodies.forEach((body) => {
|
||||
requests.push(
|
||||
req.requestContext
|
||||
.search!.search(
|
||||
req.requestContext.search
|
||||
.search(
|
||||
{
|
||||
indexType,
|
||||
params: {
|
||||
|
|
|
@ -11,9 +11,7 @@ import {
|
|||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
RequestHandlerContext,
|
||||
Logger,
|
||||
IRouter,
|
||||
FakeRequest,
|
||||
} from 'src/core/server';
|
||||
import { Observable } from 'rxjs';
|
||||
|
@ -27,6 +25,7 @@ import { visDataRoutes } from './routes/vis';
|
|||
import { fieldsRoutes } from './routes/fields';
|
||||
import { SearchStrategyRegistry } from './lib/search_strategies';
|
||||
import { uiSettings } from './ui_settings';
|
||||
import type { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRouter } from './types';
|
||||
|
||||
export interface LegacySetup {
|
||||
server: Server;
|
||||
|
@ -42,7 +41,7 @@ interface VisTypeTimeseriesPluginStartDependencies {
|
|||
|
||||
export interface VisTypeTimeseriesSetup {
|
||||
getVisData: (
|
||||
requestContext: RequestHandlerContext,
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
fakeRequest: FakeRequest,
|
||||
options: GetVisDataOptions
|
||||
) => ReturnType<GetVisData>;
|
||||
|
@ -55,7 +54,7 @@ export interface Framework {
|
|||
config$: Observable<VisTypeTimeseriesConfig>;
|
||||
globalConfig$: PluginInitializerContext['config']['legacy']['globalConfig$'];
|
||||
logger: Logger;
|
||||
router: IRouter;
|
||||
router: VisTypeTimeseriesRouter;
|
||||
searchStrategyRegistry: SearchStrategyRegistry;
|
||||
}
|
||||
|
||||
|
@ -73,7 +72,7 @@ export class VisTypeTimeseriesPlugin implements Plugin<VisTypeTimeseriesSetup> {
|
|||
const config$ = this.initializerContext.config.create<VisTypeTimeseriesConfig>();
|
||||
// Global config contains things like the ES shard timeout
|
||||
const globalConfig$ = this.initializerContext.config.legacy.globalConfig$;
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<VisTypeTimeseriesRequestHandlerContext>();
|
||||
|
||||
const searchStrategyRegistry = new SearchStrategyRegistry();
|
||||
|
||||
|
@ -92,7 +91,7 @@ export class VisTypeTimeseriesPlugin implements Plugin<VisTypeTimeseriesSetup> {
|
|||
|
||||
return {
|
||||
getVisData: async (
|
||||
requestContext: RequestHandlerContext,
|
||||
requestContext: VisTypeTimeseriesRequestHandlerContext,
|
||||
fakeRequest: FakeRequest,
|
||||
options: GetVisDataOptions
|
||||
) => {
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { IRouter, KibanaRequest } from 'kibana/server';
|
||||
import { KibanaRequest } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ensureNoUnsafeProperties } from '@kbn/std';
|
||||
import { getVisData, GetVisDataOptions } from '../lib/get_vis_data';
|
||||
import { visPayloadSchema } from '../../common/vis_schema';
|
||||
import { ROUTES } from '../../common/constants';
|
||||
import { Framework } from '../plugin';
|
||||
import type { VisTypeTimeseriesRouter } from '../types';
|
||||
|
||||
const escapeHatch = schema.object({}, { unknowns: 'allow' });
|
||||
|
||||
export const visDataRoutes = (router: IRouter, framework: Framework) => {
|
||||
export const visDataRoutes = (router: VisTypeTimeseriesRouter, framework: Framework) => {
|
||||
router.post(
|
||||
{
|
||||
path: ROUTES.VIS_DATA,
|
||||
|
|
16
src/plugins/vis_type_timeseries/server/types.ts
Normal file
16
src/plugins/vis_type_timeseries/server/types.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* and the Server Side Public License, v 1; you may not use this file except in
|
||||
* compliance with, at your election, the Elastic License or the Server Side
|
||||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { IRouter, RequestHandlerContext } from 'src/core/server';
|
||||
import type { DataApiRequestHandlerContext } from '../../data/server';
|
||||
|
||||
export interface VisTypeTimeseriesRequestHandlerContext extends RequestHandlerContext {
|
||||
search: DataApiRequestHandlerContext;
|
||||
}
|
||||
|
||||
export type VisTypeTimeseriesRouter = IRouter<VisTypeTimeseriesRequestHandlerContext>;
|
|
@ -7,6 +7,6 @@
|
|||
*/
|
||||
|
||||
import { CorePluginAPlugin } from './plugin';
|
||||
export { PluginARequestContext } from './plugin';
|
||||
export { PluginAApiRequestContext } from './plugin';
|
||||
|
||||
export const plugin = () => new CorePluginAPlugin();
|
||||
|
|
|
@ -6,26 +6,27 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
import type { Plugin, CoreSetup, RequestHandlerContext } from 'kibana/server';
|
||||
|
||||
export interface PluginARequestContext {
|
||||
export interface PluginAApiRequestContext {
|
||||
ping: () => Promise<string>;
|
||||
}
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
pluginA?: PluginARequestContext;
|
||||
}
|
||||
interface PluginARequstHandlerContext extends RequestHandlerContext {
|
||||
pluginA: PluginAApiRequestContext;
|
||||
}
|
||||
|
||||
export class CorePluginAPlugin implements Plugin {
|
||||
public setup(core: CoreSetup, deps: {}) {
|
||||
core.http.registerRouteHandlerContext('pluginA', (context) => {
|
||||
return {
|
||||
ping: () =>
|
||||
context.core.elasticsearch.legacy.client.callAsInternalUser('ping') as Promise<string>,
|
||||
};
|
||||
});
|
||||
core.http.registerRouteHandlerContext<PluginARequstHandlerContext, 'pluginA'>(
|
||||
'pluginA',
|
||||
(context) => {
|
||||
return {
|
||||
ping: () =>
|
||||
context.core.elasticsearch.legacy.client.callAsInternalUser('ping') as Promise<string>,
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
|
|
|
@ -6,19 +6,17 @@
|
|||
* Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
import { Plugin, CoreSetup, RequestHandlerContext } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { PluginARequestContext } from '../../core_plugin_a/server';
|
||||
import { PluginAApiRequestContext } from '../../core_plugin_a/server';
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
pluginA?: PluginARequestContext;
|
||||
}
|
||||
interface PluginBContext extends RequestHandlerContext {
|
||||
pluginA: PluginAApiRequestContext;
|
||||
}
|
||||
|
||||
export class CorePluginBPlugin implements Plugin {
|
||||
public setup(core: CoreSetup, deps: {}) {
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<PluginBContext>();
|
||||
router.get({ path: '/core_plugin_b', validate: false }, async (context, req, res) => {
|
||||
if (!context.pluginA) return res.internalError({ body: 'pluginA is disabled' });
|
||||
const response = await context.pluginA.ping();
|
||||
|
|
|
@ -7,6 +7,5 @@
|
|||
*/
|
||||
|
||||
import { CorePluginRouteTimeoutsPlugin } from './plugin';
|
||||
export { PluginARequestContext } from './plugin';
|
||||
|
||||
export const plugin = () => new CorePluginRouteTimeoutsPlugin();
|
||||
|
|
|
@ -9,16 +9,6 @@
|
|||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
export interface PluginARequestContext {
|
||||
ping: () => Promise<string>;
|
||||
}
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
pluginA?: PluginARequestContext;
|
||||
}
|
||||
}
|
||||
|
||||
export class CorePluginRouteTimeoutsPlugin implements Plugin {
|
||||
public setup(core: CoreSetup, deps: {}) {
|
||||
const { http } = core;
|
||||
|
|
|
@ -14,12 +14,13 @@ import { ActionsConfigType } from './types';
|
|||
export type ActionsClient = PublicMethodsOf<ActionsClientClass>;
|
||||
export type ActionsAuthorization = PublicMethodsOf<ActionsAuthorizationClass>;
|
||||
|
||||
export {
|
||||
export type {
|
||||
ActionsPlugin,
|
||||
ActionResult,
|
||||
ActionTypeExecutorOptions,
|
||||
ActionType,
|
||||
PreConfiguredAction,
|
||||
ActionsApiRequestHandlerContext,
|
||||
} from './types';
|
||||
|
||||
export type {
|
||||
|
@ -45,7 +46,7 @@ export type {
|
|||
TeamsActionParams,
|
||||
} from './builtin_action_types';
|
||||
|
||||
export { PluginSetupContract, PluginStartContract } from './plugin';
|
||||
export type { PluginSetupContract, PluginStartContract } from './plugin';
|
||||
|
||||
export { asSavedObjectExecutionSource, asHttpRequestExecutionSource } from './lib';
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { featuresPluginMock } from '../../features/server/mocks';
|
|||
import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks';
|
||||
import { taskManagerMock } from '../../task_manager/server/mocks';
|
||||
import { eventLogMock } from '../../event_log/server/mocks';
|
||||
import { ActionType } from './types';
|
||||
import { ActionType, ActionsApiRequestHandlerContext } from './types';
|
||||
import { ActionsConfig } from './config';
|
||||
import {
|
||||
ActionsPlugin,
|
||||
|
@ -73,7 +73,10 @@ describe('Actions Plugin', () => {
|
|||
});
|
||||
|
||||
expect(coreSetup.http.registerRouteHandlerContext).toHaveBeenCalledTimes(1);
|
||||
const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0];
|
||||
const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0] as [
|
||||
string,
|
||||
Function
|
||||
];
|
||||
expect(handler[0]).toEqual('actions');
|
||||
|
||||
const actionsContextHandler = ((await handler[1](
|
||||
|
@ -91,7 +94,7 @@ describe('Actions Plugin', () => {
|
|||
} as unknown) as RequestHandlerContext,
|
||||
httpServerMock.createKibanaRequest(),
|
||||
httpServerMock.createResponseFactory()
|
||||
)) as unknown) as RequestHandlerContext['actions'];
|
||||
)) as unknown) as ActionsApiRequestHandlerContext;
|
||||
actionsContextHandler!.getActionsClient();
|
||||
});
|
||||
|
||||
|
@ -101,7 +104,10 @@ describe('Actions Plugin', () => {
|
|||
await plugin.setup(coreSetup as any, pluginsSetup);
|
||||
|
||||
expect(coreSetup.http.registerRouteHandlerContext).toHaveBeenCalledTimes(1);
|
||||
const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0];
|
||||
const handler = coreSetup.http.registerRouteHandlerContext.mock.calls[0] as [
|
||||
string,
|
||||
Function
|
||||
];
|
||||
expect(handler[0]).toEqual('actions');
|
||||
|
||||
const actionsContextHandler = ((await handler[1](
|
||||
|
@ -114,7 +120,7 @@ describe('Actions Plugin', () => {
|
|||
} as unknown) as RequestHandlerContext,
|
||||
httpServerMock.createKibanaRequest(),
|
||||
httpServerMock.createResponseFactory()
|
||||
)) as unknown) as RequestHandlerContext['actions'];
|
||||
)) as unknown) as ActionsApiRequestHandlerContext;
|
||||
expect(() => actionsContextHandler!.getActionsClient()).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unable to create actions client because the Encrypted Saved Objects plugin uses an ephemeral encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command."`
|
||||
);
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
CoreStart,
|
||||
KibanaRequest,
|
||||
Logger,
|
||||
RequestHandler,
|
||||
IContextProvider,
|
||||
ElasticsearchServiceStart,
|
||||
ILegacyClusterClient,
|
||||
|
@ -46,6 +45,7 @@ import {
|
|||
ActionTypeConfig,
|
||||
ActionTypeSecrets,
|
||||
ActionTypeParams,
|
||||
ActionsRequestHandlerContext,
|
||||
} from './types';
|
||||
|
||||
import { getActionsConfigurationUtilities } from './actions_config';
|
||||
|
@ -228,7 +228,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
|
|||
}
|
||||
|
||||
this.kibanaIndexConfig.subscribe((config) => {
|
||||
core.http.registerRouteHandlerContext(
|
||||
core.http.registerRouteHandlerContext<ActionsRequestHandlerContext, 'actions'>(
|
||||
'actions',
|
||||
this.createRouteHandlerContext(core, config.kibana.index)
|
||||
);
|
||||
|
@ -243,7 +243,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
|
|||
});
|
||||
|
||||
// Routes
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<ActionsRequestHandlerContext>();
|
||||
createActionRoute(router, this.licenseState);
|
||||
deleteActionRoute(router, this.licenseState);
|
||||
getActionRoute(router, this.licenseState);
|
||||
|
@ -448,7 +448,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
|
|||
private createRouteHandlerContext = (
|
||||
core: CoreSetup<ActionsPluginsStart>,
|
||||
defaultKibanaIndex: string
|
||||
): IContextProvider<RequestHandler<unknown, unknown, unknown>, 'actions'> => {
|
||||
): IContextProvider<ActionsRequestHandlerContext, 'actions'> => {
|
||||
const {
|
||||
actionTypeRegistry,
|
||||
isESOUsingEphemeralEncryptionKey,
|
||||
|
|
|
@ -4,15 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { ActionResult } from '../types';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ActionResult, ActionsRequestHandlerContext } from '../types';
|
||||
import { ILicenseState, verifyApiAccess, isErrorThatHandlesItsOwnResponse } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
|
||||
|
@ -23,7 +17,10 @@ export const bodySchema = schema.object({
|
|||
secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
|
||||
});
|
||||
|
||||
export const createActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const createActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/action`,
|
||||
|
@ -31,11 +28,7 @@ export const createActionRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
body: bodySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, unknown, TypeOf<typeof bodySchema>>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
|
||||
if (!context.actions) {
|
||||
|
|
|
@ -9,22 +9,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess, isErrorThatHandlesItsOwnResponse } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { ActionsRequestHandlerContext } from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const deleteActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const deleteActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.delete(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/action/{id}`,
|
||||
|
@ -32,11 +30,7 @@ export const deleteActionRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.actions) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for actions' });
|
||||
|
|
|
@ -3,17 +3,11 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess, isErrorThatHandlesItsOwnResponse } from '../lib';
|
||||
|
||||
import { ActionTypeExecutorResult } from '../types';
|
||||
import { ActionTypeExecutorResult, ActionsRequestHandlerContext } from '../types';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { asHttpRequestExecutionSource } from '../lib/action_execution_source';
|
||||
|
||||
|
@ -25,7 +19,10 @@ const bodySchema = schema.object({
|
|||
params: schema.recordOf(schema.string(), schema.any()),
|
||||
});
|
||||
|
||||
export const executeActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const executeActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/action/{id}/_execute`,
|
||||
|
@ -34,11 +31,7 @@ export const executeActionRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, TypeOf<typeof bodySchema>>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
|
||||
if (!context.actions) {
|
||||
|
|
|
@ -4,22 +4,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { ActionsRequestHandlerContext } from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const getActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const getActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/action/{id}`,
|
||||
|
@ -27,11 +25,7 @@ export const getActionRoute = (router: IRouter, licenseState: ILicenseState) =>
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.actions) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for actions' });
|
||||
|
|
|
@ -4,27 +4,21 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { ActionsRequestHandlerContext } from '../types';
|
||||
|
||||
export const getAllActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const getAllActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}`,
|
||||
validate: {},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.actions) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for actions' });
|
||||
|
|
|
@ -4,27 +4,21 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { ActionsRequestHandlerContext } from '../types';
|
||||
|
||||
export const listActionTypesRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const listActionTypesRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/list_action_types`,
|
||||
validate: {},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.actions) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for actions' });
|
||||
|
|
|
@ -4,16 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { ILicenseState, verifyApiAccess, isErrorThatHandlesItsOwnResponse } from '../lib';
|
||||
import { BASE_ACTION_API_PATH } from '../../common';
|
||||
import { ActionsRequestHandlerContext } from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
|
@ -25,7 +20,10 @@ const bodySchema = schema.object({
|
|||
secrets: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }),
|
||||
});
|
||||
|
||||
export const updateActionRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const updateActionRoute = (
|
||||
router: IRouter<ActionsRequestHandlerContext>,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.put(
|
||||
{
|
||||
path: `${BASE_ACTION_API_PATH}/action/{id}`,
|
||||
|
@ -34,11 +32,7 @@ export const updateActionRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, TypeOf<typeof bodySchema>>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.actions) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for actions' });
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
SavedObjectsClientContract,
|
||||
SavedObjectAttributes,
|
||||
ElasticsearchClient,
|
||||
RequestHandlerContext,
|
||||
} from '../../../../src/core/server';
|
||||
import { ActionTypeExecutorResult } from '../common';
|
||||
export { ActionTypeExecutorResult } from '../common';
|
||||
|
@ -40,13 +41,13 @@ export interface Services {
|
|||
getLegacyScopedClusterClient(clusterClient: ILegacyClusterClient): ILegacyScopedClusterClient;
|
||||
}
|
||||
|
||||
declare module 'src/core/server' {
|
||||
interface RequestHandlerContext {
|
||||
actions?: {
|
||||
getActionsClient: () => ActionsClient;
|
||||
listTypes: ActionTypeRegistry['list'];
|
||||
};
|
||||
}
|
||||
export interface ActionsApiRequestHandlerContext {
|
||||
getActionsClient: () => ActionsClient;
|
||||
listTypes: ActionTypeRegistry['list'];
|
||||
}
|
||||
|
||||
export interface ActionsRequestHandlerContext extends RequestHandlerContext {
|
||||
actions: ActionsApiRequestHandlerContext;
|
||||
}
|
||||
|
||||
export interface ActionsPlugin {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { AlertsConfigType } from './types';
|
|||
|
||||
export type AlertsClient = PublicMethodsOf<AlertsClientClass>;
|
||||
|
||||
export {
|
||||
export type {
|
||||
ActionVariable,
|
||||
AlertType,
|
||||
ActionGroup,
|
||||
|
@ -26,6 +26,7 @@ export {
|
|||
PartialAlert,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
AlertingApiRequestHandlerContext,
|
||||
} from './types';
|
||||
export { PluginSetupContract, PluginStartContract } from './plugin';
|
||||
export { FindResult } from './alerts_client';
|
||||
|
|
|
@ -28,13 +28,13 @@ import {
|
|||
CoreStart,
|
||||
SavedObjectsServiceStart,
|
||||
IContextProvider,
|
||||
RequestHandler,
|
||||
ElasticsearchServiceStart,
|
||||
ILegacyClusterClient,
|
||||
StatusServiceSetup,
|
||||
ServiceStatus,
|
||||
SavedObjectsBulkGetObject,
|
||||
} from '../../../../src/core/server';
|
||||
import type { AlertingRequestHandlerContext } from './types';
|
||||
|
||||
import {
|
||||
aggregateAlertRoute,
|
||||
|
@ -255,10 +255,13 @@ export class AlertingPlugin {
|
|||
|
||||
initializeAlertingHealth(this.logger, plugins.taskManager, core.getStartServices());
|
||||
|
||||
core.http.registerRouteHandlerContext('alerting', this.createRouteHandlerContext(core));
|
||||
core.http.registerRouteHandlerContext<AlertingRequestHandlerContext, 'alerting'>(
|
||||
'alerting',
|
||||
this.createRouteHandlerContext(core)
|
||||
);
|
||||
|
||||
// Routes
|
||||
const router = core.http.createRouter();
|
||||
const router = core.http.createRouter<AlertingRequestHandlerContext>();
|
||||
// Register routes
|
||||
aggregateAlertRoute(router, this.licenseState);
|
||||
createAlertRoute(router, this.licenseState);
|
||||
|
@ -392,7 +395,7 @@ export class AlertingPlugin {
|
|||
|
||||
private createRouteHandlerContext = (
|
||||
core: CoreSetup
|
||||
): IContextProvider<RequestHandler<unknown, unknown, unknown>, 'alerting'> => {
|
||||
): IContextProvider<AlertingRequestHandlerContext, 'alerting'> => {
|
||||
const { alertTypeRegistry, alertsClientFactory } = this;
|
||||
return async function alertsRouteHandlerContext(context, request) {
|
||||
const [{ savedObjects }] = await core.getStartServices();
|
||||
|
|
|
@ -4,18 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
KibanaResponseFactory,
|
||||
ILegacyClusterClient,
|
||||
} from 'kibana/server';
|
||||
import { KibanaRequest, KibanaResponseFactory, ILegacyClusterClient } from 'kibana/server';
|
||||
import { identity } from 'lodash';
|
||||
import type { MethodKeysOf } from '@kbn/utility-types';
|
||||
import { httpServerMock } from '../../../../../src/core/server/mocks';
|
||||
import { alertsClientMock, AlertsClientMock } from '../alerts_client.mock';
|
||||
import { AlertsHealth, AlertType } from '../../common';
|
||||
import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks';
|
||||
import type { AlertingRequestHandlerContext } from '../types';
|
||||
|
||||
export function mockHandlerArguments(
|
||||
{
|
||||
|
@ -32,7 +28,11 @@ export function mockHandlerArguments(
|
|||
},
|
||||
req: unknown,
|
||||
res?: Array<MethodKeysOf<KibanaResponseFactory>>
|
||||
): [RequestHandlerContext, KibanaRequest<unknown, unknown, unknown>, KibanaResponseFactory] {
|
||||
): [
|
||||
AlertingRequestHandlerContext,
|
||||
KibanaRequest<unknown, unknown, unknown>,
|
||||
KibanaResponseFactory
|
||||
] {
|
||||
const listTypes = jest.fn(() => listTypesRes);
|
||||
return [
|
||||
({
|
||||
|
@ -44,7 +44,7 @@ export function mockHandlerArguments(
|
|||
},
|
||||
getFrameworkHealth,
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
} as unknown) as AlertingRequestHandlerContext,
|
||||
req as KibanaRequest<unknown, unknown, unknown>,
|
||||
mockResponseFactory(res),
|
||||
];
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -38,7 +32,7 @@ const querySchema = schema.object({
|
|||
filter: schema.maybe(schema.string()),
|
||||
});
|
||||
|
||||
export const aggregateAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const aggregateAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/_aggregate`,
|
||||
|
@ -46,11 +40,7 @@ export const aggregateAlertRoute = (router: IRouter, licenseState: ILicenseState
|
|||
query: querySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, TypeOf<typeof querySchema>, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { validateDurationSchema } from '../lib';
|
||||
|
@ -48,7 +42,7 @@ export const bodySchema = schema.object({
|
|||
notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })),
|
||||
});
|
||||
|
||||
export const createAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const createAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.post(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert`,
|
||||
|
@ -57,11 +51,7 @@ export const createAlertRoute = (router: IRouter, licenseState: ILicenseState) =
|
|||
},
|
||||
},
|
||||
handleDisabledApiKeysError(
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, unknown, TypeOf<typeof bodySchema>>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
|
||||
if (!context.alerting) {
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -20,7 +14,7 @@ const paramSchema = schema.object({
|
|||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const deleteAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const deleteAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.delete(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}`,
|
||||
|
@ -28,11 +22,7 @@ export const deleteAlertRoute = (router: IRouter, licenseState: ILicenseState) =
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -21,7 +15,7 @@ const paramSchema = schema.object({
|
|||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const disableAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const disableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.post(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}/_disable`,
|
||||
|
@ -29,11 +23,7 @@ export const disableAlertRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -22,7 +16,7 @@ const paramSchema = schema.object({
|
|||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const enableAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const enableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.post(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}/_enable`,
|
||||
|
@ -31,11 +25,7 @@ export const enableAlertRoute = (router: IRouter, licenseState: ILicenseState) =
|
|||
},
|
||||
},
|
||||
handleDisabledApiKeysError(
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -43,7 +38,7 @@ const querySchema = schema.object({
|
|||
filter: schema.maybe(schema.string()),
|
||||
});
|
||||
|
||||
export const findAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const findAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/_find`,
|
||||
|
@ -51,11 +46,7 @@ export const findAlertRoute = (router: IRouter, licenseState: ILicenseState) =>
|
|||
query: querySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, TypeOf<typeof querySchema>, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,23 +4,17 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
import type { AlertingRouter } from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const getAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const getAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}`,
|
||||
|
@ -28,11 +22,7 @@ export const getAlertRoute = (router: IRouter, licenseState: ILicenseState) => {
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -24,7 +18,10 @@ const querySchema = schema.object({
|
|||
dateStart: schema.maybe(schema.string()),
|
||||
});
|
||||
|
||||
export const getAlertInstanceSummaryRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const getAlertInstanceSummaryRoute = (
|
||||
router: AlertingRouter,
|
||||
licenseState: ILicenseState
|
||||
) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`,
|
||||
|
@ -33,11 +30,7 @@ export const getAlertInstanceSummaryRoute = (router: IRouter, licenseState: ILic
|
|||
query: querySchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, TypeOf<typeof querySchema>, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,14 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { BASE_ALERT_API_PATH } from '../../common';
|
||||
|
@ -20,7 +14,7 @@ const paramSchema = schema.object({
|
|||
id: schema.string(),
|
||||
});
|
||||
|
||||
export const getAlertStateRoute = (router: IRouter, licenseState: ILicenseState) => {
|
||||
export const getAlertStateRoute = (router: AlertingRouter, licenseState: ILicenseState) => {
|
||||
router.get(
|
||||
{
|
||||
path: `${BASE_ALERT_API_PATH}/alert/{id}/state`,
|
||||
|
@ -28,11 +22,7 @@ export const getAlertStateRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
params: paramSchema,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<TypeOf<typeof paramSchema>, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -4,13 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
IRouter,
|
||||
RequestHandlerContext,
|
||||
KibanaRequest,
|
||||
IKibanaResponse,
|
||||
KibanaResponseFactory,
|
||||
} from 'kibana/server';
|
||||
import type { AlertingRouter } from '../types';
|
||||
import { ILicenseState } from '../lib/license_state';
|
||||
import { verifyApiAccess } from '../lib/license_api_access';
|
||||
import { AlertingFrameworkHealth } from '../types';
|
||||
|
@ -28,7 +22,7 @@ interface XPackUsageSecurity {
|
|||
}
|
||||
|
||||
export function healthRoute(
|
||||
router: IRouter,
|
||||
router: AlertingRouter,
|
||||
licenseState: ILicenseState,
|
||||
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
|
||||
) {
|
||||
|
@ -37,11 +31,7 @@ export function healthRoute(
|
|||
path: '/api/alerts/_health',
|
||||
validate: false,
|
||||
},
|
||||
router.handleLegacyErrors(async function (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<unknown, unknown, unknown>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse> {
|
||||
router.handleLegacyErrors(async function (context, req, res) {
|
||||
verifyApiAccess(licenseState);
|
||||
if (!context.alerting) {
|
||||
return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' });
|
||||
|
|
|
@ -5,22 +5,10 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
RequestHandler,
|
||||
KibanaRequest,
|
||||
KibanaResponseFactory,
|
||||
RequestHandlerContext,
|
||||
RouteMethod,
|
||||
} from 'kibana/server';
|
||||
import { RequestHandlerWrapper } from 'kibana/server';
|
||||
|
||||
export function handleDisabledApiKeysError<P, Q, B>(
|
||||
handler: RequestHandler<P, Q, B>
|
||||
): RequestHandler<P, Q, B> {
|
||||
return async (
|
||||
context: RequestHandlerContext,
|
||||
request: KibanaRequest<P, Q, B, RouteMethod>,
|
||||
response: KibanaResponseFactory
|
||||
) => {
|
||||
export const handleDisabledApiKeysError: RequestHandlerWrapper = (handler) => {
|
||||
return async (context, request, response) => {
|
||||
try {
|
||||
return await handler(context, request, response);
|
||||
} catch (e) {
|
||||
|
@ -36,7 +24,7 @@ export function handleDisabledApiKeysError<P, Q, B>(
|
|||
throw e;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export function isApiKeyDisabledError(e: Error) {
|
||||
return e?.message?.includes('api keys are not enabled') ?? false;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue