Select Git revision
cipher-core.js
Forked from
Développement Web Avancé / 2019_TP2
Source project has a limited visibility.
DojoValidators.ts 11.26 KiB
import Config from '../config/Config.js';
import { CustomValidator, ErrorMessage, FieldMessageFactory, Meta } from 'express-validator/src/base';
import { BailOptions, ValidationChain } from 'express-validator/src/chain';
import GitlabManager from '../managers/GitlabManager.js';
import express from 'express';
import logger from '../shared/logging/WinstonLogger.js';
import Json5FileValidator from '../shared/helpers/Json5FileValidator.js';
import ExerciseResultsFile from '../shared/types/Dojo/ExerciseResultsFile.js';
import ParamsCallbackManager from '../middlewares/ParamsCallbackManager.js';
import ExerciseManager from '../managers/ExerciseManager.js';
import Toolbox from '../shared/helpers/Toolbox.js';
declare type DojoMeta = Meta & {
req: express.Request
};
declare type DojoCustomValidator = (input: unknown, meta: DojoMeta) => unknown;
declare type DojoCustomValidatorSchemaOptions = { errorMessage?: FieldMessageFactory | ErrorMessage, negated?: boolean, bail?: boolean | BailOptions, if?: CustomValidator | ValidationChain, options?: CustomValidator }
class DojoValidators {
private toValidatorSchemaOptions(arg: { errorMessage?: FieldMessageFactory | ErrorMessage, negated?: boolean, bail?: boolean | BailOptions, if?: DojoCustomValidator | ValidationChain, options?: DojoCustomValidator }) {
// This is a hack to make the types work with req arg as express.Request instead of Request defined by express-validator
return arg as unknown as DojoCustomValidatorSchemaOptions;
}
private getParamValue(req: express.Request, path: string): unknown {
return 'body' in req && path in req.body ? req.body[path] : req.query[path];
}
readonly nullSanitizer = this.toValidatorSchemaOptions({
options: value => {
try {
return value === 'null' || value === 'undefined' || value === '' ? null : value;
} catch ( error ) {
logger.error(`null sanitizer error: ${ JSON.stringify(error) }`);
return value;
}
}
});
readonly jsonSanitizer = this.toValidatorSchemaOptions({
options: value => {
try {
return JSON.parse(value as string) as unknown;
} catch ( e ) {
return value;
}
}
});
readonly templateUrlValidator = this.toValidatorSchemaOptions({
bail : true,
errorMessage: 'Template doesn\'t exist or you don\'t have access to it',
options : (_value, {
req,
path
}) => {
return new Promise((resolve, reject) => {
const template = this.getParamValue(req, path) as string;
if ( template ) {
void GitlabManager.checkTemplateAccess(template, req).then(templateAccess => {
templateAccess ? resolve(true) : reject();
});
}
resolve(true);
});
}
});
readonly templateUrlSanitizer = this.toValidatorSchemaOptions({
options: (value, {
req,
path
}) => {
try {
const template = this.getParamValue(req, path);
if ( template && Toolbox.isString(template) ) {
const gitlabUrlWithCredentials = Config.gitlab.urls[0].replace(/^([a-z]{3,5}:\/{2})?(.*)/, `$1${ Config.gitlab.account.username }:${ Config.gitlab.account.token }@$2`);
return `${ gitlabUrlWithCredentials }${ template }.git`;
} else {
return Config.assignment.default.template;
}
} catch ( error ) {
logger.error(`Template url sanitizer error: ${ JSON.stringify(error) }`);
return value;
}
}
});
readonly exerciseResultsValidator = this.toValidatorSchemaOptions({
bail : true,
errorMessage: 'Results: not provided or invalid format',
options : (_value, {
req,
path
}) => {
return new Promise((resolve, reject) => {
const results = this.getParamValue(req, path) as string;
if ( results ) {
Json5FileValidator.validateFile(ExerciseResultsFile, results, false).isValid ? resolve(true) : reject();
} else {
reject();
}
});
}
});
readonly exerciseIdOrUrlValidator = this.toValidatorSchemaOptions({
bail : true,
errorMessage: 'ExerciseIdOrUrl: not provided or invalid',
options : (_value, {
req,
path
}) => {
return new Promise((resolve, reject) => {
const exerciseIdOrUrl = this.getParamValue(req, path) as string;
if ( exerciseIdOrUrl ) {
ParamsCallbackManager.initBoundParams(req);
ExerciseManager.get(exerciseIdOrUrl).then(exercise => {
req.boundParams.exercise = exercise;
exercise !== undefined ? resolve(true) : reject();
}).catch(() => {
reject();
});
} else {
reject();
}
});
}
});
}
export default new DojoValidators();