Alerting: Prevent incorrect prefill params to crash the rule editor (#106395)

also introduces "zod" as dependency
This commit is contained in:
Gilles De Mey
2025-06-24 11:51:20 +00:00
committed by GitHub
parent 3c799b13e9
commit 7c914af56a
4 changed files with 95 additions and 5 deletions
+2 -1
View File
@@ -259,7 +259,8 @@
"webpack-subresource-integrity": "^5.2.0-rc.1",
"webpackbar": "^7.0.0",
"yaml": "^2.0.0",
"yargs": "^17.5.1"
"yargs": "^17.5.1",
"zod": "^3.25.55"
},
"dependencies": {
"@bsull/augurs": "^0.10.0",
@@ -106,9 +106,7 @@ export const AlertRuleForm = ({ existing, prefill, isManualRestore }: Props) =>
return formValuesFromPrefill(prefill);
}
const defaultRuleType = ruleType || RuleFormType.grafana;
return defaultFormValuesForRuleType(defaultRuleType);
return defaultFormValuesForRuleType(ruleType);
}, [existing, prefill, ruleType]);
const formAPI = useForm<RuleFormValues>({
@@ -1,4 +1,5 @@
import { clamp } from 'lodash';
import { z } from 'zod/v4';
import { config } from '@grafana/runtime';
import { RuleWithLocation } from 'app/types/unified-alerting';
@@ -136,9 +137,12 @@ export function formValuesFromQueryParams(ruleDefinition: string, type: RuleForm
}
export function formValuesFromPrefill(rule: Partial<RuleFormValues>): RuleFormValues {
// coerce prefill params to a valid RuleFormValues interface
const parsedRule = ruleFormValuesSchema.parse(rule);
return revealHiddenQueries({
...getDefaultFormValues(rule.type),
...rule,
...parsedRule,
});
}
@@ -169,3 +173,82 @@ export function translateRouteParamToRuleType(param = ''): RuleFormType {
return RuleFormType.grafana;
}
// we use this schema to coerce prefilled query params into a valid "FormValues" interface
const ruleFormValuesSchema = z.looseObject({
name: z.string().optional(),
type: z.enum(RuleFormType).catch(RuleFormType.grafana),
dataSourceName: z.string().optional().default(''),
group: z.string().optional(),
labels: z
.array(
z.object({
key: z.string(),
value: z.string(),
})
)
.optional()
.default([]),
annotations: z
.array(
z.object({
key: z.string(),
value: z.string(),
})
)
.optional()
.default([]),
queries: z.array(z.any()).optional(),
condition: z.string().optional(),
noDataState: z
.enum(GrafanaAlertStateDecision)
.optional()
.default(GrafanaAlertStateDecision.NoData)
.catch(GrafanaAlertStateDecision.NoData),
execErrState: z
.enum(GrafanaAlertStateDecision)
.optional()
.default(GrafanaAlertStateDecision.Error)
.catch(GrafanaAlertStateDecision.Error),
folder: z
.union([
z.object({
title: z.string(),
uid: z.string(),
}),
z.undefined(),
])
.optional(),
evaluateEvery: z.string().optional(),
evaluateFor: z.string().optional().default('0s'),
keepFiringFor: z.string().optional(),
isPaused: z.boolean().optional().default(false),
manualRouting: z.boolean().optional(),
contactPoints: z
.record(
z.string(),
z.object({
selectedContactPoint: z.string(),
overrideGrouping: z.boolean(),
groupBy: z.array(z.string()),
overrideTimings: z.boolean(),
groupWaitValue: z.string(),
groupIntervalValue: z.string(),
repeatIntervalValue: z.string(),
muteTimeIntervals: z.array(z.string()),
activeTimeIntervals: z.array(z.string()),
})
)
.optional(),
editorSettings: z
.object({
simplifiedQueryEditor: z.boolean(),
simplifiedNotificationEditor: z.boolean(),
})
.optional(),
metric: z.string().optional(),
targetDatasourceUid: z.string().optional(),
namespace: z.string().optional(),
expression: z.string().optional(),
missingSeriesEvalsToResolve: z.number().optional(),
});
+8
View File
@@ -18450,6 +18450,7 @@ __metadata:
whatwg-fetch: "npm:3.6.20"
yaml: "npm:^2.0.0"
yargs: "npm:^17.5.1"
zod: "npm:^3.25.55"
dependenciesMeta:
prettier@3.4.2:
unplugged: true
@@ -32978,3 +32979,10 @@ __metadata:
checksum: 10/0e35432dcca7f053e63f5dd491a87c78abe0d981817547252c3b6d05f0f58788695d1a69724759c6501dff3fd62929be24c9f314a3625179bee889150f7a61fa
languageName: node
linkType: hard
"zod@npm:^3.25.55":
version: 3.25.55
resolution: "zod@npm:3.25.55"
checksum: 10/1f86d370730fc1eed10fe584079bfebd0008303722f2da21057d493e784b42f0b1edbac028b5a788e2e04bd31da070eac8e8d5f237ec968bc2a6aa30985fa9d6
languageName: node
linkType: hard