api: add validators to endpoints
This commit is contained in:
parent
9d32012bbc
commit
8b61f4f69f
|
@ -3,19 +3,35 @@
|
||||||
|
|
||||||
const { get_latest_runtime_matching_language_version } = require('../runtime');
|
const { get_latest_runtime_matching_language_version } = require('../runtime');
|
||||||
const { Job } = require('./job');
|
const { Job } = require('./job');
|
||||||
|
const { body } = require('express-validator');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
run_job_validators: [
|
||||||
|
body('language')
|
||||||
|
.isString(),
|
||||||
|
body('version')
|
||||||
|
.isSemVer(),
|
||||||
|
body('files')
|
||||||
|
.isArray(),
|
||||||
|
body('files.*.name')
|
||||||
|
.isString()
|
||||||
|
.bail()
|
||||||
|
.not()
|
||||||
|
.contains('/'),
|
||||||
|
body('files.*.content')
|
||||||
|
.isString(),
|
||||||
|
body('*_timeout')
|
||||||
|
.isNumeric(),
|
||||||
|
body('stdin')
|
||||||
|
.isString(),
|
||||||
|
body('args')
|
||||||
|
.isArray(),
|
||||||
|
body('args.*')
|
||||||
|
.isString()
|
||||||
|
],
|
||||||
async run_job(req, res){
|
async run_job(req, res){
|
||||||
// POST /jobs
|
// POST /jobs
|
||||||
var errored = false;
|
|
||||||
['language', 'version',
|
|
||||||
'files', 'main',
|
|
||||||
'args', 'stdin',
|
|
||||||
'compile_timeout', 'run_timeout',
|
|
||||||
].forEach(key => {
|
|
||||||
if(req.body[key] == undefined) errored = errored || res.json_error(`${key} is required`, 400);
|
|
||||||
});
|
|
||||||
if(errored) return errored;
|
|
||||||
|
|
||||||
const runtime = get_latest_runtime_matching_language_version(req.body.language, req.body.version);
|
const runtime = get_latest_runtime_matching_language_version(req.body.language, req.body.version);
|
||||||
if(runtime == undefined) return res.json_error(`${req.body.language}-${req.body.version} runtime is unknown`, 400);
|
if(runtime == undefined) return res.json_error(`${req.body.language}-${req.body.version} runtime is unknown`, 400);
|
||||||
|
|
|
@ -11,6 +11,7 @@ const fs = require('fs/promises');
|
||||||
const fss = require('fs');
|
const fss = require('fs');
|
||||||
const body_parser = require('body-parser');
|
const body_parser = require('body-parser');
|
||||||
const runtime = require('./runtime');
|
const runtime = require('./runtime');
|
||||||
|
const {validationResult} = require('express-validator');
|
||||||
|
|
||||||
const logger = Logger.create('index');
|
const logger = Logger.create('index');
|
||||||
const app = express();
|
const app = express();
|
||||||
|
@ -58,11 +59,6 @@ const app = express();
|
||||||
|
|
||||||
logger.debug('Constructing Express App');
|
logger.debug('Constructing Express App');
|
||||||
|
|
||||||
logger.debug('Registering middleware');
|
|
||||||
|
|
||||||
app.use(body_parser.urlencoded({extended: true}));
|
|
||||||
app.use(body_parser.json());
|
|
||||||
|
|
||||||
logger.debug('Registering custom message wrappers');
|
logger.debug('Registering custom message wrappers');
|
||||||
|
|
||||||
express.response.json_error = function(message, code) {
|
express.response.json_error = function(message, code) {
|
||||||
|
@ -74,23 +70,33 @@ const app = express();
|
||||||
return this.json({success: true, data: obj});
|
return this.json({success: true, data: obj});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
logger.debug('Registering middleware');
|
||||||
|
|
||||||
|
app.use(body_parser.urlencoded({extended: true}));
|
||||||
|
app.use(body_parser.json());
|
||||||
|
|
||||||
|
|
||||||
|
function validate(req, res, next) {
|
||||||
|
const errors = validationResult(req);
|
||||||
|
if (!errors.isEmpty())
|
||||||
|
return res.json_error(errors.array(), 422);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug('Registering Routes');
|
logger.debug('Registering Routes');
|
||||||
|
|
||||||
const ppman_routes = require('./ppman/routes');
|
const ppman_routes = require('./ppman/routes');
|
||||||
|
|
||||||
app.get ('/repos', ppman_routes.repo_list);
|
app.get ('/repos', validate, ppman_routes.repo_list);
|
||||||
app.post ('/repos', ppman_routes.repo_add);
|
app.post ('/repos', ppman_routes.repo_add_validators, validate, ppman_routes.repo_add);
|
||||||
app.get ('/repos/:repo_slug', ppman_routes.repo_info);
|
app.get ('/repos/:repo_slug', ppman_routes.repo_info_validators, validate, ppman_routes.repo_info);
|
||||||
app.get ('/repos/:repo_slug/packages', ppman_routes.repo_packages);
|
app.get ('/repos/:repo_slug/packages', ppman_routes.repo_packages_validators, validate, ppman_routes.repo_packages);
|
||||||
app.get ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info);
|
app.get ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_info);
|
||||||
app.post ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_install);
|
app.post ('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_install);
|
||||||
app.delete('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_uninstall); //TODO
|
app.delete('/repos/:repo_slug/packages/:language/:version', ppman_routes.package_info_validators, validate, ppman_routes.package_uninstall); //TODO
|
||||||
|
|
||||||
const executor_routes = require('./executor/routes');
|
const executor_routes = require('./executor/routes');
|
||||||
app.post ('/jobs', executor_routes.run_job);
|
app.post ('/jobs', executor_routes.run_job_validators, validate, executor_routes.run_job);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger.debug('Calling app.listen');
|
logger.debug('Calling app.listen');
|
||||||
const [address,port] = config.bind_address.split(':');
|
const [address,port] = config.bind_address.split(':');
|
||||||
|
|
|
@ -3,6 +3,7 @@ const state = require('../state');
|
||||||
const logger = require('logplease').create('ppman/routes');
|
const logger = require('logplease').create('ppman/routes');
|
||||||
const {Repository} = require('./repo');
|
const {Repository} = require('./repo');
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
|
const { body, param } = require('express-validator');
|
||||||
|
|
||||||
async function get_or_construct_repo(slug){
|
async function get_or_construct_repo(slug){
|
||||||
if(repos.has(slug))return repos.get(slug);
|
if(repos.has(slug))return repos.get(slug);
|
||||||
|
@ -39,38 +40,61 @@ module.exports = {
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
repo_add_validators: [
|
||||||
|
body('slug')
|
||||||
|
.notEmpty()
|
||||||
|
.bail()
|
||||||
|
.isSlug()
|
||||||
|
.bail()
|
||||||
|
.not()
|
||||||
|
.custom(value=>state.state.get('repositories').keys().includes(value))
|
||||||
|
.withMessage("slug is already in use"),
|
||||||
|
body('url')
|
||||||
|
.notEmpty()
|
||||||
|
.bail()
|
||||||
|
.isURL({require_protocol: true})
|
||||||
|
|
||||||
|
],
|
||||||
async repo_add(req, res){
|
async repo_add(req, res){
|
||||||
// POST /repos
|
// POST /repos
|
||||||
|
|
||||||
logger.debug(`Request for repoAdd slug=${req.body.slug} url=${req.body.url}`);
|
logger.debug(`Request for repoAdd slug=${req.body.slug} url=${req.body.url}`);
|
||||||
if(!req.body.slug)
|
|
||||||
return res.json_error('slug is missing from request body', 400);
|
|
||||||
if(!req.body.url)
|
|
||||||
return res.json_error('url is missing from request body', 400);
|
|
||||||
|
|
||||||
const repo_state = state.state.get('repositories');
|
const repo_state = state.state.get('repositories');
|
||||||
|
|
||||||
if(repo_state.has(req.body.slug)) return res.json_error(`repository ${req.body.slug} already exists`, 409);
|
|
||||||
|
|
||||||
repo_state.set(req.body.slug, req.body.url);
|
repo_state.set(req.body.slug, req.body.url);
|
||||||
logger.info(`Repository ${req.body.slug} added url=${req.body.url}`);
|
logger.info(`Repository ${req.body.slug} added url=${req.body.url}`);
|
||||||
|
|
||||||
return res.json_success(req.body.slug);
|
return res.json_success(req.body.slug);
|
||||||
},
|
},
|
||||||
|
repo_info_validators: [
|
||||||
|
param('repo_slug')
|
||||||
|
.isSlug()
|
||||||
|
.bail()
|
||||||
|
.custom(value=>state.state.get('repositories').has(value))
|
||||||
|
.withMessage("repository does not exist")
|
||||||
|
.bail()
|
||||||
|
],
|
||||||
async repo_info(req, res){
|
async repo_info(req, res){
|
||||||
// GET /repos/:slug
|
// GET /repos/:slug
|
||||||
|
|
||||||
logger.debug(`Request for repoInfo for ${req.params.repo_slug}`);
|
logger.debug(`Request for repoInfo for ${req.params.repo_slug}`);
|
||||||
const repo = await get_or_construct_repo(req.params.repo_slug);
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
||||||
|
|
||||||
if(repo == null) return res.json_error(`Requested repo ${req.params.repo_slug} does not exist`, 404);
|
|
||||||
|
|
||||||
res.json_success({
|
res.json_success({
|
||||||
slug: repo.slug,
|
slug: repo.slug,
|
||||||
url: repo.url,
|
url: repo.url,
|
||||||
packages: repo.packages.length
|
packages: repo.packages.length
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
repo_packages_validators: [
|
||||||
|
param('repo_slug')
|
||||||
|
.isSlug()
|
||||||
|
.bail()
|
||||||
|
.custom(value=>state.state.get('repositories').has(value))
|
||||||
|
.withMessage("repository does not exist")
|
||||||
|
.bail()
|
||||||
|
],
|
||||||
async repo_packages(req, res){
|
async repo_packages(req, res){
|
||||||
// GET /repos/:slug/packages
|
// GET /repos/:slug/packages
|
||||||
logger.debug('Request to repoPackages');
|
logger.debug('Request to repoPackages');
|
||||||
|
@ -86,13 +110,20 @@ module.exports = {
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
package_info_validators: [
|
||||||
|
param('repo_slug')
|
||||||
|
.isSlug()
|
||||||
|
.bail()
|
||||||
|
.custom(value=>state.state.get('repositories').has(value))
|
||||||
|
.withMessage("repository does not exist")
|
||||||
|
.bail()
|
||||||
|
],
|
||||||
async package_info(req, res){
|
async package_info(req, res){
|
||||||
// GET /repos/:slug/packages/:language/:version
|
// GET /repos/:slug/packages/:language/:version
|
||||||
|
|
||||||
logger.debug('Request to packageInfo');
|
logger.debug('Request to packageInfo');
|
||||||
|
|
||||||
const repo = await get_or_construct_repo(req.params.repo_slug);
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
||||||
if(repo == null) return res.json_error(`Requested repo ${req.params.repo_slug} does not exist`, 404);
|
|
||||||
|
|
||||||
const pkg = await get_package(repo, req.params.language, req.params.version);
|
const pkg = await get_package(repo, req.params.language, req.params.version);
|
||||||
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
||||||
|
@ -113,8 +144,6 @@ module.exports = {
|
||||||
logger.debug('Request to packageInstall');
|
logger.debug('Request to packageInstall');
|
||||||
|
|
||||||
const repo = await get_or_construct_repo(req.params.repo_slug);
|
const repo = await get_or_construct_repo(req.params.repo_slug);
|
||||||
if(repo == null) return res.json_error(`Requested repo ${req.params.repo_slug} does not exist`, 404);
|
|
||||||
|
|
||||||
const pkg = await get_package(repo, req.params.language, req.params.version);
|
const pkg = await get_package(repo, req.params.language, req.params.version);
|
||||||
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
if(pkg == null) return res.json_error(`Requested package ${req.params.language}-${req.params.version} does not exist`, 404);
|
||||||
|
|
||||||
|
@ -131,6 +160,7 @@ module.exports = {
|
||||||
async package_uninstall(req,res){
|
async package_uninstall(req,res){
|
||||||
// DELETE /repos/:slug/packages/:language/:version
|
// DELETE /repos/:slug/packages/:language/:version
|
||||||
|
|
||||||
res.json(req.body); //TODO
|
//res.json(req.body); //TODO
|
||||||
|
res.json_error("not implemented", 500)
|
||||||
}
|
}
|
||||||
};
|
};
|
Loading…
Reference in New Issue