The input is validated and results are coming back!

This commit is contained in:
Matt Aitken
2023-02-13 21:44:18 +00:00
parent 38f32f405f
commit 027f0210dc
5 changed files with 146 additions and 4 deletions
+7
View File
@@ -11,6 +11,13 @@
"type": "node-terminal",
"cwd": "${workspaceFolder}"
},
{
"command": "pnpm run dev --filter integrations",
"name": "Run integrations",
"request": "launch",
"type": "node-terminal",
"cwd": "${workspaceFolder}"
},
{
"type": "chrome",
"request": "launch",
+16 -2
View File
@@ -1,4 +1,5 @@
import { AuthCredentialsSchema } from "core/authentication/types";
import { validateInputs } from "core/validation/inputs";
import { Request, Response } from "express";
import { catalog } from "integrations/catalog";
import { z } from "zod";
@@ -43,8 +44,6 @@ export async function handleAction(req: Request, res: Response) {
return;
}
console.log("body", req.body);
const bodyResult = bodySchema.safeParse(req.body);
if (!bodyResult.success) {
@@ -57,10 +56,25 @@ export async function handleAction(req: Request, res: Response) {
return;
}
const inputValidationResult = await validateInputs(
matchingAction.spec.input,
bodyResult.data
);
if (!inputValidationResult.success) {
res.status(400).send(
JSON.stringify({
success: false,
error: inputValidationResult.error,
})
);
return;
}
try {
const data = await matchingAction.action(bodyResult.data);
res.send(JSON.stringify(data));
} catch (e: any) {
console.error(e);
res
.status(500)
.send(JSON.stringify({ success: false, errors: e.toString() }));
+8 -2
View File
@@ -7,13 +7,19 @@ export type RequestError =
| ExtraParametersError
| InsufficientScopesError
| MissingResponseSpec
| ResponseBodyInvalid;
| ResponseBodyInvalid
| BodyMissing
| MissingCredentialsError;
export interface RequestBodyInvalid {
type: "request_body_invalid";
errors: any[];
}
export interface BodyMissing {
type: "missing_body";
}
export interface ParameterMissing {
type: "missing_parameter";
parameter: {
@@ -27,7 +33,7 @@ export interface ParametersInvalid {
name: string;
value: any;
};
errors: Array<{ name: string; errors: JSONSchemaError[] }>;
errors: JSONSchemaError[];
}
export interface ExtraParametersError {
@@ -18,6 +18,12 @@ export async function requestEndpoint(
let path = endpointSpec.path;
// validate the request body
if (body == null && request.body?.schema != null) {
throw {
type: "missing_body",
};
}
const requestValid = await validate(body, request.body?.schema);
if (!requestValid.success) {
throw {
@@ -0,0 +1,109 @@
import { InputSpec } from "core/action/types";
import { checkRequiredScopes } from "core/authentication/credentials";
import { RequestError } from "core/request/errors";
import { RequestData, RequestSpec } from "core/request/types";
import { validate } from "core/schemas/validate";
type ValidationResult =
| {
success: true;
}
| {
success: false;
error: RequestError;
};
export async function validateInputs(
inputSpec: InputSpec,
{ parameters, body, credentials }: RequestData
): Promise<ValidationResult> {
if (inputSpec.security) {
if (credentials === undefined) {
return {
success: false,
error: {
type: "missing_credentials",
},
};
}
const requiredScopes = inputSpec.security[credentials.name] ?? [];
const result = checkRequiredScopes(requiredScopes, credentials);
if (!result.success) {
return {
success: false,
error: {
type: "insufficient_scopes",
missingScopes: result.missingScopes,
},
};
}
}
// validate the request body exists it it should
if (body == null && inputSpec.body != null) {
return {
success: false,
error: {
type: "missing_body",
},
};
}
//validate the request body against the schema
const requestValid = await validate(body, inputSpec.body);
if (!requestValid.success) {
return {
success: false,
error: {
type: "request_body_invalid",
errors: requestValid.errors,
},
};
}
//validate the parameters
if (inputSpec.parameters != null) {
for (const parameter of inputSpec.parameters) {
const { name, required } = parameter;
// if the parameter is missing
if (parameters === undefined || parameters[name] == null) {
if (required) {
return {
success: false,
error: {
type: "missing_parameter",
parameter: {
name,
},
},
};
} else {
continue;
}
}
const element = parameters[name];
//validate the parameter against the schema
const valid = await validate(element, parameter.schema);
if (!valid.success) {
return {
success: false,
error: {
type: "parameter_invalid",
parameter: {
name,
value: element,
},
errors: valid.errors,
},
};
}
}
}
return {
success: true,
};
}