From 5e1ba9d36d4c36a484259692e75e453db2c2d9f4 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> (cherry picked from commit fbb232815b85961ac09b6abbe369eb7b3760752d) # Conflicts: # x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts # x-pack/plugins/alerting/common/routes/rule/common/index.ts # x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts --- .../common/routes/rule/apis/create/schemas/v1.ts | 10 +++++++++- .../common/routes/rule/response/constants/v1.ts | 6 ++++++ .../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 +++++++++++++ 10 files changed, 69 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 98d82abf62be4..4f60d606c07f5 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 @@ -7,6 +7,7 @@ import { schema } from '@kbn/config-schema'; import { ruleNotifyWhenV1 } from '../../../response'; +import { filterStateStore as filterStateStoreV1 } from '../../../response/constants/v1'; import { validateNotifyWhenV1, validateDurationV1, @@ -37,7 +38,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(filterStateStoreV1.APP_STATE), + schema.literal(filterStateStoreV1.GLOBAL_STATE), + ]), + }) + ), }) ), dsl: schema.maybe(schema.string()), diff --git a/x-pack/plugins/alerting/common/routes/rule/response/constants/v1.ts b/x-pack/plugins/alerting/common/routes/rule/response/constants/v1.ts index a241412310482..8b4402a6029f1 100644 --- a/x-pack/plugins/alerting/common/routes/rule/response/constants/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/response/constants/v1.ts @@ -42,6 +42,11 @@ export const ruleExecutionStatusWarningReason = { MAX_ALERTS: 'maxAlerts', } 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]; @@ -51,3 +56,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/response/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts index 3aecec56c3a41..a8a6e451a17ba 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 @@ -12,6 +12,7 @@ import { ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, + filterStateStore as filterStateStoreV1, } from '../constants/v1'; export const ruleParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); @@ -42,7 +43,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 7b0aa82a90ca9..2b200018921d6 100644 --- a/x-pack/plugins/alerting/server/application/rule/constants.ts +++ b/x-pack/plugins/alerting/server/application/rule/constants.ts @@ -41,3 +41,8 @@ export const ruleExecutionStatusWarningReason = { MAX_EXECUTABLE_ACTIONS: 'maxExecutableActions', MAX_ALERTS: 'maxAlerts', } 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 ddd6691a635a3..be937aa539366 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 { @@ -54,7 +54,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 f123466eca1ab..e901ca364b061 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 5843467a4cb46..9e4b1ff32e79c 100644 --- a/x-pack/plugins/alerting/server/raw_rule_schema.ts +++ b/x-pack/plugins/alerting/server/raw_rule_schema.ts @@ -168,7 +168,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 9d6f89e070c3a..7820765ed0cc6 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 c1d902b2c3288..3308666c00b70 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 @@ -142,6 +142,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}}':