scaffolder-backend: add dry-run request body validation

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2022-05-31 10:55:42 +02:00
parent caafe75e89
commit 0203775f4b
2 changed files with 22 additions and 13 deletions
+2 -1
View File
@@ -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 }),
},
});