diff --git a/x-pack/plugins/alerting/common/rule.ts b/x-pack/plugins/alerting/common/rule.ts index fbc8e8d686419..28093ff7a5a65 100644 --- a/x-pack/plugins/alerting/common/rule.ts +++ b/x-pack/plugins/alerting/common/rule.ts @@ -141,6 +141,7 @@ export interface RuleSystemAction { actionTypeId: string; params: RuleActionParams; type: typeof RuleActionTypes.SYSTEM; + useAlertDataForTemplate?: boolean; } export type RuleAction = RuleDefaultAction | RuleSystemAction; diff --git a/x-pack/plugins/alerting/server/routes/clone_rule.ts b/x-pack/plugins/alerting/server/routes/clone_rule.ts index fa775e626d903..d2cc49d637715 100644 --- a/x-pack/plugins/alerting/server/routes/clone_rule.ts +++ b/x-pack/plugins/alerting/server/routes/clone_rule.ts @@ -8,26 +8,21 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; import { ILicenseState, RuleTypeDisabledError } from '../lib'; -import { - verifyAccessAndContext, - RewriteResponseCase, - handleDisabledApiKeysError, - rewriteRuleLastRun, - rewriteActionsRes, -} from './lib'; +import { verifyAccessAndContext, handleDisabledApiKeysError, rewriteRuleLastRun } from './lib'; import { RuleTypeParams, AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH, PartialRule, } from '../types'; +import { transformRuleActions } from './rule/transforms'; const paramSchema = schema.object({ id: schema.string(), newId: schema.maybe(schema.string()), }); -const rewriteBodyRes: RewriteResponseCase> = ({ +const rewriteBodyRes = ({ actions, alertTypeId, scheduledTaskId, @@ -46,7 +41,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ lastRun, nextRun, ...rest -}) => ({ +}: PartialRule) => ({ ...rest, api_key_owner: apiKeyOwner, created_by: createdBy, @@ -71,7 +66,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ : {}), ...(actions ? { - actions: rewriteActionsRes(actions), + actions: transformRuleActions(actions), } : {}), ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), diff --git a/x-pack/plugins/alerting/server/routes/find_rules.ts b/x-pack/plugins/alerting/server/routes/find_rules.ts index 1eab92db82383..711baa3108f35 100644 --- a/x-pack/plugins/alerting/server/routes/find_rules.ts +++ b/x-pack/plugins/alerting/server/routes/find_rules.ts @@ -10,12 +10,7 @@ import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { schema } from '@kbn/config-schema'; import { ILicenseState } from '../lib'; import { FindOptions, FindResult } from '../rules_client'; -import { - RewriteRequestCase, - RewriteResponseCase, - verifyAccessAndContext, - rewriteRule, -} from './lib'; +import { RewriteRequestCase, verifyAccessAndContext, rewriteRule } from './lib'; import { RuleTypeParams, AlertingRequestHandlerContext, @@ -69,11 +64,7 @@ const rewriteQueryReq: RewriteRequestCase = ({ ...(hasReference ? { hasReference } : {}), ...(searchFields ? { searchFields } : {}), }); -const rewriteBodyRes: RewriteResponseCase> = ({ - perPage, - data, - ...restOfResult -}) => { +const rewriteBodyRes = ({ perPage, data, ...restOfResult }: FindResult) => { return { ...restOfResult, per_page: perPage, diff --git a/x-pack/plugins/alerting/server/routes/get_rule.ts b/x-pack/plugins/alerting/server/routes/get_rule.ts index bc7983f6acdf1..1e3d1911cfca3 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule.ts @@ -9,12 +9,7 @@ import { omit } from 'lodash'; import { schema } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; import { ILicenseState } from '../lib'; -import { - verifyAccessAndContext, - RewriteResponseCase, - rewriteRuleLastRun, - rewriteActionsRes, -} from './lib'; +import { verifyAccessAndContext, rewriteRuleLastRun } from './lib'; import { RuleTypeParams, AlertingRequestHandlerContext, @@ -22,12 +17,13 @@ import { INTERNAL_BASE_ALERTING_API_PATH, SanitizedRule, } from '../types'; +import { transformRuleActions } from './rule/transforms'; const paramSchema = schema.object({ id: schema.string(), }); -const rewriteBodyRes: RewriteResponseCase> = ({ +const rewriteBodyRes = ({ alertTypeId, createdBy, updatedBy, @@ -47,7 +43,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ nextRun, viewInAppRelativeUrl, ...rest -}) => ({ +}: SanitizedRule) => ({ ...rest, rule_type_id: alertTypeId, created_by: createdBy, @@ -66,7 +62,7 @@ const rewriteBodyRes: RewriteResponseCase> = ({ last_execution_date: executionStatus.lastExecutionDate, last_duration: executionStatus.lastDuration, }, - actions: rewriteActionsRes(actions), + actions: transformRuleActions(actions), ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), ...(nextRun ? { next_run: nextRun } : {}), ...(viewInAppRelativeUrl ? { view_in_app_relative_url: viewInAppRelativeUrl } : {}), diff --git a/x-pack/plugins/alerting/server/routes/lib/index.ts b/x-pack/plugins/alerting/server/routes/lib/index.ts index 790436109f3e8..825753cf28be0 100644 --- a/x-pack/plugins/alerting/server/routes/lib/index.ts +++ b/x-pack/plugins/alerting/server/routes/lib/index.ts @@ -18,11 +18,7 @@ export type { } from './rewrite_request_case'; export { verifyAccessAndContext } from './verify_access_and_context'; export { countUsageOfPredefinedIds } from './count_usage_of_predefined_ids'; -export { - rewriteActionsReq, - rewriteActionsRes, - rewriteActionsReqWithSystemActions, -} from './rewrite_actions'; +export { rewriteActionsReq } from './rewrite_actions'; export { actionsSchema } from './actions_schema'; export { rewriteRule, rewriteRuleLastRun } from './rewrite_rule'; export { rewriteNamespaces } from './rewrite_namespaces'; diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.test.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.test.ts index 61dc9282bbfa1..365330e0995ce 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.test.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.test.ts @@ -5,25 +5,25 @@ * 2.0. */ -import { rewriteActionsReq, rewriteActionsRes } from './rewrite_actions'; +import { RuleActionTypes } from '../../../common'; +import { rewriteActionsReq } from './rewrite_actions'; -describe('rewrite Actions', () => { - describe('rewriteActionsRes', () => { - it('rewrites the actions response correctly', () => { - expect( - rewriteActionsRes([ +describe('rewriteActionsReq', () => { + it('should rewrite actions correctly', () => { + expect( + rewriteActionsReq( + [ { uuid: '111', group: 'default', id: '1', - actionTypeId: '2', params: { foo: 'bar' }, frequency: { summary: true, - notifyWhen: 'onThrottleInterval', + notify_when: 'onThrottleInterval', throttle: '1h', }, - alertsFilter: { + alerts_filter: { query: { kql: 'test:1s', dsl: '{test:1}', @@ -39,60 +39,12 @@ describe('rewrite Actions', () => { }, }, }, - ]) - ).toEqual([ - { - alerts_filter: { - query: { dsl: '{test:1}', kql: 'test:1s', filters: [] }, - timeframe: { - days: [1, 2, 3], - hours: { end: '15:00', start: '00:00' }, - timezone: 'UTC', - }, - }, - connector_type_id: '2', - frequency: { notify_when: 'onThrottleInterval', summary: true, throttle: '1h' }, - group: 'default', - id: '1', - params: { foo: 'bar' }, - uuid: '111', - }, - ]); - }); - }); - - describe('rewriteActionsReq', () => { - expect( - rewriteActionsReq([ - { - uuid: '111', - group: 'default', - id: '1', - params: { foo: 'bar' }, - frequency: { - summary: true, - notify_when: 'onThrottleInterval', - throttle: '1h', - }, - alerts_filter: { - query: { - kql: 'test:1s', - dsl: '{test:1}', - filters: [], - }, - timeframe: { - days: [1, 2, 3], - timezone: 'UTC', - hours: { - start: '00:00', - end: '15:00', - }, - }, - }, - }, - ]) + ], + () => false + ) ).toEqual([ { + type: RuleActionTypes.DEFAULT, uuid: '111', group: 'default', id: '1', @@ -120,4 +72,54 @@ describe('rewrite Actions', () => { }, ]); }); + it('should rewrite system actions correctly', () => { + expect( + rewriteActionsReq( + [ + { + uuid: '111', + group: 'default', + id: '1', + params: { foo: 'bar' }, + frequency: { + summary: true, + notify_when: 'onThrottleInterval', + throttle: '1h', + }, + }, + { + uuid: '111', + group: 'default', + id: 'system-1', + params: { foo: 'bar' }, + frequency: { + summary: true, + notify_when: 'onThrottleInterval', + throttle: '1h', + }, + }, + ], + (id) => id.startsWith('system') + ) + ).toEqual([ + { + type: RuleActionTypes.DEFAULT, + uuid: '111', + group: 'default', + id: '1', + params: { foo: 'bar' }, + frequency: { + summary: true, + notifyWhen: 'onThrottleInterval', + throttle: '1h', + }, + }, + { + type: RuleActionTypes.SYSTEM, + uuid: '111', + id: 'system-1', + params: { foo: 'bar' }, + }, + ]); + }); }); diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts index 70884f7b4a603..55dd2c61973cb 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts @@ -7,12 +7,12 @@ import { TypeOf } from '@kbn/config-schema/src/types/object_type'; import { omit } from 'lodash'; import { NormalizedAlertAction } from '../../rules_client'; -import { RuleAction } from '../../types'; import { actionsSchema } from './actions_schema'; import { RuleActionTypes } from '../../../common'; export const rewriteActionsReq = ( - actions?: TypeOf + actions: TypeOf, + isSystemAction: (connectorId: string) => boolean ): NormalizedAlertAction[] => { if (!actions) return []; @@ -23,78 +23,35 @@ export const rewriteActionsReq = ( use_alert_data_for_template: useAlertDataForTemplate, ...action }) => { + if (isSystemAction(action.id)) { + return { + id: action.id, + params: action.params, + ...(typeof useAlertDataForTemplate !== 'undefined' ? { useAlertDataForTemplate } : {}), + ...(action.uuid ? { uuid: action.uuid } : {}), + type: RuleActionTypes.SYSTEM, + }; + } + return { - ...action, + group: action.group ?? 'default', + id: action.id, + params: action.params, + ...(action.uuid ? { uuid: action.uuid } : {}), ...(typeof useAlertDataForTemplate !== 'undefined' ? { useAlertDataForTemplate } : {}), ...(frequency ? { frequency: { ...omit(frequency, 'notify_when'), + summary: frequency.summary, + throttle: frequency.throttle, notifyWhen: frequency.notify_when, }, } : {}), ...(alertsFilter ? { alertsFilter } : {}), + type: RuleActionTypes.DEFAULT, }; } ); }; - -export const rewriteActionsReqWithSystemActions = ( - actions: TypeOf, - isSystemAction: (connectorId: string) => boolean -): NormalizedAlertAction[] => { - if (!actions) return []; - - return actions.map(({ frequency, alerts_filter: alertsFilter, ...action }) => { - if (isSystemAction(action.id)) { - return { - id: action.id, - params: action.params, - ...(action.uuid ? { uuid: action.uuid } : {}), - type: RuleActionTypes.SYSTEM, - }; - } - - return { - group: action.group ?? 'default', - id: action.id, - params: action.params, - ...(action.uuid ? { uuid: action.uuid } : {}), - ...(frequency - ? { - frequency: { - summary: frequency.summary, - throttle: frequency.throttle, - notifyWhen: frequency.notify_when, - }, - } - : {}), - ...(alertsFilter ? { alertsFilter } : {}), - type: RuleActionTypes.DEFAULT, - }; - }); -}; - -export const rewriteActionsRes = (actions?: RuleAction[]) => { - const rewriteFrequency = ({ notifyWhen, ...rest }: NonNullable) => ({ - ...rest, - notify_when: notifyWhen, - }); - if (!actions) return []; - return actions.map( - ({ actionTypeId, frequency, alertsFilter, useAlertDataForTemplate, ...action }) => ({ - ...action, - connector_type_id: actionTypeId, - ...(typeof useAlertDataForTemplate !== 'undefined' - ? { use_alert_data_for_template: useAlertDataForTemplate } - : {}), - ...(frequency ? { frequency: rewriteFrequency(frequency) } : {}), - ...(alertsFilter - ? { - alerts_filter: alertsFilter, - } - : {}), - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts index 7a348e583ac6c..0cc343d0124ac 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts @@ -38,6 +38,7 @@ const sampleRule: SanitizedRule & { activeSnoozes?: string[] } = id: 'aaa', actionTypeId: 'bbb', params: {}, + type: 'default', frequency: { summary: false, notifyWhen: 'onThrottleInterval', @@ -45,6 +46,13 @@ const sampleRule: SanitizedRule & { activeSnoozes?: string[] } = }, alertsFilter: { query: { kql: 'test:1', dsl: '{}', filters: [] } }, }, + { + id: 'ccc', + actionTypeId: 'ddd', + params: {}, + type: 'system', + useAlertDataForTemplate: true, + }, ], scheduledTaskId: 'xyz456', snoozeSchedule: [], @@ -78,13 +86,15 @@ describe('rewriteRule', () => { }); it('should rewrite actions correctly', () => { const rewritten = rewriteRule(sampleRule); - for (const action of rewritten.actions) { - expect(Object.keys(action)).toEqual( - expect.arrayContaining(['group', 'id', 'connector_type_id', 'params', 'frequency']) - ); - expect(Object.keys(action.frequency!)).toEqual( - expect.arrayContaining(['summary', 'notify_when', 'throttle']) - ); - } + const [rewrittenDefaultAction, rewrittenSystemAction] = rewritten.actions; + expect(Object.keys(rewrittenDefaultAction)).toEqual( + expect.arrayContaining(['group', 'id', 'connector_type_id', 'params', 'frequency']) + ); + expect(Object.keys(rewrittenDefaultAction.frequency!)).toEqual( + expect.arrayContaining(['summary', 'notify_when', 'throttle']) + ); + expect(Object.keys(rewrittenSystemAction)).toEqual( + expect.arrayContaining(['use_alert_data_for_template', 'connector_type_id']) + ); }); }); diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts index 953211a5ef4f7..816bd485d14fe 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.ts @@ -6,7 +6,13 @@ */ import { omit } from 'lodash'; -import { RuleTypeParams, SanitizedRule, RuleLastRun } from '../../types'; +import { + RuleTypeParams, + SanitizedRule, + RuleLastRun, + RuleActionTypes, + RuleDefaultAction, +} from '../../types'; export const rewriteRuleLastRun = (lastRun: RuleLastRun) => { const { outcomeMsg, outcomeOrder, alertsCount, ...rest } = lastRun; @@ -58,23 +64,37 @@ export const rewriteRule = ({ last_execution_date: executionStatus.lastExecutionDate, last_duration: executionStatus.lastDuration, }, - actions: actions.map(({ group, id, actionTypeId, params, frequency, uuid, alertsFilter }) => ({ - group, - id, - params, - connector_type_id: actionTypeId, - ...(frequency - ? { - frequency: { - summary: frequency.summary, - notify_when: frequency.notifyWhen, - throttle: frequency.throttle, - }, - } - : {}), - ...(uuid && { uuid }), - ...(alertsFilter && { alerts_filter: alertsFilter }), - })), + actions: actions.map( + ({ id, actionTypeId, params, uuid, type, useAlertDataForTemplate, ...action }) => { + if (type === RuleActionTypes.SYSTEM) { + return { + ...action, + connector_type_id: actionTypeId, + ...(typeof useAlertDataForTemplate !== 'undefined' + ? { use_alert_data_for_template: useAlertDataForTemplate } + : {}), + }; + } + const { group, frequency, alertsFilter } = action as RuleDefaultAction; + return { + group, + id, + params, + connector_type_id: actionTypeId, + ...(frequency + ? { + frequency: { + summary: frequency.summary, + notify_when: frequency.notifyWhen, + throttle: frequency.throttle, + }, + } + : {}), + ...(uuid && { uuid }), + ...(alertsFilter && { alerts_filter: alertsFilter }), + }; + } + ), ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), ...(nextRun ? { next_run: nextRun } : {}), ...(apiKeyCreatedByUser !== undefined ? { api_key_created_by_user: apiKeyCreatedByUser } : {}), diff --git a/x-pack/plugins/alerting/server/routes/update_rule.ts b/x-pack/plugins/alerting/server/routes/update_rule.ts index 2f1e32999af3a..02d59dc11db6c 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule.ts @@ -16,7 +16,7 @@ import { handleDisabledApiKeysError, actionsSchema, rewriteRuleLastRun, - rewriteActionsReqWithSystemActions, + rewriteActionsReq, } from './lib'; import { RuleTypeParams, @@ -70,7 +70,7 @@ const rewriteBodyReq = ( data: { ...rest, notifyWhen, - actions: rewriteActionsReqWithSystemActions(actions, isSystemAction), + actions: rewriteActionsReq(actions, isSystemAction), }, }; }; @@ -146,15 +146,13 @@ export const updateRuleRoute = ( router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { const rulesClient = (await context.alerting).getRulesClient(); - const actionsClient = (await context.actions).getActionsClient(); + const { isSystemAction } = (await context.actions).getActionsClient(); const { id } = req.params; const rule = req.body; try { const alertRes = await rulesClient.update( - rewriteBodyReq({ id, data: rule }, (connectorId: string) => - actionsClient.isSystemAction(connectorId) - ) + rewriteBodyReq({ id, data: rule }, isSystemAction) ); return res.ok({ body: rewriteBodyRes(alertRes),