The input is validated and results are coming back!
This commit is contained in:
Vendored
+7
@@ -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",
|
||||
|
||||
@@ -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() }));
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user