scaffolder-backend: add dry-run request body validation
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -72,7 +72,8 @@
|
||||
"winston": "^3.2.1",
|
||||
"yaml": "^1.10.0",
|
||||
"vm2": "^3.9.6",
|
||||
"zen-observable": "^0.8.15"
|
||||
"zen-observable": "^0.8.15",
|
||||
"zod": "^3.11.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-test-utils": "^0.1.25-next.0",
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { Config, JsonObject } from '@backstage/config';
|
||||
import { InputError, NotFoundError } from '@backstage/errors';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import {
|
||||
@@ -35,6 +35,7 @@ import Router from 'express-promise-router';
|
||||
import { validate } from 'jsonschema';
|
||||
import { Logger } from 'winston';
|
||||
import { TemplateFilter } from '../lib';
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
createBuiltinActions,
|
||||
DatabaseTaskStore,
|
||||
@@ -336,20 +337,27 @@ export async function createRouter(
|
||||
});
|
||||
})
|
||||
.post('/v2/dry-run', async (req, res) => {
|
||||
const template = req.body.template as TemplateEntityV1beta3;
|
||||
const bodySchema = z.object({
|
||||
template: z.unknown(),
|
||||
values: z.record(z.unknown()),
|
||||
secrets: z.record(z.string()),
|
||||
content: z.array(
|
||||
z.object({ path: z.string(), base64Content: z.string() }),
|
||||
),
|
||||
});
|
||||
const body = await bodySchema.parseAsync(req.body).catch(e => {
|
||||
throw new InputError(`Malformed request: ${e}`);
|
||||
});
|
||||
|
||||
const template = body.template as TemplateEntityV1beta3;
|
||||
if (!(await templateEntityV1beta3Validator.check(template))) {
|
||||
throw new InputError('Input template is not a template');
|
||||
}
|
||||
|
||||
const values = req.body.values;
|
||||
const token = getBearerToken(req.headers.authorization);
|
||||
const content = req.body.content as {
|
||||
path: string;
|
||||
base64Content: string;
|
||||
}[];
|
||||
|
||||
for (const parameters of [template.spec.parameters ?? []].flat()) {
|
||||
const result = validate(values, parameters);
|
||||
const result = validate(body.values, parameters);
|
||||
if (!result.valid) {
|
||||
res.status(400).json({ errors: result.errors });
|
||||
return;
|
||||
@@ -367,15 +375,15 @@ export async function createRouter(
|
||||
apiVersion: template.apiVersion,
|
||||
steps,
|
||||
output: template.spec.output ?? {},
|
||||
parameters: values,
|
||||
parameters: body.values as JsonObject,
|
||||
},
|
||||
content: (content ?? []).map(file => ({
|
||||
content: (body.content ?? []).map(file => ({
|
||||
path: file.path,
|
||||
content: Buffer.from(file.base64Content, 'base64'),
|
||||
})),
|
||||
secrets: {
|
||||
...req.body.secrets,
|
||||
backstageToken: token,
|
||||
...body.secrets,
|
||||
...(token && { backstageToken: token }),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user