diff --git a/api_docs/alerting.json b/api_docs/alerting.json index 3aa2165f89af5..0001f7dafabd7 100644 --- a/api_docs/alerting.json +++ b/api_docs/alerting.json @@ -955,7 +955,7 @@ "description": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 112 + "lineNumber": 94 } } ], @@ -963,13 +963,13 @@ "returnComment": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 104 + "lineNumber": 86 } } ], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 103 + "lineNumber": 85 }, "initialIsOpen": false }, @@ -988,7 +988,7 @@ "description": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 124 + "lineNumber": 106 }, "signature": [ "() => Set<", @@ -1044,7 +1044,7 @@ "description": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 125 + "lineNumber": 107 } } ], @@ -1052,7 +1052,7 @@ "returnComment": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 125 + "lineNumber": 107 } }, { @@ -1063,7 +1063,7 @@ "description": [], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 126 + "lineNumber": 108 }, "signature": [ "() => Promise<", @@ -1080,7 +1080,7 @@ ], "source": { "path": "x-pack/plugins/alerting/server/plugin.ts", - "lineNumber": 123 + "lineNumber": 105 }, "initialIsOpen": false } @@ -2991,32 +2991,32 @@ "initialIsOpen": false }, { + "id": "def-common.DefaultActionGroupId", + "type": "Type", + "label": "DefaultActionGroupId", "tags": [], - "id": "def-common.BASE_ALERT_API_PATH", - "type": "string", - "label": "BASE_ALERT_API_PATH", "description": [], "source": { - "path": "x-pack/plugins/alerting/common/index.ts", - "lineNumber": 27 + "path": "x-pack/plugins/alerting/common/builtin_action_groups.ts", + "lineNumber": 11 }, "signature": [ - "\"/api/alerts\"" + "\"default\"" ], "initialIsOpen": false }, { - "id": "def-common.DefaultActionGroupId", - "type": "Type", - "label": "DefaultActionGroupId", "tags": [], + "id": "def-common.LEGACY_BASE_ALERT_API_PATH", + "type": "string", + "label": "LEGACY_BASE_ALERT_API_PATH", "description": [], "source": { - "path": "x-pack/plugins/alerting/common/builtin_action_groups.ts", - "lineNumber": 11 + "path": "x-pack/plugins/alerting/common/index.ts", + "lineNumber": 27 }, "signature": [ - "\"default\"" + "\"/api/alerts\"" ], "initialIsOpen": false }, diff --git a/x-pack/examples/alerting_example/public/components/view_alert.tsx b/x-pack/examples/alerting_example/public/components/view_alert.tsx index 12f0eb6f35701..ce2a3f0b40967 100644 --- a/x-pack/examples/alerting_example/public/components/view_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_alert.tsx @@ -21,8 +21,12 @@ import { import { withRouter, RouteComponentProps } from 'react-router-dom'; import { CoreStart } from 'kibana/public'; import { isEmpty } from 'lodash'; -import { Alert, AlertTaskState, BASE_ALERT_API_PATH } from '../../../../plugins/alerting/common'; import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; +import { + Alert, + AlertTaskState, + LEGACY_BASE_ALERT_API_PATH, +} from '../../../../plugins/alerting/common'; type Props = RouteComponentProps & { http: CoreStart['http']; @@ -34,10 +38,10 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => { useEffect(() => { if (!alert) { - http.get(`${BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); + http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); } if (!alertState) { - http.get(`${BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); + http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); } }, [alert, alertState, http, id]); diff --git a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx index 1d8bf4e3a71dd..800c351e569f0 100644 --- a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx @@ -23,8 +23,12 @@ import { import { withRouter, RouteComponentProps } from 'react-router-dom'; import { CoreStart } from 'kibana/public'; import { isEmpty } from 'lodash'; -import { Alert, AlertTaskState, BASE_ALERT_API_PATH } from '../../../../plugins/alerting/common'; import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants'; +import { + Alert, + AlertTaskState, + LEGACY_BASE_ALERT_API_PATH, +} from '../../../../plugins/alerting/common'; type Props = RouteComponentProps & { http: CoreStart['http']; @@ -40,10 +44,10 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => { useEffect(() => { if (!alert) { - http.get(`${BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); + http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert); } if (!alertState) { - http.get(`${BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); + http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`).then(setAlertState); } }, [alert, alertState, http, id]); diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index ff1540090a357..5acc87c64eab6 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -24,5 +24,5 @@ export interface AlertingFrameworkHealth { alertingFrameworkHeath: AlertsHealth; } -export const BASE_ALERT_API_PATH = '/api/alerts'; +export const LEGACY_BASE_ALERT_API_PATH = '/api/alerts'; export const ALERTS_FEATURE_ID = 'alerts'; diff --git a/x-pack/plugins/alerting/public/alert_api.ts b/x-pack/plugins/alerting/public/alert_api.ts index 6eb2e29a7e8e5..d1213c80b95be 100644 --- a/x-pack/plugins/alerting/public/alert_api.ts +++ b/x-pack/plugins/alerting/public/alert_api.ts @@ -7,11 +7,11 @@ import { HttpSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; -import { BASE_ALERT_API_PATH } from '../common'; +import { LEGACY_BASE_ALERT_API_PATH } from '../common'; import type { Alert, AlertType } from '../common'; export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/list_alert_types`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`); } export async function loadAlertType({ @@ -22,7 +22,7 @@ export async function loadAlertType({ id: AlertType['id']; }): Promise { const maybeAlertType = ((await http.get( - `${BASE_ALERT_API_PATH}/list_alert_types` + `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types` )) as AlertType[]).find((type) => type.id === id); if (!maybeAlertType) { throw new Error( @@ -44,5 +44,5 @@ export async function loadAlert({ http: HttpSetup; alertId: string; }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/alert/${alertId}`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alertId}`); } diff --git a/x-pack/plugins/alerting/server/routes/aggregate.ts b/x-pack/plugins/alerting/server/routes/aggregate.ts new file mode 100644 index 0000000000000..3538175a7296c --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/aggregate.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { renameKeys } from './lib/rename_keys'; +import { FindOptions } from '../alerts_client'; + +// config definition +const querySchema = schema.object({ + search: schema.maybe(schema.string()), + default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { + defaultValue: 'OR', + }), + search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), + has_reference: schema.maybe( + // use nullable as maybe is currently broken + // in config-schema + schema.nullable( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ) + ), + filter: schema.maybe(schema.string()), +}); + +export const aggregateAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/_aggregate`, + validate: { + query: querySchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + + const query = req.query; + const renameMap = { + default_search_operator: 'defaultSearchOperator', + has_reference: 'hasReference', + search: 'search', + filter: 'filter', + }; + + const options = renameKeys>(renameMap, query); + + if (query.search_fields) { + options.searchFields = Array.isArray(query.search_fields) + ? query.search_fields + : [query.search_fields]; + } + + const aggregateResult = await alertsClient.aggregate({ options }); + return res.ok({ + body: aggregateResult, + }); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/create.ts b/x-pack/plugins/alerting/server/routes/create.ts new file mode 100644 index 0000000000000..660b5389d8f25 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/create.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { 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'; +import { handleDisabledApiKeysError } from './lib/error_handler'; +import { + Alert, + AlertNotifyWhenType, + AlertTypeParams, + LEGACY_BASE_ALERT_API_PATH, + validateNotifyWhenType, +} from '../types'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +export const bodySchema = schema.object({ + name: schema.string(), + alertTypeId: schema.string(), + enabled: schema.boolean({ defaultValue: true }), + consumer: schema.string(), + tags: schema.arrayOf(schema.string(), { defaultValue: [] }), + throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), + params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + schedule: schema.object({ + interval: schema.string({ validate: validateDurationSchema }), + }), + actions: schema.arrayOf( + schema.object({ + group: schema.string(), + id: schema.string(), + actionTypeId: schema.maybe(schema.string()), + params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + }), + { defaultValue: [] } + ), + notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), +}); + +export const createAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id?}`, + validate: { + params: schema.maybe( + schema.object({ + id: schema.maybe(schema.string()), + }) + ), + body: bodySchema, + }, + }, + handleDisabledApiKeysError( + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const alert = req.body; + const params = req.params; + const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as AlertNotifyWhenType) : null; + try { + const alertRes: Alert = await alertsClient.create({ + data: { ...alert, notifyWhen }, + options: { id: params?.id }, + }); + return res.ok({ + body: alertRes, + }); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/delete.ts b/x-pack/plugins/alerting/server/routes/delete.ts new file mode 100644 index 0000000000000..6302a9cafd0db --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/delete.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const deleteAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.delete( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + await alertsClient.delete({ id }); + return res.noContent(); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/disable.ts b/x-pack/plugins/alerting/server/routes/disable.ts new file mode 100644 index 0000000000000..0a596afe55478 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/disable.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const disableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_disable`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + try { + await alertsClient.disable({ id }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/enable.ts b/x-pack/plugins/alerting/server/routes/enable.ts new file mode 100644 index 0000000000000..c1b3724813e4c --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/enable.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { handleDisabledApiKeysError } from './lib/error_handler'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const enableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_enable`, + validate: { + params: paramSchema, + }, + }, + handleDisabledApiKeysError( + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + try { + await alertsClient.enable({ id }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/find.ts b/x-pack/plugins/alerting/server/routes/find.ts new file mode 100644 index 0000000000000..88b168a956efa --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/find.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; + +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { renameKeys } from './lib/rename_keys'; +import { FindOptions } from '../alerts_client'; + +// config definition +const querySchema = schema.object({ + per_page: schema.number({ defaultValue: 10, min: 0 }), + page: schema.number({ defaultValue: 1, min: 1 }), + search: schema.maybe(schema.string()), + default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { + defaultValue: 'OR', + }), + search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), + sort_field: schema.maybe(schema.string()), + sort_order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), + has_reference: schema.maybe( + // use nullable as maybe is currently broken + // in config-schema + schema.nullable( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ) + ), + fields: schema.maybe(schema.arrayOf(schema.string())), + filter: schema.maybe(schema.string()), +}); + +export const findAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/_find`, + validate: { + query: querySchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + + const query = req.query; + const renameMap = { + default_search_operator: 'defaultSearchOperator', + fields: 'fields', + has_reference: 'hasReference', + page: 'page', + per_page: 'perPage', + search: 'search', + sort_field: 'sortField', + sort_order: 'sortOrder', + filter: 'filter', + }; + + const options = renameKeys>(renameMap, query); + + if (query.search_fields) { + options.searchFields = Array.isArray(query.search_fields) + ? query.search_fields + : [query.search_fields]; + } + + const findResult = await alertsClient.find({ options }); + return res.ok({ + body: findResult, + }); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/get.ts b/x-pack/plugins/alerting/server/routes/get.ts new file mode 100644 index 0000000000000..107e537228e35 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/get.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import type { AlertingRouter } from '../types'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const getAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + return res.ok({ + body: await alertsClient.get({ id }), + }); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/get_alert_instance_summary.ts b/x-pack/plugins/alerting/server/routes/get_alert_instance_summary.ts new file mode 100644 index 0000000000000..9ae8774a6f809 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/get_alert_instance_summary.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +const querySchema = schema.object({ + dateStart: schema.maybe(schema.string()), +}); + +export const getAlertInstanceSummaryRoute = ( + router: AlertingRouter, + licenseState: ILicenseState +) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`, + validate: { + params: paramSchema, + query: querySchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + const { dateStart } = req.query; + const summary = await alertsClient.getAlertInstanceSummary({ id, dateStart }); + return res.ok({ body: summary }); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/get_alert_state.ts b/x-pack/plugins/alerting/server/routes/get_alert_state.ts new file mode 100644 index 0000000000000..b3b2d1a5ae1ec --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/get_alert_state.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const getAlertStateRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/state`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + const state = await alertsClient.getAlertState({ id }); + return state ? res.ok({ body: state }) : res.noContent(); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/aggregate.ts b/x-pack/plugins/alerting/server/routes/legacy/aggregate.ts index dc54176043de0..91189fdf3d0a6 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/aggregate.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/aggregate.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { renameKeys } from './../lib/rename_keys'; import { FindOptions } from '../../alerts_client'; @@ -36,7 +36,7 @@ const querySchema = schema.object({ export const aggregateAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.get( { - path: `${BASE_ALERT_API_PATH}/_aggregate`, + path: `${LEGACY_BASE_ALERT_API_PATH}/_aggregate`, validate: { query: querySchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.ts b/x-pack/plugins/alerting/server/routes/legacy/create.ts index 2f6a258344cdd..9b9dc9b51a1d7 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/create.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/create.ts @@ -15,7 +15,7 @@ import { Alert, AlertNotifyWhenType, AlertTypeParams, - BASE_ALERT_API_PATH, + LEGACY_BASE_ALERT_API_PATH, validateNotifyWhenType, } from '../../types'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; @@ -46,7 +46,7 @@ export const bodySchema = schema.object({ export const createAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id?}`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id?}`, validate: { params: schema.maybe( schema.object({ diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.ts index e4a551d0b6bf6..650126be4499d 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/delete.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; const paramSchema = schema.object({ id: schema.string(), @@ -18,7 +18,7 @@ const paramSchema = schema.object({ export const deleteAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.delete( { - path: `${BASE_ALERT_API_PATH}/alert/{id}`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.ts index 6b95e391a6963..140e0492fbaab 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/disable.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; const paramSchema = schema.object({ @@ -19,7 +19,7 @@ const paramSchema = schema.object({ export const disableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_disable`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_disable`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.ts index 28c4ead2d5ef4..fcf9ceb8a058b 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/enable.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { handleDisabledApiKeysError } from './../lib/error_handler'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; @@ -20,7 +20,7 @@ const paramSchema = schema.object({ export const enableAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_enable`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_enable`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.ts b/x-pack/plugins/alerting/server/routes/legacy/find.ts index 0f6d8adaa9881..1d54df53d883a 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/find.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/find.ts @@ -10,7 +10,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { renameKeys } from './../lib/rename_keys'; import { FindOptions } from '../../alerts_client'; @@ -42,7 +42,7 @@ const querySchema = schema.object({ export const findAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.get( { - path: `${BASE_ALERT_API_PATH}/_find`, + path: `${LEGACY_BASE_ALERT_API_PATH}/_find`, validate: { query: querySchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.ts b/x-pack/plugins/alerting/server/routes/legacy/get.ts index 3dc7283727b92..cf63a4387a93e 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get.ts @@ -8,7 +8,7 @@ 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 { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import type { AlertingRouter } from '../../types'; const paramSchema = schema.object({ @@ -18,7 +18,7 @@ const paramSchema = schema.object({ export const getAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.get( { - path: `${BASE_ALERT_API_PATH}/alert/{id}`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts index 18e8bf9fb32cc..00c96197f6f9b 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; const paramSchema = schema.object({ id: schema.string(), @@ -25,7 +25,7 @@ export const getAlertInstanceSummaryRoute = ( ) => { router.get( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`, validate: { params: paramSchema, query: querySchema, diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts index e0150957d7d1e..5e7cbfbe6eb95 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; const paramSchema = schema.object({ id: schema.string(), @@ -18,7 +18,7 @@ const paramSchema = schema.object({ export const getAlertStateRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.get( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/state`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/state`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts index e38bab5504017..da41cc487228c 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts @@ -8,12 +8,12 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; export const listAlertTypesRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.get( { - path: `${BASE_ALERT_API_PATH}/list_alert_types`, + path: `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`, validate: {}, }, router.handleLegacyErrors(async function (context, req, res) { diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts index 10a913780e3ef..643aeb97084a8 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; const paramSchema = schema.object({ @@ -19,7 +19,7 @@ const paramSchema = schema.object({ export const muteAllAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_mute_all`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_mute_all`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts index 1f38294729619..2b35f59c7fce1 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { renameKeys } from './../lib/rename_keys'; import { MuteOptions } from '../../alerts_client'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; @@ -22,7 +22,7 @@ const paramSchema = schema.object({ export const muteAlertInstanceRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts index b29c04acf7c1a..1259428be3329 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; const paramSchema = schema.object({ @@ -19,7 +19,7 @@ const paramSchema = schema.object({ export const unmuteAllAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_unmute_all`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_unmute_all`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts index 461c8904876ab..25f5aa654bde1 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; const paramSchema = schema.object({ @@ -20,7 +20,7 @@ const paramSchema = schema.object({ export const unmuteAlertInstanceRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.ts b/x-pack/plugins/alerting/server/routes/legacy/update.ts index 4f57c37a6c3e8..8e593a47e61a1 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/update.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/update.ts @@ -11,7 +11,7 @@ import { ILicenseState } from '../../lib/license_state'; import { verifyApiAccess } from '../../lib/license_api_access'; import { validateDurationSchema } from '../../lib'; import { handleDisabledApiKeysError } from './../lib/error_handler'; -import { AlertNotifyWhenType, BASE_ALERT_API_PATH, validateNotifyWhenType } from '../../../common'; +import { AlertNotifyWhenType, LEGACY_BASE_ALERT_API_PATH, validateNotifyWhenType } from '../../../common'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; const paramSchema = schema.object({ @@ -41,7 +41,7 @@ const bodySchema = schema.object({ export const updateAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.put( { - path: `${BASE_ALERT_API_PATH}/alert/{id}`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, validate: { body: bodySchema, params: paramSchema, diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts index c99dc8656526d..a4da2538b0bf9 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts @@ -9,7 +9,7 @@ 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'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; import { handleDisabledApiKeysError } from './../lib/error_handler'; import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled'; @@ -20,7 +20,7 @@ const paramSchema = schema.object({ export const updateApiKeyRoute = (router: AlertingRouter, licenseState: ILicenseState) => { router.post( { - path: `${BASE_ALERT_API_PATH}/alert/{id}/_update_api_key`, + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_update_api_key`, validate: { params: paramSchema, }, diff --git a/x-pack/plugins/alerting/server/routes/list_alert_types.ts b/x-pack/plugins/alerting/server/routes/list_alert_types.ts new file mode 100644 index 0000000000000..31661cb481422 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/list_alert_types.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; + +export const listAlertTypesRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.get( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`, + validate: {}, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + return res.ok({ + body: Array.from(await context.alerting.getAlertsClient().listAlertTypes()), + }); + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/mute_all.ts b/x-pack/plugins/alerting/server/routes/mute_all.ts new file mode 100644 index 0000000000000..07b0f95aaf86e --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/mute_all.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const muteAllAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_mute_all`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + try { + await alertsClient.muteAll({ id }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/mute_instance.ts b/x-pack/plugins/alerting/server/routes/mute_instance.ts new file mode 100644 index 0000000000000..4a69f8c6087f5 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/mute_instance.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { renameKeys } from './lib/rename_keys'; +import { MuteOptions } from '../alerts_client'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + alert_id: schema.string(), + alert_instance_id: schema.string(), +}); + +export const muteAlertInstanceRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + + const renameMap = { + alert_id: 'alertId', + alert_instance_id: 'alertInstanceId', + }; + + const renamedQuery = renameKeys>(renameMap, req.params); + try { + await alertsClient.muteInstance(renamedQuery); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/unmute_all.ts b/x-pack/plugins/alerting/server/routes/unmute_all.ts new file mode 100644 index 0000000000000..7a5168835127b --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/unmute_all.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const unmuteAllAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_unmute_all`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + try { + await alertsClient.unmuteAll({ id }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/unmute_instance.ts new file mode 100644 index 0000000000000..604e8576f10f4 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/unmute_instance.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + alertId: schema.string(), + alertInstanceId: schema.string(), +}); + +export const unmuteAlertInstanceRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`, + validate: { + params: paramSchema, + }, + }, + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { alertId, alertInstanceId } = req.params; + try { + await alertsClient.unmuteInstance({ alertId, alertInstanceId }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/update.ts b/x-pack/plugins/alerting/server/routes/update.ts new file mode 100644 index 0000000000000..96b76b3c2f115 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/update.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { 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'; +import { handleDisabledApiKeysError } from './lib/error_handler'; +import { AlertNotifyWhenType, LEGACY_BASE_ALERT_API_PATH, validateNotifyWhenType } from '../../common'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +const bodySchema = schema.object({ + name: schema.string(), + tags: schema.arrayOf(schema.string(), { defaultValue: [] }), + schedule: schema.object({ + interval: schema.string({ validate: validateDurationSchema }), + }), + throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), + params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + actions: schema.arrayOf( + schema.object({ + group: schema.string(), + id: schema.string(), + params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), + actionTypeId: schema.maybe(schema.string()), + }), + { defaultValue: [] } + ), + notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), +}); + +export const updateAlertRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.put( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, + validate: { + body: bodySchema, + params: paramSchema, + }, + }, + handleDisabledApiKeysError( + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + const { name, actions, params, schedule, tags, throttle, notifyWhen } = req.body; + try { + const alertRes = await alertsClient.update({ + id, + data: { + name, + actions, + params, + schedule, + tags, + throttle, + notifyWhen: notifyWhen as AlertNotifyWhenType, + }, + }); + return res.ok({ + body: alertRes, + }); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/update_api_key.ts b/x-pack/plugins/alerting/server/routes/update_api_key.ts new file mode 100644 index 0000000000000..7456fb0cb58ba --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/update_api_key.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import type { AlertingRouter } from '../types'; +import { ILicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../common'; +import { handleDisabledApiKeysError } from './lib/error_handler'; +import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled'; + +const paramSchema = schema.object({ + id: schema.string(), +}); + +export const updateApiKeyRoute = (router: AlertingRouter, licenseState: ILicenseState) => { + router.post( + { + path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_update_api_key`, + validate: { + params: paramSchema, + }, + }, + handleDisabledApiKeysError( + router.handleLegacyErrors(async function (context, req, res) { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + try { + await alertsClient.updateApiKey({ id }); + return res.noContent(); + } catch (e) { + if (e instanceof AlertTypeDisabledError) { + return e.sendResponse(res); + } + throw e; + } + }) + ) + ); +}; diff --git a/x-pack/plugins/monitoring/public/alerts/configuration.tsx b/x-pack/plugins/monitoring/public/alerts/configuration.tsx index 59411d431d83a..5416095671d71 100644 --- a/x-pack/plugins/monitoring/public/alerts/configuration.tsx +++ b/x-pack/plugins/monitoring/public/alerts/configuration.tsx @@ -12,7 +12,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSwitch } from '@elastic/eui'; import { CommonAlert } from '../../common/types/alerts'; import { Legacy } from '../legacy_shims'; import { hideBottomBar, showBottomBar } from '../lib/setup_mode'; -import { BASE_ALERT_API_PATH } from '../../../alerting/common'; +import { LEGACY_BASE_ALERT_API_PATH } from '../../../alerting/common'; interface Props { alert: CommonAlert; @@ -28,7 +28,7 @@ export const AlertConfiguration: React.FC = (props: Props) => { async function disableAlert() { setIsSaving(true); try { - await Legacy.shims.http.post(`${BASE_ALERT_API_PATH}/alert/${alert.id}/_disable`); + await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_disable`); } catch (err) { Legacy.shims.toastNotifications.addDanger({ title: i18n.translate('xpack.monitoring.alerts.panel.disableAlert.errorTitle', { @@ -42,7 +42,7 @@ export const AlertConfiguration: React.FC = (props: Props) => { async function enableAlert() { setIsSaving(true); try { - await Legacy.shims.http.post(`${BASE_ALERT_API_PATH}/alert/${alert.id}/_enable`); + await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_enable`); } catch (err) { Legacy.shims.toastNotifications.addDanger({ title: i18n.translate('xpack.monitoring.alerts.panel.enableAlert.errorTitle', { @@ -56,7 +56,7 @@ export const AlertConfiguration: React.FC = (props: Props) => { async function muteAlert() { setIsSaving(true); try { - await Legacy.shims.http.post(`${BASE_ALERT_API_PATH}/alert/${alert.id}/_mute_all`); + await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_mute_all`); } catch (err) { Legacy.shims.toastNotifications.addDanger({ title: i18n.translate('xpack.monitoring.alerts.panel.muteAlert.errorTitle', { @@ -70,7 +70,7 @@ export const AlertConfiguration: React.FC = (props: Props) => { async function unmuteAlert() { setIsSaving(true); try { - await Legacy.shims.http.post(`${BASE_ALERT_API_PATH}/alert/${alert.id}/_unmute_all`); + await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_unmute_all`); } catch (err) { Legacy.shims.toastNotifications.addDanger({ title: i18n.translate('xpack.monitoring.alerts.panel.ummuteAlert.errorTitle', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts index e5db5a45975af..fd311388faf04 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; -export { BASE_ALERT_API_PATH } from '../../../../alerting/common'; +export { LEGACY_BASE_ALERT_API_PATH } from '../../../../alerting/common'; export { BASE_ACTION_API_PATH } from '../../../../actions/common'; export type Section = 'connectors' | 'alerts'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.ts index e0ef7dbe08412..14c56eabe08ac 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api.ts @@ -11,7 +11,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { pick } from 'lodash'; import { alertStateSchema, AlertingFrameworkHealth } from '../../../../alerting/common'; -import { BASE_ALERT_API_PATH } from '../constants'; +import { LEGACY_BASE_ALERT_API_PATH } from '../constants'; import { Alert, AlertAggregations, @@ -22,7 +22,7 @@ import { } from '../../types'; export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/list_alert_types`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`); } export async function loadAlert({ @@ -32,7 +32,7 @@ export async function loadAlert({ http: HttpSetup; alertId: string; }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/alert/${alertId}`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alertId}`); } type EmptyHttpResponse = ''; @@ -44,7 +44,7 @@ export async function loadAlertState({ alertId: string; }): Promise { return await http - .get(`${BASE_ALERT_API_PATH}/alert/${alertId}/state`) + .get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alertId}/state`) .then((state: AlertTaskState | EmptyHttpResponse) => (state ? state : {})) .then((state: AlertTaskState) => { return pipe( @@ -63,7 +63,7 @@ export async function loadAlertInstanceSummary({ http: HttpSetup; alertId: string; }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/alert/${alertId}/_instance_summary`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alertId}/_instance_summary`); } export const mapFiltersToKql = ({ @@ -117,7 +117,7 @@ export async function loadAlerts({ data: Alert[]; }> { const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, alertStatusesFilter }); - return await http.get(`${BASE_ALERT_API_PATH}/_find`, { + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/_find`, { query: { page: page.index + 1, per_page: page.size, @@ -145,7 +145,7 @@ export async function loadAlertAggregations({ alertStatusesFilter?: string[]; }): Promise { const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, alertStatusesFilter }); - return await http.get(`${BASE_ALERT_API_PATH}/_aggregate`, { + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/_aggregate`, { query: { search_fields: searchText ? JSON.stringify(['name', 'tags']) : undefined, search: searchText, @@ -164,7 +164,7 @@ export async function deleteAlerts({ }): Promise<{ successes: string[]; errors: string[] }> { const successes: string[] = []; const errors: string[] = []; - await Promise.all(ids.map((id) => http.delete(`${BASE_ALERT_API_PATH}/alert/${id}`))).then( + await Promise.all(ids.map((id) => http.delete(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`))).then( function (fulfilled) { successes.push(...fulfilled); }, @@ -185,7 +185,7 @@ export async function createAlert({ 'createdBy' | 'updatedBy' | 'muteAll' | 'mutedInstanceIds' | 'executionStatus' >; }): Promise { - return await http.post(`${BASE_ALERT_API_PATH}/alert`, { + return await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert`, { body: JSON.stringify(alert), }); } @@ -202,7 +202,7 @@ export async function updateAlert({ >; id: string; }): Promise { - return await http.put(`${BASE_ALERT_API_PATH}/alert/${id}`, { + return await http.put(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`, { body: JSON.stringify( pick(alert, ['throttle', 'name', 'tags', 'schedule', 'params', 'actions', 'notifyWhen']) ), @@ -210,7 +210,7 @@ export async function updateAlert({ } export async function enableAlert({ id, http }: { id: string; http: HttpSetup }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/_enable`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/_enable`); } export async function enableAlerts({ @@ -224,7 +224,7 @@ export async function enableAlerts({ } export async function disableAlert({ id, http }: { id: string; http: HttpSetup }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/_disable`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/_disable`); } export async function disableAlerts({ @@ -246,7 +246,7 @@ export async function muteAlertInstance({ instanceId: string; http: HttpSetup; }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/alert_instance/${instanceId}/_mute`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/alert_instance/${instanceId}/_mute`); } export async function unmuteAlertInstance({ @@ -258,11 +258,11 @@ export async function unmuteAlertInstance({ instanceId: string; http: HttpSetup; }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/alert_instance/${instanceId}/_unmute`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/alert_instance/${instanceId}/_unmute`); } export async function muteAlert({ id, http }: { id: string; http: HttpSetup }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/_mute_all`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/_mute_all`); } export async function muteAlerts({ ids, http }: { ids: string[]; http: HttpSetup }): Promise { @@ -270,7 +270,7 @@ export async function muteAlerts({ ids, http }: { ids: string[]; http: HttpSetup } export async function unmuteAlert({ id, http }: { id: string; http: HttpSetup }): Promise { - await http.post(`${BASE_ALERT_API_PATH}/alert/${id}/_unmute_all`); + await http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/_unmute_all`); } export async function unmuteAlerts({ @@ -288,5 +288,5 @@ export async function alertingFrameworkHealth({ }: { http: HttpSetup; }): Promise { - return await http.get(`${BASE_ALERT_API_PATH}/_health`); + return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/_health`); }