+
) : (
diff --git a/src/plugins/data_view_management/server/routes/preview_scripted_field.ts b/src/plugins/data_view_management/server/routes/preview_scripted_field.ts
index 71df0d5033a11..f5384bedce956 100644
--- a/src/plugins/data_view_management/server/routes/preview_scripted_field.ts
+++ b/src/plugins/data_view_management/server/routes/preview_scripted_field.ts
@@ -14,6 +14,12 @@ export function registerPreviewScriptedFieldRoute(router: IRouter): void {
router.post(
{
path: '/internal/index-pattern-management/preview_scripted_field',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by Elasticsearch',
+ },
+ },
validate: {
body: schema.object({
index: schema.string(),
diff --git a/src/plugins/data_view_management/server/routes/resolve_index.ts b/src/plugins/data_view_management/server/routes/resolve_index.ts
index c6b054182b1c4..f51027e55f9ca 100644
--- a/src/plugins/data_view_management/server/routes/resolve_index.ts
+++ b/src/plugins/data_view_management/server/routes/resolve_index.ts
@@ -15,6 +15,12 @@ export function registerResolveIndexRoute(router: IRouter): void {
router.get(
{
path: '/internal/index-pattern-management/resolve_index/{query}',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by Elasticsearch',
+ },
+ },
validate: {
params: schema.object({
query: schema.string(),
diff --git a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts
index 5471ddb5dfedd..cf7806d76a4be 100644
--- a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts
+++ b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts
@@ -60,6 +60,12 @@ export const registerExistingIndicesPath = (router: IRouter): void => {
.addVersion(
{
version,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'This route is opted out from authorization',
+ },
+ },
validate: {
request: {
query: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields.ts
index 0d8f8b4dd67b5..9543fc4c3f008 100644
--- a/src/plugins/data_views/server/rest_api_routes/internal/fields.ts
+++ b/src/plugins/data_views/server/rest_api_routes/internal/fields.ts
@@ -146,10 +146,17 @@ export const registerFields = (
>,
isRollupsEnabled: () => boolean
) => {
- router.versioned
- .get({ path, access: 'internal', enableQueryVersion: true })
- .addVersion(
- { version: '1', validate: { request: { query: querySchema }, response: validate.response } },
- handler(isRollupsEnabled)
- );
+ router.versioned.get({ path, access: 'internal', enableQueryVersion: true }).addVersion(
+ {
+ version: '1',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by Elasticsearch',
+ },
+ },
+ validate: { request: { query: querySchema }, response: validate.response },
+ },
+ handler(isRollupsEnabled)
+ );
};
diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts
index 7ff9f3ee9fede..d444d6f5131f1 100644
--- a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts
+++ b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts
@@ -9,7 +9,7 @@
import { estypes } from '@elastic/elasticsearch';
import { schema } from '@kbn/config-schema';
-import { IRouter, RequestHandler, StartServicesAccessor } from '@kbn/core/server';
+import type { IRouter, RequestHandler, RouteAuthz, StartServicesAccessor } from '@kbn/core/server';
import { VersionedRouteValidation } from '@kbn/core-http-server';
import { INITIAL_REST_VERSION_INTERNAL as version } from '../../constants';
import { IndexPatternsFetcher } from '../../fetcher';
@@ -217,14 +217,31 @@ export const registerFieldForWildcard = (
isRollupsEnabled: () => boolean
) => {
const configuredHandler = handler(isRollupsEnabled);
+ const authz: RouteAuthz = { enabled: false, reason: 'Authorization provided by Elasticsearch' };
// handler
- router.versioned.put({ path, access }).addVersion({ version, validate }, configuredHandler);
- router.versioned.post({ path, access }).addVersion({ version, validate }, configuredHandler);
- router.versioned
- .get({ path, access })
- .addVersion(
- { version, validate: { request: { query: querySchema }, response: validate.response } },
- configuredHandler
- );
+ router.versioned.put({ path, access }).addVersion(
+ {
+ version,
+ security: { authz },
+ validate,
+ },
+ configuredHandler
+ );
+ router.versioned.post({ path, access }).addVersion(
+ {
+ version,
+ security: { authz },
+ validate,
+ },
+ configuredHandler
+ );
+ router.versioned.get({ path, access }).addVersion(
+ {
+ version,
+ security: { authz },
+ validate: { request: { query: querySchema }, response: validate.response },
+ },
+ configuredHandler
+ );
};
diff --git a/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts b/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts
index a03da883594a3..4db1fce3a2040 100644
--- a/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts
+++ b/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts
@@ -45,6 +45,12 @@ export const registerHasDataViewsRoute = (router: IRouter): void => {
.addVersion(
{
version: '1',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
response: {
200: {
diff --git a/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts b/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts
index 72b2e508ba529..f9907e55f49b6 100644
--- a/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts
+++ b/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts
@@ -133,6 +133,12 @@ export const registerHasEsDataRoute = (
.addVersion(
{
version: '1',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by Elasticsearch',
+ },
+ },
validate: {
response: {
200: {
diff --git a/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts
index 374c83880c019..68147df006ab4 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts
@@ -61,6 +61,11 @@ const registerCreateDataViewRouteFactory =
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
body: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts
index 47700284d717b..9a5bf1f4ff361 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts
@@ -73,6 +73,12 @@ const manageDefaultIndexPatternRoutesFactory =
router.versioned.get({ path, access: 'public', description: getDescription }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {},
response: {
@@ -110,6 +116,11 @@ const manageDefaultIndexPatternRoutesFactory =
router.versioned.post({ path, access: 'public', description: postDescription }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
body: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts
index 686c642257b31..cea1bd7e4e31e 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts
@@ -53,6 +53,11 @@ const deleteIndexPatternRouteFactory =
router.versioned.delete({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts
index eb59b0f8911bc..5f8faa2093ad5 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts
@@ -131,6 +131,11 @@ const updateFieldsActionRouteFactory = (path: string, serviceKey: string, descri
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts
index 6f4a7b7607a44..9b81de4913cb5 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts
@@ -57,6 +57,12 @@ const getDataViewRouteFactory =
router.versioned.get({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts b/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts
index 1add1096fe4ee..7ac2b3f1cb870 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts
@@ -66,6 +66,12 @@ const getDataViewsRouteFactory =
router.versioned.get({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {},
response: { 200: { body: responseValidation } },
diff --git a/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts
index 026b39dfbbf2a..62117555259f8 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts
@@ -46,6 +46,12 @@ const hasUserDataViewRouteFactory =
router.versioned.get({ path, access: 'internal' }).addVersion(
{
version: '1',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {},
response: {
diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts
index 301891642b2a7..2419082086daa 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts
@@ -82,6 +82,11 @@ const runtimeCreateFieldRouteFactory =
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts
index 92e295f874aa7..d12aeabccc312 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts
@@ -65,6 +65,11 @@ const deleteRuntimeFieldRouteFactory =
router.versioned.delete({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts
index 574320c4e95d9..65f9af3c4fe01 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts
@@ -73,6 +73,12 @@ const getRuntimeFieldRouteFactory =
router.versioned.get({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {
params: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts
index cc122bb1da750..620e1fec6cca1 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts
@@ -81,6 +81,11 @@ const putRuntimeFieldRouteFactory =
router.versioned.put({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts
index 612eebac89787..cd5c196e0e4f8 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts
@@ -81,6 +81,11 @@ const updateRuntimeFieldRouteFactory =
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts
index a826237b4b65e..829b5aa29c686 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts
@@ -31,6 +31,11 @@ export const registerCreateScriptedFieldRoute = (
.addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts
index e2d4285524825..66790d0d7f5e7 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts
@@ -32,6 +32,11 @@ export const registerDeleteScriptedFieldRoute = (
.addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts
index 18e5239715405..ba1b275ba5604 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts
@@ -31,6 +31,12 @@ export const registerGetScriptedFieldRoute = (
.addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts
index 0860804aa6789..d6c8b534dbd84 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts
@@ -31,6 +31,11 @@ export const registerPutScriptedFieldRoute = (
.addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts
index be42dd4787373..2ff837728d091 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts
@@ -36,6 +36,11 @@ export const registerUpdateScriptedFieldRoute = (
.addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts b/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts
index f40932137e3b3..52faad19da0eb 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts
@@ -70,6 +70,14 @@ export const swapReferencesRoute =
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ enabled: false,
+ // We don't use the indexPatterns:manage privilege for this route because it can be used for saved object
+ // types other than index-pattern
+ reason: 'Authorization provided by saved objects client',
+ },
+ },
validate: {
request: {
body: schema.object({
diff --git a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts
index 51d7056ae2a2d..15e64ba05a340 100644
--- a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts
+++ b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts
@@ -147,6 +147,11 @@ const updateDataViewRouteFactory =
router.versioned.post({ path, access: 'public', description }).addVersion(
{
version: INITIAL_REST_VERSION,
+ security: {
+ authz: {
+ requiredPrivileges: ['indexPatterns:manage'],
+ },
+ },
validate: {
request: {
params: schema.object(
diff --git a/src/plugins/dev_tools/public/application.tsx b/src/plugins/dev_tools/public/application.tsx
index f58441cd6ddcc..0b66621fb2e9d 100644
--- a/src/plugins/dev_tools/public/application.tsx
+++ b/src/plugins/dev_tools/public/application.tsx
@@ -75,7 +75,7 @@ function DevToolsWrapper({
return (
-
+
{devTools.map((currentDevTool) => (
onClose()}
- style={{ width: 700 }}
+ css={{ width: 700 }}
data-test-subj="discover-esql-to-dataview-modal"
>
diff --git a/src/plugins/discover/public/application/main/components/total_documents/total_documents.tsx b/src/plugins/discover/public/application/main/components/total_documents/total_documents.tsx
index 5644efc8a9bbd..053d1b3362bd1 100644
--- a/src/plugins/discover/public/application/main/components/total_documents/total_documents.tsx
+++ b/src/plugins/discover/public/application/main/components/total_documents/total_documents.tsx
@@ -28,7 +28,7 @@ export const TotalDocuments = ({
{isEsqlMode ? (
diff --git a/src/plugins/discover/public/components/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap b/src/plugins/discover/public/components/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap
index 22e4b3a0d9657..2b44ac56c64ae 100644
--- a/src/plugins/discover/public/components/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap
+++ b/src/plugins/discover/public/components/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap
@@ -6,7 +6,7 @@ exports[`TableHeader with time column renders correctly 1`] = `
data-test-subj="docTableHeader"
>
|
| |
- | |
+ |
{displayedColumns.map((col, index) => {
return (
{
return {
logsContextService: createLogsContextServiceMock(),
+ discoverShared: discoverSharedPluginMock.createStartContract(),
} as ProfileProviderServices;
};
diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/create_app_wrapper_accessor.ts b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/create_app_wrapper_accessor.ts
new file mode 100644
index 0000000000000..42382f088b7a3
--- /dev/null
+++ b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/create_app_wrapper_accessor.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import type { SecuritySolutionAppWrapperFeature } from '@kbn/discover-shared-plugin/public';
+
+export const createAppWrapperAccessor = async (
+ appWrapperFeature?: SecuritySolutionAppWrapperFeature
+) => {
+ if (!appWrapperFeature) return undefined;
+ return appWrapperFeature.getWrapper();
+};
diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.test.tsx b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.test.tsx
new file mode 100644
index 0000000000000..9774bafdb69b3
--- /dev/null
+++ b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.test.tsx
@@ -0,0 +1,57 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import React from 'react';
+import type { SecuritySolutionCellRendererFeature } from '@kbn/discover-shared-plugin/public';
+import { DataGridCellValueElementProps } from '@kbn/unified-data-table';
+import { createCellRendererAccessor } from './get_cell_renderer_accessor';
+import { render } from '@testing-library/react';
+
+const cellRendererFeature: SecuritySolutionCellRendererFeature = {
+ id: 'security-solution-cell-renderer',
+ getRenderer: async () => (fieldName: string) => {
+ if (fieldName === 'host.name') {
+ return (props: DataGridCellValueElementProps) => {
+ return {props.columnId}
;
+ };
+ }
+ },
+};
+
+const mockCellProps = {
+ columnId: 'host.name',
+ row: {
+ id: '1',
+ raw: {},
+ flattened: {},
+ },
+} as DataGridCellValueElementProps;
+
+describe('getCellRendererAccessort', () => {
+ it('should return a cell renderer', async () => {
+ const getCellRenderer = await createCellRendererAccessor(cellRendererFeature);
+ expect(getCellRenderer).toBeDefined();
+ const CellRenderer = getCellRenderer?.('host.name') as React.FC;
+ expect(CellRenderer).toBeDefined();
+ const { getByTestId } = render();
+ expect(getByTestId('cell-render-feature')).toBeVisible();
+ expect(getByTestId('cell-render-feature')).toHaveTextContent('host.name');
+ });
+
+ it('should return undefined if cellRendererFeature is not defined', async () => {
+ const getCellRenderer = await createCellRendererAccessor();
+ expect(getCellRenderer).toBeUndefined();
+ });
+
+ it('should return undefined if cellRendererGetter returns undefined', async () => {
+ const getCellRenderer = await createCellRendererAccessor(cellRendererFeature);
+ const cellRenderer = getCellRenderer?.('user.name');
+ expect(cellRenderer).toBeUndefined();
+ });
+});
diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.tsx b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.tsx
new file mode 100644
index 0000000000000..9f1d18d4a4d90
--- /dev/null
+++ b/src/plugins/discover/public/context_awareness/profile_providers/security/accessors/get_cell_renderer_accessor.tsx
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import React from 'react';
+import type { SecuritySolutionCellRendererFeature } from '@kbn/discover-shared-plugin/public';
+import { DataGridCellValueElementProps } from '@kbn/unified-data-table';
+
+export const createCellRendererAccessor = async (
+ cellRendererFeature?: SecuritySolutionCellRendererFeature
+) => {
+ if (!cellRendererFeature) return undefined;
+ const cellRendererGetter = await cellRendererFeature.getRenderer();
+ function getCellRenderer(fieldName: string) {
+ const CellRenderer = cellRendererGetter(fieldName);
+ if (!CellRenderer) return undefined;
+ return React.memo(function SecuritySolutionCellRenderer(props: DataGridCellValueElementProps) {
+ return ;
+ });
+ }
+
+ return getCellRenderer;
+};
diff --git a/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx
index 602879125a331..572c86a0e515b 100644
--- a/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx
+++ b/src/plugins/discover/public/context_awareness/profile_providers/security/security_root_profile/profile.tsx
@@ -7,25 +7,71 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
+import React, { FunctionComponent, PropsWithChildren } from 'react';
+import { DataGridCellValueElementProps } from '@kbn/unified-data-table';
import { RootProfileProvider, SolutionType } from '../../../profiles';
import { ProfileProviderServices } from '../../profile_provider_services';
import { SecurityProfileProviderFactory } from '../types';
+import { createCellRendererAccessor } from '../accessors/get_cell_renderer_accessor';
+import { createAppWrapperAccessor } from '../accessors/create_app_wrapper_accessor';
+
+interface SecurityRootProfileContext {
+ appWrapper?: FunctionComponent>;
+ getCellRenderer?: (
+ fieldName: string
+ ) => FunctionComponent | undefined;
+}
+
+const EmptyAppWrapper: FunctionComponent> = ({ children }) => <>{children}>;
export const createSecurityRootProfileProvider: SecurityProfileProviderFactory<
- RootProfileProvider
-> = (services: ProfileProviderServices) => ({
- profileId: 'security-root-profile',
- isExperimental: true,
- profile: {
- getCellRenderers: (prev) => (params) => ({
- ...prev(params),
- }),
- },
- resolve: (params) => {
- if (params.solutionNavId === SolutionType.Security) {
- return { isMatch: true, context: { solutionType: SolutionType.Security } };
- }
+ RootProfileProvider
+> = (services: ProfileProviderServices) => {
+ const { discoverShared } = services;
+ const discoverFeaturesRegistry = discoverShared.features.registry;
+ const cellRendererFeature = discoverFeaturesRegistry.getById('security-solution-cell-renderer');
+ const appWrapperFeature = discoverFeaturesRegistry.getById('security-solution-app-wrapper');
+
+ return {
+ profileId: 'security-root-profile',
+ isExperimental: true,
+ profile: {
+ getRenderAppWrapper: (PrevWrapper, params) => {
+ const AppWrapper = params.context.appWrapper ?? EmptyAppWrapper;
+ return ({ children }) => (
+
+ {children}
+
+ );
+ },
+ getCellRenderers:
+ (prev, { context }) =>
+ (params) => {
+ const entries = prev(params);
+ ['host.name', 'user.name', 'source.ip', 'destination.ip'].forEach((fieldName) => {
+ entries[fieldName] = context.getCellRenderer?.(fieldName) ?? entries[fieldName];
+ });
+ return entries;
+ },
+ },
+ resolve: async (params) => {
+ if (params.solutionNavId !== SolutionType.Security) {
+ return {
+ isMatch: false,
+ };
+ }
+
+ const getAppWrapper = await createAppWrapperAccessor(appWrapperFeature);
+ const getCellRenderer = await createCellRendererAccessor(cellRendererFeature);
- return { isMatch: false };
- },
-});
+ return {
+ isMatch: true,
+ context: {
+ solutionType: SolutionType.Security,
+ appWrapper: getAppWrapper?.(),
+ getCellRenderer,
+ },
+ };
+ },
+ };
+};
diff --git a/src/plugins/discover/public/context_awareness/types.ts b/src/plugins/discover/public/context_awareness/types.ts
index 51034e97155b6..70e40df3f8f63 100644
--- a/src/plugins/discover/public/context_awareness/types.ts
+++ b/src/plugins/discover/public/context_awareness/types.ts
@@ -20,7 +20,7 @@ import type { EuiIconType } from '@elastic/eui/src/components/icon/icon';
import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query';
import type { OmitIndexSignature } from 'type-fest';
import type { Trigger } from '@kbn/ui-actions-plugin/public';
-import type { PropsWithChildren, ReactElement } from 'react';
+import type { FunctionComponent, PropsWithChildren } from 'react';
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
import type { DiscoverDataSource } from '../../common/data_sources';
import type { DiscoverAppState } from '../application/main/state_management/discover_app_state_container';
@@ -268,7 +268,7 @@ export interface Profile {
* @param props The app wrapper props
* @returns The custom app wrapper component
*/
- getRenderAppWrapper: (props: PropsWithChildren<{}>) => ReactElement;
+ getRenderAppWrapper: FunctionComponent>;
/**
* Gets default Discover app state that should be used when the profile is resolved
diff --git a/src/plugins/discover/public/embeddable/components/saved_search_embeddable_base.tsx b/src/plugins/discover/public/embeddable/components/saved_search_embeddable_base.tsx
index deea7aa43c9fc..f723ae1ea7495 100644
--- a/src/plugins/discover/public/embeddable/components/saved_search_embeddable_base.tsx
+++ b/src/plugins/discover/public/embeddable/components/saved_search_embeddable_base.tsx
@@ -69,7 +69,7 @@ export const SavedSearchEmbeddableBase: FC
)}
- {children}
+ {children}
{Boolean(append) && {append}}
diff --git a/src/plugins/discover/public/embeddable/components/saved_search_grid.tsx b/src/plugins/discover/public/embeddable/components/saved_search_grid.tsx
index f6c77dc6cddf5..0a2919fe1540c 100644
--- a/src/plugins/discover/public/embeddable/components/saved_search_grid.tsx
+++ b/src/plugins/discover/public/embeddable/components/saved_search_grid.tsx
@@ -36,12 +36,13 @@ interface DiscoverGridEmbeddableProps extends Omit void;
onRemoveColumn: (column: string) => void;
savedSearchId?: string;
+ enableDocumentViewer: boolean;
}
export const DiscoverGridMemoized = React.memo(DiscoverGrid);
export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
- const { interceptedWarnings, ...gridProps } = props;
+ const { interceptedWarnings, enableDocumentViewer, ...gridProps } = props;
const [expandedDoc, setExpandedDoc] = useState(undefined);
@@ -131,7 +132,7 @@ export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
expandedDoc={expandedDoc}
showMultiFields={props.services.uiSettings.get(SHOW_MULTIFIELDS)}
maxDocFieldsDisplayed={props.services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)}
- renderDocumentView={renderDocumentView}
+ renderDocumentView={enableDocumentViewer ? renderDocumentView : undefined}
renderCustomToolbar={renderCustomToolbarWithElements}
externalCustomRenderers={cellRenderers}
enableComparisonMode
diff --git a/src/plugins/discover/public/embeddable/components/search_embeddable_grid_component.tsx b/src/plugins/discover/public/embeddable/components/search_embeddable_grid_component.tsx
index 44d3c1685cbfe..9c7a54054d265 100644
--- a/src/plugins/discover/public/embeddable/components/search_embeddable_grid_component.tsx
+++ b/src/plugins/discover/public/embeddable/components/search_embeddable_grid_component.tsx
@@ -49,6 +49,7 @@ interface SavedSearchEmbeddableComponentProps {
};
dataView: DataView;
onAddFilter?: DocViewFilterFn;
+ enableDocumentViewer: boolean;
stateManager: SearchEmbeddableStateManager;
}
@@ -59,6 +60,7 @@ export function SearchEmbeddableGridComponent({
api,
dataView,
onAddFilter,
+ enableDocumentViewer,
stateManager,
}: SavedSearchEmbeddableComponentProps) {
const discoverServices = useDiscoverServices();
@@ -272,6 +274,7 @@ export function SearchEmbeddableGridComponent({
services={discoverServices}
showTimeCol={!discoverServices.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false)}
dataGridDensityState={savedSearch.density}
+ enableDocumentViewer={enableDocumentViewer}
/>
);
}
diff --git a/src/plugins/discover/public/embeddable/get_search_embeddable_factory.tsx b/src/plugins/discover/public/embeddable/get_search_embeddable_factory.tsx
index 37213b17c377d..4117a36a4e048 100644
--- a/src/plugins/discover/public/embeddable/get_search_embeddable_factory.tsx
+++ b/src/plugins/discover/public/embeddable/get_search_embeddable_factory.tsx
@@ -37,6 +37,7 @@ import { initializeEditApi } from './initialize_edit_api';
import { initializeFetch, isEsqlMode } from './initialize_fetch';
import { initializeSearchEmbeddableApi } from './initialize_search_embeddable_api';
import {
+ NonPersistedDisplayOptions,
SearchEmbeddableApi,
SearchEmbeddableRuntimeState,
SearchEmbeddableSerializedState,
@@ -84,6 +85,11 @@ export const getSearchEmbeddableFactory = ({
initialState?.savedObjectDescription
);
+ /** By-value SavedSearchComponent package (non-dashboard contexts) state, to adhere to the comparator contract of an embeddable. */
+ const nonPersistedDisplayOptions$ = new BehaviorSubject<
+ NonPersistedDisplayOptions | undefined
+ >(initialState?.nonPersistedDisplayOptions);
+
/** All other state */
const blockingError$ = new BehaviorSubject(undefined);
const dataLoading$ = new BehaviorSubject(true);
@@ -201,6 +207,10 @@ export const getSearchEmbeddableFactory = ({
defaultPanelDescription$,
(value) => defaultPanelDescription$.next(value),
],
+ nonPersistedDisplayOptions: [
+ nonPersistedDisplayOptions$,
+ (value) => nonPersistedDisplayOptions$.next(value),
+ ],
}
);
@@ -304,7 +314,18 @@ export const getSearchEmbeddableFactory = ({
diff --git a/src/plugins/discover/public/embeddable/initialize_search_embeddable_api.tsx b/src/plugins/discover/public/embeddable/initialize_search_embeddable_api.tsx
index e824fb6fdc021..650d2e95852bb 100644
--- a/src/plugins/discover/public/embeddable/initialize_search_embeddable_api.tsx
+++ b/src/plugins/discover/public/embeddable/initialize_search_embeddable_api.tsx
@@ -15,8 +15,8 @@ import { ISearchSource, SerializedSearchSourceFields } from '@kbn/data-plugin/co
import { DataView } from '@kbn/data-views-plugin/common';
import { DataTableRecord } from '@kbn/discover-utils/types';
import type {
- PublishesDataViews,
- PublishesUnifiedSearch,
+ PublishesWritableUnifiedSearch,
+ PublishesWritableDataViews,
StateComparators,
} from '@kbn/presentation-publishing';
import { DiscoverGridSettings, SavedSearch } from '@kbn/saved-search-plugin/common';
@@ -71,7 +71,7 @@ export const initializeSearchEmbeddableApi = async (
discoverServices: DiscoverServices;
}
): Promise<{
- api: PublishesSavedSearch & PublishesDataViews & Partial;
+ api: PublishesSavedSearch & PublishesWritableDataViews & Partial;
stateManager: SearchEmbeddableStateManager;
comparators: StateComparators;
cleanup: () => void;
@@ -144,6 +144,25 @@ export const initializeSearchEmbeddableApi = async (
pick(stateManager, EDITABLE_SAVED_SEARCH_KEYS)
);
+ /** APIs for updating search source properties */
+ const setDataViews = (nextDataViews: DataView[]) => {
+ searchSource.setField('index', nextDataViews[0]);
+ dataViews.next(nextDataViews);
+ searchSource$.next(searchSource);
+ };
+
+ const setFilters = (filters: Filter[] | undefined) => {
+ searchSource.setField('filter', filters);
+ filters$.next(filters);
+ searchSource$.next(searchSource);
+ };
+
+ const setQuery = (query: Query | AggregateQuery | undefined) => {
+ searchSource.setField('query', query);
+ query$.next(query);
+ searchSource$.next(searchSource);
+ };
+
/** Keep the saved search in sync with any state changes */
const syncSavedSearch = combineLatest([onAnyStateChange, searchSource$])
.pipe(
@@ -163,10 +182,13 @@ export const initializeSearchEmbeddableApi = async (
syncSavedSearch.unsubscribe();
},
api: {
+ setDataViews,
dataViews,
savedSearch$,
filters$,
+ setFilters,
query$,
+ setQuery,
},
stateManager,
comparators: {
diff --git a/src/plugins/discover/public/embeddable/types.ts b/src/plugins/discover/public/embeddable/types.ts
index 1b7ab4a96c2de..64cf5a390da3a 100644
--- a/src/plugins/discover/public/embeddable/types.ts
+++ b/src/plugins/discover/public/embeddable/types.ts
@@ -15,10 +15,9 @@ import {
HasInPlaceLibraryTransforms,
PublishesBlockingError,
PublishesDataLoading,
- PublishesDataViews,
PublishesSavedObjectId,
- PublishesUnifiedSearch,
PublishesWritablePanelTitle,
+ PublishesWritableUnifiedSearch,
PublishingSubject,
SerializedTimeRange,
SerializedTitles,
@@ -30,6 +29,7 @@ import {
} from '@kbn/saved-search-plugin/common/types';
import { DataTableColumnsMeta } from '@kbn/unified-data-table';
import { BehaviorSubject } from 'rxjs';
+import { PublishesWritableDataViews } from '@kbn/presentation-publishing/interfaces/publishes_data_views';
import { EDITABLE_SAVED_SEARCH_KEYS } from './constants';
export type SearchEmbeddableState = Pick<
@@ -59,6 +59,13 @@ export type SearchEmbeddableSerializedAttributes = Omit<
> &
Pick;
+// These are options that are not persisted in the saved object, but can be used by solutions
+// when utilising the SavedSearchComponent package outside of dashboard contexts.
+export interface NonPersistedDisplayOptions {
+ enableDocumentViewer?: boolean;
+ enableFilters?: boolean;
+}
+
export type SearchEmbeddableSerializedState = SerializedTitles &
SerializedTimeRange &
Partial> & {
@@ -66,6 +73,7 @@ export type SearchEmbeddableSerializedState = SerializedTitles &
attributes?: SavedSearchAttributes & { references: SavedSearch['references'] };
// by reference
savedObjectId?: string;
+ nonPersistedDisplayOptions?: NonPersistedDisplayOptions;
};
export type SearchEmbeddableRuntimeState = SearchEmbeddableSerializedAttributes &
@@ -74,20 +82,20 @@ export type SearchEmbeddableRuntimeState = SearchEmbeddableSerializedAttributes
savedObjectTitle?: string;
savedObjectId?: string;
savedObjectDescription?: string;
+ nonPersistedDisplayOptions?: NonPersistedDisplayOptions;
};
export type SearchEmbeddableApi = DefaultEmbeddableApi<
SearchEmbeddableSerializedState,
SearchEmbeddableRuntimeState
> &
- PublishesDataViews &
PublishesSavedObjectId &
PublishesDataLoading &
PublishesBlockingError &
PublishesWritablePanelTitle &
PublishesSavedSearch &
- PublishesDataViews &
- PublishesUnifiedSearch &
+ PublishesWritableDataViews &
+ PublishesWritableUnifiedSearch &
HasInPlaceLibraryTransforms &
HasTimeRange &
Partial;
diff --git a/src/plugins/discover/public/embeddable/utils/serialization_utils.ts b/src/plugins/discover/public/embeddable/utils/serialization_utils.ts
index 191a37fe3326e..f193d52054a3c 100644
--- a/src/plugins/discover/public/embeddable/utils/serialization_utils.ts
+++ b/src/plugins/discover/public/embeddable/utils/serialization_utils.ts
@@ -67,6 +67,7 @@ export const deserializeState = async ({
return {
...savedSearch,
...panelState,
+ nonPersistedDisplayOptions: serializedState.rawState.nonPersistedDisplayOptions,
};
}
};
diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts
index b5d4308010f1f..b54665bdc50a0 100644
--- a/src/plugins/discover/public/index.ts
+++ b/src/plugins/discover/public/index.ts
@@ -35,6 +35,10 @@ export {
type PublishesSavedSearch,
type HasTimeRange,
type SearchEmbeddableSerializedState,
+ type SearchEmbeddableRuntimeState,
+ type SearchEmbeddableApi,
+ type NonPersistedDisplayOptions,
} from './embeddable';
export { loadSharingDataHelpers } from './utils';
export { LogsExplorerTabs, type LogsExplorerTabsProps } from './components/logs_explorer_tabs';
+export type { DiscoverServices } from './build_services';
diff --git a/src/plugins/discover/public/types.ts b/src/plugins/discover/public/types.ts
index 2ef380db98703..4b16e3e58df7c 100644
--- a/src/plugins/discover/public/types.ts
+++ b/src/plugins/discover/public/types.ts
@@ -42,7 +42,7 @@ import type { AiopsPluginStart } from '@kbn/aiops-plugin/public';
import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public';
import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public';
import type { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public';
-import { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public';
+import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public';
import { DiscoverAppLocator } from '../common';
import { DiscoverCustomizationContext } from './customizations';
import { type DiscoverContainerProps } from './components/discover_container';
diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json
index 1bb3aa10acce0..36655983db13a 100644
--- a/src/plugins/discover/tsconfig.json
+++ b/src/plugins/discover/tsconfig.json
@@ -95,9 +95,9 @@
"@kbn/presentation-containers",
"@kbn/observability-ai-assistant-plugin",
"@kbn/fields-metadata-plugin",
+ "@kbn/discover-contextual-components",
"@kbn/logs-data-access-plugin",
"@kbn/core-lifecycle-browser",
- "@kbn/discover-contextual-components",
"@kbn/esql-ast",
"@kbn/discover-shared-plugin"
],
diff --git a/src/plugins/discover_shared/public/index.ts b/src/plugins/discover_shared/public/index.ts
index f58a9eaf44f84..4be7a75c817a8 100644
--- a/src/plugins/discover_shared/public/index.ts
+++ b/src/plugins/discover_shared/public/index.ts
@@ -17,5 +17,9 @@ export type { DiscoverSharedPublicSetup, DiscoverSharedPublicStart } from './typ
export type {
ObservabilityLogsAIAssistantFeatureRenderDeps,
ObservabilityLogsAIAssistantFeature,
+ SecuritySolutionCellRendererFeature,
+ SecuritySolutionAppWrapperFeature,
DiscoverFeature,
-} from './services/discover_features';
+ DiscoverFeaturesServiceSetup,
+ DiscoverFeaturesServiceStart,
+} from './services/discover_features/types';
diff --git a/src/plugins/discover_shared/public/services/discover_features/types.ts b/src/plugins/discover_shared/public/services/discover_features/types.ts
index cdf78b3335507..a40a4f87a3eb9 100644
--- a/src/plugins/discover_shared/public/services/discover_features/types.ts
+++ b/src/plugins/discover_shared/public/services/discover_features/types.ts
@@ -7,7 +7,9 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-import { DataTableRecord } from '@kbn/discover-utils';
+import type { DataTableRecord } from '@kbn/discover-utils';
+import type { FunctionComponent, PropsWithChildren } from 'react';
+import type { DataGridCellValueElementProps } from '@kbn/unified-data-table';
import { FeaturesRegistry } from '../../../common';
/**
@@ -38,8 +40,31 @@ export interface ObservabilityCreateSLOFeature {
}) => React.ReactNode;
}
+/** **************** Security Solution ****************/
+
+export interface SecuritySolutionCellRendererFeature {
+ id: 'security-solution-cell-renderer';
+ getRenderer: () => Promise<
+ (fieldName: string) => FunctionComponent | undefined
+ >;
+}
+
+export interface SecuritySolutionAppWrapperFeature {
+ id: 'security-solution-app-wrapper';
+ getWrapper: () => Promise<() => FunctionComponent>>;
+}
+
+export type SecuritySolutionFeature =
+ | SecuritySolutionCellRendererFeature
+ | SecuritySolutionAppWrapperFeature;
+
+/** ****************************************************************************************/
+
// This should be a union of all the available client features.
-export type DiscoverFeature = ObservabilityLogsAIAssistantFeature | ObservabilityCreateSLOFeature;
+export type DiscoverFeature =
+ | ObservabilityLogsAIAssistantFeature
+ | ObservabilityCreateSLOFeature
+ | SecuritySolutionFeature;
/**
* Service types
diff --git a/src/plugins/discover_shared/tsconfig.json b/src/plugins/discover_shared/tsconfig.json
index 9d2b07eb7aae9..d8bda5214c747 100644
--- a/src/plugins/discover_shared/tsconfig.json
+++ b/src/plugins/discover_shared/tsconfig.json
@@ -13,5 +13,6 @@
"kbn_references": [
"@kbn/discover-utils",
"@kbn/core",
+ "@kbn/unified-data-table",
]
}
diff --git a/src/plugins/es_ui_shared/static/forms/docs/examples/dynamic_fields.mdx b/src/plugins/es_ui_shared/static/forms/docs/examples/dynamic_fields.mdx
index 82516423424f6..e48e5192f189e 100644
--- a/src/plugins/es_ui_shared/static/forms/docs/examples/dynamic_fields.mdx
+++ b/src/plugins/es_ui_shared/static/forms/docs/examples/dynamic_fields.mdx
@@ -65,7 +65,7 @@ export const DynamicFields = () => {
onClick={() => removeItem(item.id)}
iconType="minusInCircle"
aria-label="Remove item"
- style={{ marginTop: '28px' }}
+ css={{ marginTop: '28px' }}
/>
@@ -155,7 +155,7 @@ export const DynamicFieldsValidation = () => {
onClick={() => removeItem(item.id)}
iconType="minusInCircle"
aria-label="Remove item"
- style={{ marginTop: '28px' }}
+ css={{ marginTop: '28px' }}
/>
@@ -218,7 +218,7 @@ export const DynamicFieldsReorder = () => {
return (
-
+
@@ -245,7 +245,7 @@ export const DynamicFieldsReorder = () => {
onClick={() => removeItem(item.id)}
iconType="minusInCircle"
aria-label="Remove item"
- style={{ marginTop: '28px' }}
+ css={{ marginTop: '28px' }}
/>
@@ -273,4 +273,4 @@ export const DynamicFieldsReorder = () => {
);
};
-```
\ No newline at end of file
+```
diff --git a/src/plugins/es_ui_shared/static/forms/docs/examples/fields_composition.mdx b/src/plugins/es_ui_shared/static/forms/docs/examples/fields_composition.mdx
index 7e7cce5e81332..0851440400814 100644
--- a/src/plugins/es_ui_shared/static/forms/docs/examples/fields_composition.mdx
+++ b/src/plugins/es_ui_shared/static/forms/docs/examples/fields_composition.mdx
@@ -7,8 +7,8 @@ tags: ['forms', 'kibana', 'dev']
date: 2021-04-14
---
-If your form does not have a fix set of fields (single interface) and you need to add/remove fields dynamically, you can leverage the power of field composition with the form lib. It let's you swap fields in your form whenever needed. Any field that **is not in the DOM** is automatically cleared when unmounting and its value won't be returned in the form data.
-If you _do_ need to keep a field value, but hide the field in the UI, then you need to use CSS (`
...
`)
+If your form does not have a fix set of fields (single interface) and you need to add/remove fields dynamically, you can leverage the power of field composition with the form lib. It let's you swap fields in your form whenever needed. Any field that **is not in the DOM** is automatically cleared when unmounting and its value won't be returned in the form data.
+If you _do_ need to keep a field value, but hide the field in the UI, then you need to use CSS (`
...
`)
Imagine you're building an app that lets people buy a car online. You want to build a form that lets the user select the model of the car (`sedan`, `golf cart`, `clown mobile`), and based on their selection you'll show a different form for configuring the selected model's options.
diff --git a/src/plugins/es_ui_shared/static/forms/docs/examples/serializers_deserializers.mdx b/src/plugins/es_ui_shared/static/forms/docs/examples/serializers_deserializers.mdx
index dd3b402e85e3f..3ab849d262db2 100644
--- a/src/plugins/es_ui_shared/static/forms/docs/examples/serializers_deserializers.mdx
+++ b/src/plugins/es_ui_shared/static/forms/docs/examples/serializers_deserializers.mdx
@@ -90,7 +90,7 @@ export const SerializersAndDeserializers = () => {
{/* We don't remove it from the DOM as we would lose the value entered in the field. */}
-
+
diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx
index f920eb91ea3cc..b777ecd4a85b8 100644
--- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx
+++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx
@@ -43,7 +43,7 @@ const percentageOptions = [
{
value: 'percentage_config_1',
inputDisplay: (
-
+
Percentage 1
),
@@ -51,7 +51,7 @@ const percentageOptions = [
{
value: 'percentage_config_2',
inputDisplay: (
-
+
Percentage 2
),
@@ -59,7 +59,7 @@ const percentageOptions = [
{
value: 'percentage_config_3',
inputDisplay: (
-
+
Percentage 3
),
@@ -70,7 +70,7 @@ const valueOptions = [
{
value: 'value_config_1',
inputDisplay: (
-
+
Value 1
),
@@ -78,7 +78,7 @@ const valueOptions = [
{
value: 'value_config_2',
inputDisplay: (
-
+
Value 2
),
@@ -86,7 +86,7 @@ const valueOptions = [
{
value: 'value_config_3',
inputDisplay: (
-
+
Value 3
),
@@ -188,7 +188,7 @@ const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => {
component={TextField}
componentProps={{
euiFieldProps: {
- style: {
+ css: {
maxWidth: '180px',
},
},
@@ -303,7 +303,7 @@ const percentageOptions = [
{
value: 'percentage_config_1',
inputDisplay: (
-
+
Percentage 1
),
@@ -311,7 +311,7 @@ const percentageOptions = [
{
value: 'percentage_config_2',
inputDisplay: (
-
+
Percentage 2
),
@@ -319,7 +319,7 @@ const percentageOptions = [
{
value: 'percentage_config_3',
inputDisplay: (
-
+
Percentage 3
),
@@ -330,7 +330,7 @@ const valueOptions = [
{
value: 'value_config_1',
inputDisplay: (
-
+
Value 1
),
@@ -338,7 +338,7 @@ const valueOptions = [
{
value: 'value_config_2',
inputDisplay: (
-
+
Value 2
),
@@ -346,7 +346,7 @@ const valueOptions = [
{
value: 'value_config_3',
inputDisplay: (
-
+
Value 3
),
@@ -448,7 +448,7 @@ const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => {
component={TextField}
componentProps={{
euiFieldProps: {
- style: {
+ css: {
maxWidth: '180px',
},
},
diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx
index 83beef1fc8387..098919fb96c2a 100644
--- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx
+++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx
@@ -46,7 +46,7 @@ const percentageOptions = [
{
value: 'percentage_config_1',
inputDisplay: (
-
+