Skip to content

Commit

Permalink
[RAM][Bug] Fix bug preventing filters from being added to conditional…
Browse files Browse the repository at this point in the history
… actions (elastic#171048)

## Summary
Resolves: elastic#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 <[email protected]>
  • Loading branch information
JiaweiWu and kibanamachine authored Nov 15, 2023
1 parent d09e47a commit fbb2328
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];
4 changes: 4 additions & 0 deletions x-pack/plugins/alerting/common/routes/rule/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export {
ruleExecutionStatusValues,
ruleExecutionStatusErrorReason,
ruleExecutionStatusWarningReason,
filterStateStore,
} from './constants/latest';

export type {
Expand All @@ -19,6 +20,7 @@ export type {
RuleExecutionStatusValues,
RuleExecutionStatusErrorReason,
RuleExecutionStatusWarningReason,
FilterStateStore,
} from './constants/latest';

export {
Expand All @@ -27,6 +29,7 @@ export {
ruleExecutionStatusValues as ruleExecutionStatusValuesV1,
ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1,
ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1,
filterStateStore as filterStateStoreV1,
} from './constants/v1';

export type {
Expand All @@ -35,4 +38,5 @@ export type {
RuleExecutionStatusValues as RuleExecutionStatusValuesV1,
RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1,
RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1,
FilterStateStore as FilterStateStoreV1,
} from './constants/v1';
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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),
]),
})
),
})
),
})
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/alerting/server/application/rule/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -55,7 +55,11 @@ export async function createRule<Params extends RuleParams = never>(
): Promise<SanitizedRule<Params>> {
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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@

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()));

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),
]),
})
),
})
);

Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/alerting/server/application/rule/types/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ruleExecutionStatusValues,
ruleExecutionStatusErrorReason,
ruleExecutionStatusWarningReason,
filterStateStore,
} from '../constants';
import {
ruleParamsSchema,
Expand All @@ -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<typeof ruleParamsSchema>;
export type RuleSnoozeSchedule = TypeOf<typeof snoozeScheduleSchema>;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/alerting/server/raw_rule_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')]),
})
Expand Down
10 changes: 9 additions & 1 deletion x-pack/plugins/alerting/server/routes/lib/actions_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}}':
Expand Down

0 comments on commit fbb2328

Please sign in to comment.