Skip to content

Commit

Permalink
feat: validation api for grading job configuartions
Browse files Browse the repository at this point in the history
  • Loading branch information
williams-jack committed Aug 28, 2024
1 parent 293017d commit 6ed0ac1
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request, Response } from "express";
import { errorResponse, formatValidationErrors } from "./utils";
import {
graderImageExists,
graderImageExists,
logger,
validations,
} from "@codegrade-orca/common";
Expand All @@ -10,7 +10,12 @@ import { GradingQueueOperationException, enqueueImageBuild, imageIsAwaitingBuild
export const createGraderImage = async (req: Request, res: Response) => {
const validator = validations.graderImageBuildRequest;
if (!validator(req.body)) {
return errorResponse(res, 400, formatValidationErrors("The request body to build a grader image is invalid.", validator.errors));
return errorResponse(res, 400,
[
"The request body to build a grader image is invalid.",
...formatValidationErrors(validator.errors)
]
);
}
const { dockerfile_sha_sum } = req.body;
if (graderImageExists(dockerfile_sha_sum)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,12 @@ export const createOrUpdateImmediateJob = async (
) => {
const validator = validations.gradingJobConfig
if (!validator(req.body)) {
return errorResponse(res, 400, formatValidationErrors("The given grading job was invalid.", validator.errors));
return errorResponse(res, 400,
[
"The given grading job was invalid.",
...formatValidationErrors(validator.errors)
]
);
}
try {
const status = await putJobInQueue(req.body, true);
Expand All @@ -130,7 +135,12 @@ export const createOrUpdateImmediateJob = async (
export const createOrUpdateJob = async (req: Request, res: Response) => {
const validator = validations.gradingJobConfig
if (!validator(req.body)) {
return errorResponse(res, 400, formatValidationErrors("The given grading job was invalid.", validator.errors));
return errorResponse(res, 400,
[
"The given immediate grading job was invalid.",
...formatValidationErrors(validator.errors)
]
);
}
try {
const status = await putJobInQueue(req.body, false);
Expand Down Expand Up @@ -197,4 +207,3 @@ export const jobStatus = async (req: Request, res: Response) => {
return res.json(`Your job is number ${queuePosition} in the queue.`);
}
}

13 changes: 5 additions & 8 deletions orchestrator/packages/api/src/controllers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GradingJobConfig, GradingJobResult, logger, validations } from "@codegrade-orca/common";
import { ValidationErrors } from "@codegrade-orca/common/src/validations";
import { ValidationErrors } from "@codegrade-orca/common";
import { Response } from "express";

export const errorResponse = (
Expand All @@ -15,13 +15,10 @@ export const errorResponse = (
return res.status(status).json({ errors: errors });
};

export const formatValidationErrors = (description: string, validationErrors: ValidationErrors): Array<string> =>
[
description,
...(validationErrors ?
validationErrors.map((e) => formatValidationError(e.instancePath, e.message)).filter((s) => s !== '') :
[])
];
export const formatValidationErrors = (validationErrors: ValidationErrors): Array<string> =>
validationErrors ?
validationErrors.map((e) => formatValidationError(e.instancePath, e.message)).filter((s) => s !== '') :
[];

const formatValidationError = (instancePath: string, message: string | undefined): string => {
return `${instancePath} ${message ?? ''}`.trim();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Request, Response } from "express";
import { errorResponse, formatValidationErrors } from "./utils";
import { validations } from "@codegrade-orca/common";

export const gradingJobValidation = async (req: Request, res: Response) => {
if (!req.body || Object.keys(req.body).length === 0) {
return errorResponse(res, 400, ['No request body provided for grading job configuration schema validation.']);
}
const validator = validations.gradingJobConfig;
return validator(req.body) ?
res.json({ "message": "Provided request body is a valid grading job configuration." }) :
res.json({ "errors": formatValidationErrors(validator.errors) });
}
9 changes: 9 additions & 0 deletions orchestrator/packages/api/src/routes/validations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Router } from "express";
import verifyAPIKey from "../middleware/verify-api-key";
import { gradingJobValidation } from "../controllers/validations-controller";

const validationsRouter = Router();

validationsRouter.post('/validate_grading_job', verifyAPIKey, gradingJobValidation);

export default validationsRouter;
4 changes: 2 additions & 2 deletions orchestrator/packages/common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import path from "path";
import { getConfig } from "./config";
import logger from "./logger";
import validations from "./validations";
import validations, { ValidationErrors } from "./validations";
import { existsSync } from "fs";

export * from "./grading-jobs";
export * from "./types";
export * from "./config";
export * from "./utils";
export { validations };
export { validations, ValidationErrors };
export { logger };

export const toMilliseconds = (seconds: number) => seconds * 1_000;
Expand Down

0 comments on commit 6ed0ac1

Please sign in to comment.