From fbb232815b85961ac09b6abbe369eb7b3760752d Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Wed, 15 Nov 2023 11:38:50 -0800 Subject: [PATCH] [RAM][Bug] Fix bug preventing filters from being added to conditional actions (#171048) ## Summary Resolves: https://github.com/elastic/kibana/issues/171036 Fixes a bug where the schema name for the conditional action filter `$state` was incorrectly name. This prevented the user from adding filters to conditional actions as the schema validation would reject the request. ### To verify the fix: 1. Create a rule 2. Add a conditional action 3. Assert that filters can be added to the rule 4. Rule is saved 5. Repeat 1 - 4 but this time, update the rule. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/routes/rule/apis/create/schemas/v1.ts | 10 +++++++++- .../common/routes/rule/common/constants/v1.ts | 6 ++++++ .../alerting/common/routes/rule/common/index.ts | 4 ++++ .../common/routes/rule/response/schemas/v1.ts | 10 +++++++++- .../alerting/server/application/rule/constants.ts | 5 +++++ .../application/rule/methods/create/create_rule.ts | 8 ++++++-- .../application/rule/schemas/action_schemas.ts | 10 +++++++++- .../alerting/server/application/rule/types/rule.ts | 2 ++ x-pack/plugins/alerting/server/raw_rule_schema.ts | 2 +- .../alerting/server/routes/lib/actions_schema.ts | 10 +++++++++- .../apps/triggers_actions_ui/alert_create_flyout.ts | 13 +++++++++++++ 11 files changed, 73 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts index 6f8420c8cc4da..751f2e8c38780 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation'; import { notifyWhenSchemaV1 } from '../../../response'; +import { filterStateStore } from '../../../common/constants/v1'; export const actionFrequencySchema = schema.object({ summary: schema.boolean(), @@ -23,7 +24,14 @@ export const actionAlertsFilterSchema = schema.object({ schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStore.APP_STATE), + schema.literal(filterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ), dsl: schema.maybe(schema.string()), diff --git a/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts b/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts index fbeb08ba6bc7f..3bf7208efe37f 100644 --- a/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts @@ -43,6 +43,11 @@ export const ruleExecutionStatusWarningReason = { MAX_QUEUED_ACTIONS: 'maxQueuedActions', } as const; +export const filterStateStore = { + APP_STATE: 'appState', + GLOBAL_STATE: 'globalState', +} as const; + export type RuleNotifyWhen = typeof ruleNotifyWhen[keyof typeof ruleNotifyWhen]; export type RuleLastRunOutcomeValues = typeof ruleLastRunOutcomeValues[keyof typeof ruleLastRunOutcomeValues]; @@ -52,3 +57,4 @@ export type RuleExecutionStatusErrorReason = typeof ruleExecutionStatusErrorReason[keyof typeof ruleExecutionStatusErrorReason]; export type RuleExecutionStatusWarningReason = typeof ruleExecutionStatusWarningReason[keyof typeof ruleExecutionStatusWarningReason]; +export type FilterStateStore = typeof filterStateStore[keyof typeof filterStateStore]; diff --git a/x-pack/plugins/alerting/common/routes/rule/common/index.ts b/x-pack/plugins/alerting/common/routes/rule/common/index.ts index 5989a3a993e7a..669bfc484070a 100644 --- a/x-pack/plugins/alerting/common/routes/rule/common/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/common/index.ts @@ -11,6 +11,7 @@ export { ruleExecutionStatusValues, ruleExecutionStatusErrorReason, ruleExecutionStatusWarningReason, + filterStateStore, } from './constants/latest'; export type { @@ -19,6 +20,7 @@ export type { RuleExecutionStatusValues, RuleExecutionStatusErrorReason, RuleExecutionStatusWarningReason, + FilterStateStore, } from './constants/latest'; export { @@ -27,6 +29,7 @@ export { ruleExecutionStatusValues as ruleExecutionStatusValuesV1, ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, + filterStateStore as filterStateStoreV1, } from './constants/v1'; export type { @@ -35,4 +38,5 @@ export type { RuleExecutionStatusValues as RuleExecutionStatusValuesV1, RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1, RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1, + FilterStateStore as FilterStateStoreV1, } from './constants/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts index fe02146c5ef62..0e043aa217667 100644 --- a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts @@ -13,6 +13,7 @@ import { ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, + filterStateStore as filterStateStoreV1, } from '../../common/constants/v1'; import { validateNotifyWhenV1 } from '../../validation'; @@ -47,7 +48,14 @@ const actionAlertsFilterSchema = schema.object({ schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStoreV1.APP_STATE), + schema.literal(filterStateStoreV1.GLOBAL_STATE), + ]), + }) + ), }) ), }) diff --git a/x-pack/plugins/alerting/server/application/rule/constants.ts b/x-pack/plugins/alerting/server/application/rule/constants.ts index bc75d91375ecb..0881868d9db8f 100644 --- a/x-pack/plugins/alerting/server/application/rule/constants.ts +++ b/x-pack/plugins/alerting/server/application/rule/constants.ts @@ -42,3 +42,8 @@ export const ruleExecutionStatusWarningReason = { MAX_ALERTS: 'maxAlerts', MAX_QUEUED_ACTIONS: 'maxQueuedActions', } as const; + +export const filterStateStore = { + APP_STATE: 'appState', + GLOBAL_STATE: 'globalState', +} as const; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts index d774a80ae4ebc..74dd0775d0c22 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts @@ -23,7 +23,7 @@ import { } from '../../../../rules_client/lib'; import { generateAPIKeyName, apiKeyAsRuleDomainProperties } from '../../../../rules_client/common'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; -import { RulesClientContext } from '../../../../rules_client/types'; +import { RulesClientContext, NormalizedAlertAction } from '../../../../rules_client/types'; import { RuleDomain, RuleParams } from '../../types'; import { SanitizedRule } from '../../../../types'; import { @@ -55,7 +55,11 @@ export async function createRule( ): Promise> { const { data: initialData, options, allowMissingConnectorSecrets } = createParams; - const data = { ...initialData, actions: addGeneratedActionValues(initialData.actions) }; + // TODO (http-versioning): Remove this cast when we fix addGeneratedActionValues + const data = { + ...initialData, + actions: addGeneratedActionValues(initialData.actions as NormalizedAlertAction[]), + }; const id = options?.id || SavedObjectsUtils.generateId(); diff --git a/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts b/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts index fa8e05f837c25..579f41adb0424 100644 --- a/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts +++ b/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts @@ -7,6 +7,7 @@ import { schema } from '@kbn/config-schema'; import { notifyWhenSchema } from './notify_when_schema'; +import { filterStateStore } from '../constants'; export const actionParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); @@ -14,7 +15,14 @@ const actionAlertsFilterQueryFiltersSchema = schema.arrayOf( schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStore.APP_STATE), + schema.literal(filterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ); diff --git a/x-pack/plugins/alerting/server/application/rule/types/rule.ts b/x-pack/plugins/alerting/server/application/rule/types/rule.ts index 04e37a125aa40..d8dbabb72b23b 100644 --- a/x-pack/plugins/alerting/server/application/rule/types/rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/types/rule.ts @@ -12,6 +12,7 @@ import { ruleExecutionStatusValues, ruleExecutionStatusErrorReason, ruleExecutionStatusWarningReason, + filterStateStore, } from '../constants'; import { ruleParamsSchema, @@ -33,6 +34,7 @@ export type RuleExecutionStatusErrorReason = typeof ruleExecutionStatusErrorReason[keyof typeof ruleExecutionStatusErrorReason]; export type RuleExecutionStatusWarningReason = typeof ruleExecutionStatusWarningReason[keyof typeof ruleExecutionStatusWarningReason]; +export type FilterStateStore = typeof filterStateStore[keyof typeof filterStateStore]; export type RuleParams = TypeOf; export type RuleSnoozeSchedule = TypeOf; diff --git a/x-pack/plugins/alerting/server/raw_rule_schema.ts b/x-pack/plugins/alerting/server/raw_rule_schema.ts index 65d4b48ec7d66..4072b15b19210 100644 --- a/x-pack/plugins/alerting/server/raw_rule_schema.ts +++ b/x-pack/plugins/alerting/server/raw_rule_schema.ts @@ -169,7 +169,7 @@ const rawRuleAlertsFilterSchema = schema.object({ params: schema.maybe(schema.recordOf(schema.string(), schema.any())), // better type? value: schema.maybe(schema.string()), }), - state$: schema.maybe( + $state: schema.maybe( schema.object({ store: schema.oneOf([schema.literal('appState'), schema.literal('globalState')]), }) diff --git a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts index 57a089bc9933a..76661b2d33ff2 100644 --- a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts +++ b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts @@ -6,6 +6,7 @@ */ import { schema } from '@kbn/config-schema'; +import { FilterStateStore } from '@kbn/es-query'; import { validateTimezone } from './validate_timezone'; import { validateDurationSchema } from '../../lib'; import { validateHours } from './validate_hours'; @@ -36,7 +37,14 @@ export const actionsSchema = schema.arrayOf( schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(FilterStateStore.APP_STATE), + schema.literal(FilterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ), dsl: schema.maybe(schema.string()), diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index cdf9cc87684ad..3cceb01b54998 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -155,6 +155,19 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('notifyWhenSelect'); await testSubjects.click('onThrottleInterval'); await testSubjects.setValue('throttleInput', '10'); + + // Alerts search bar (conditional actions) + await testSubjects.click('alertsFilterQueryToggle'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('addFilter'); + await testSubjects.click('filterFieldSuggestionList'); + await comboBox.set('filterFieldSuggestionList', '_id'); + await comboBox.set('filterOperatorList', 'is not'); + await testSubjects.setValue('filterParams', 'fake-rule-id'); + await testSubjects.click('saveFilter'); + await testSubjects.setValue('queryInput', '_id: *'); + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql( `Rule '{{rule.name}}' is active for group '{{context.group}}':