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 var valid = true;
if (!manifest.hasOwnProperty("author")) {
// add a default (empty) author
manifest.author = "";
}
if (!manifest.hasOwnProperty("description")) { Object.keys(manifestSchema).forEach(function (key) {
// add a default (empty) description var schema = manifestSchema[key];
manifest.description = ""; var value = manifest[key];
} var result = joi.validate(value, schema);
if (result.value !== undefined) {
// Validate all attributes specified in the manifest manifest[key] = result.value;
// the following attributes are allowed with these types... }
if (result.error) {
var failed = !Object.keys(manifestSchema).every(function (key) { valid = false;
var valid = true; if (value === undefined) {
console.error(
if (manifest.hasOwnProperty(key)) { "Manifest '%s' %s for attribute '%s'",
// attribute is present in manifest, now check data type filename,
var expectedType = manifestSchema[key][1]; result.error.message,
var actualType = Array.isArray(manifest[key]) ? "array" : typeof(manifest[key]); key
);
if (!Array.isArray(expectedType)) {
valid = (actualType === expectedType);
} else { } else {
valid = expectedType.some(function (type) { console.error(
return actualType === type; "Manifest '%s' %s (%s) for attribute '%s'",
});
}
if (!valid) {
console.error("Manifest '%s' uses an invalid data type (%s) for %s attribute '%s'",
filename, filename,
actualType, result.error.message,
String(expectedType), manifest[key],
key); key
} );
} else {
// attribute not present in manifest
valid = manifestSchema[key][0];
if (!valid) {
// required attribute
console.error("Manifest '%s' does not provide required attribute '%s'",
filename,
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);
}
});
}; };