1
0
Fork 0

Validate manifest using joi.

This commit is contained in:
Alan Plum 2015-03-11 12:52:29 +01:00
parent ae02f7c4df
commit 079b8c554b
1 changed files with 59 additions and 76 deletions

View File

@ -39,6 +39,7 @@
var db = require("internal").db; var db = require("internal").db;
var fs = require("fs"); var fs = require("fs");
var joi = require("joi");
var utils = require("org/arangodb/foxx/manager-utils"); var utils = require("org/arangodb/foxx/manager-utils");
var store = require("org/arangodb/foxx/store"); var store = require("org/arangodb/foxx/store");
var console = require("console"); var console = require("console");
@ -61,27 +62,30 @@
var throwFileNotFound = arangodb.throwFileNotFound; var throwFileNotFound = arangodb.throwFileNotFound;
var manifestSchema = { var manifestSchema = {
"assets": [ false, "object" ], assets: joi.object().optional(),
"author": [ false, "string" ], author: joi.string().allow("").default(""),
"configuration": [ false, "object" ], configuration: joi.object().optional(),
"contributors": [ false, "array" ], contributors: joi.array().optional(),
"controllers": [ false, "object" ], controllers: joi.object().optional(),
"defaultDocument": [ false, "string" ], defaultDocument: joi.string().allow("").optional(),
"description": [ true, "string" ], description: joi.string().allow("").default(""),
"engines": [ false, "object" ], engines: joi.object().optional(),
"files": [ false, "object" ], exports: joi.alternatives().try(
"isSystem": [ false, "boolean" ], joi.string().optional(),
"keywords": [ false, "array" ], joi.object().optional()
"lib": [ false, "string" ], ),
"license": [ false, "string" ], files: joi.object().optional(),
"name": [ true, "string" ], isSystem: joi.boolean().default(false),
"repository": [ false, "object" ], keywords: joi.array().optional(),
"setup": [ false, "string" ], lib: joi.string().optional(),
"teardown": [ false, "string" ], license: joi.string().optional(),
"thumbnail": [ false, "string" ], name: joi.string().required(),
"version": [ true, "string" ], repository: joi.object().optional(),
"rootElement": [ false, "boolean" ], setup: joi.string().optional(),
"exports": [ false, ["object", "string"] ] teardown: joi.string().optional(),
thumbnail: joi.string().optional(),
version: joi.string().required(),
rootElement: joi.boolean().default(false)
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -209,73 +213,52 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var checkManifest = function(filename, manifest) { var checkManifest = function(filename, manifest) {
// add some default attributes
if (!manifest.hasOwnProperty("author")) {
// add a default (empty) author
manifest.author = "";
}
if (!manifest.hasOwnProperty("description")) {
// add a default (empty) description
manifest.description = "";
}
// Validate all attributes specified in the manifest
// the following attributes are allowed with these types...
var failed = !Object.keys(manifestSchema).every(function (key) {
var valid = true; var valid = true;
if (manifest.hasOwnProperty(key)) { Object.keys(manifestSchema).forEach(function (key) {
// attribute is present in manifest, now check data type var schema = manifestSchema[key];
var expectedType = manifestSchema[key][1]; var value = manifest[key];
var actualType = Array.isArray(manifest[key]) ? "array" : typeof(manifest[key]); var result = joi.validate(value, schema);
if (result.value !== undefined) {
if (!Array.isArray(expectedType)) { manifest[key] = result.value;
valid = (actualType === expectedType);
} else {
valid = expectedType.some(function (type) {
return actualType === type;
});
} }
if (result.error) {
if (!valid) { valid = false;
console.error("Manifest '%s' uses an invalid data type (%s) for %s attribute '%s'", if (value === undefined) {
console.error(
"Manifest '%s' %s for attribute '%s'",
filename, filename,
actualType, result.error.message,
String(expectedType), key
key); );
}
} else { } else {
// attribute not present in manifest console.error(
valid = manifestSchema[key][0]; "Manifest '%s' %s (%s) for attribute '%s'",
if (!valid) {
// required attribute
console.error("Manifest '%s' does not provide required attribute '%s'",
filename, filename,
key); result.error.message,
manifest[key],
key
);
} }
} }
return valid;
}); });
if (failed) { Object.keys(manifest).forEach(function (key) {
if (!manifestSchema[key]) {
console.warn(
"Manifest '%s' contains an unknown attribute '%s'",
filename,
key
);
}
});
if (!valid) {
throw new ArangoError({ throw new ArangoError({
errorNum: errors.ERROR_MANIFEST_FILE_ATTRIBUTE_MISSING.code, errorNum: errors.ERROR_MANIFEST_FILE_ATTRIBUTE_MISSING.code,
errorMessage: errors.ERROR_MANIFEST_FILE_ATTRIBUTE_MISSING.message errorMessage: errors.ERROR_MANIFEST_FILE_ATTRIBUTE_MISSING.message
}); });
} }
// additionally check if there are superfluous attributes in the manifest
Object.keys(manifest).forEach(function (key) {
if (!manifestSchema.hasOwnProperty(key)) {
console.warn("Manifest '%s' contains an unknown attribute '%s'",
filename,
key);
}
});
}; };