mirror of https://gitee.com/bigwinds/arangodb
426 lines
13 KiB
JavaScript
426 lines
13 KiB
JavaScript
/*global applicationContext */
|
|
"use strict";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief A Foxx.Controller to show all Foxx Applications
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2013 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
(function() {
|
|
|
|
var internal = require("internal");
|
|
var db = require("org/arangodb").db;
|
|
var NotFound = require("http-errors").NotFound;
|
|
var FoxxController = require("org/arangodb/foxx").Controller;
|
|
var UnauthorizedError = require("http-errors").Unauthorized;
|
|
var controller = new FoxxController(applicationContext);
|
|
var ArangoError = require("org/arangodb").ArangoError;
|
|
var FoxxManager = require("org/arangodb/foxx/manager");
|
|
var fmUtils = require("org/arangodb/foxx/manager-utils");
|
|
var actions = require("org/arangodb/actions");
|
|
var joi = require("joi");
|
|
var marked = require("marked");
|
|
var highlightAuto = require("highlight.js").highlightAuto;
|
|
var docu = require("./lib/swagger").Swagger;
|
|
var underscore = require("underscore");
|
|
var mountPoint = {
|
|
type: joi.string().required().description(
|
|
"The mount point of the app. Has to be url-encoded."
|
|
)
|
|
};
|
|
var scriptName = {
|
|
type: joi.string().required().description(
|
|
"The name of an app's script to run."
|
|
)
|
|
};
|
|
var fs = require("fs");
|
|
var defaultThumb = require("/lib/defaultThumbnail").defaultThumb;
|
|
|
|
controller.activateSessions({
|
|
autoCreateSession: false,
|
|
cookie: {name: "arango_sid_" + db._name()}
|
|
});
|
|
|
|
controller.allRoutes
|
|
.errorResponse(UnauthorizedError, 401, "unauthorized")
|
|
.onlyIf(function (req, res) {
|
|
if (!internal.options()["server.disable-authentication"] && (!req.session || !req.session.get('uid'))) {
|
|
throw new UnauthorizedError();
|
|
}
|
|
});
|
|
|
|
controller.extend({
|
|
installer: function() {
|
|
this.queryParam("mount", mountPoint);
|
|
this.queryParam("upgrade", {type: joi.boolean().optional().description(
|
|
"Trigger to upgrade the app installed at the mountpoint. Triggers setup."
|
|
)});
|
|
this.queryParam("replace", {type: joi.boolean().optional().description(
|
|
"Trigger to replace the app installed at the mountpoint. Triggers teardown and setup."
|
|
)});
|
|
}
|
|
});
|
|
|
|
// ------------------------------------------------------------
|
|
// SECTION install
|
|
// ------------------------------------------------------------
|
|
|
|
var validateMount = function(req) {
|
|
var mount = req.params("mount");
|
|
// Validation
|
|
mount = decodeURIComponent(mount);
|
|
return mount;
|
|
};
|
|
|
|
var installApp = function(req, res, appInfo, options) {
|
|
var mount = validateMount(req);
|
|
var upgrade = req.params("upgrade") || false;
|
|
var replace = req.params("replace") || false;
|
|
var app;
|
|
if (upgrade) {
|
|
app = FoxxManager.upgrade(appInfo, mount, options);
|
|
} else if (replace) {
|
|
app = FoxxManager.replace(appInfo, mount, options);
|
|
} else {
|
|
app = FoxxManager.install(appInfo, mount, options);
|
|
}
|
|
var config = FoxxManager.configuration(mount);
|
|
res.json({
|
|
error: false,
|
|
configuration: config,
|
|
name: app.name,
|
|
version: app.version
|
|
});
|
|
};
|
|
|
|
/** Install a Foxx from the store
|
|
*
|
|
* Downloads a Foxx from the store and installs it at the given mount
|
|
*/
|
|
controller.put("/store", function(req, res) {
|
|
var content = JSON.parse(req.requestBody),
|
|
name = content.name,
|
|
version = content.version;
|
|
installApp(req, res, name + ":" + version);
|
|
})
|
|
.installer();
|
|
|
|
/** Install a Foxx from Github
|
|
*
|
|
* Install a Foxx with user/repository and version
|
|
*/
|
|
controller.put("/git", function (req, res) {
|
|
var content = JSON.parse(req.requestBody),
|
|
url = content.url,
|
|
version = content.version;
|
|
installApp(req, res, "git:" + url + ":" + (version || "master"));
|
|
})
|
|
.installer();
|
|
|
|
/** Generate a new foxx
|
|
*
|
|
* Generate a new empty foxx on the given mount point
|
|
*/
|
|
controller.put("/generate", function (req, res) {
|
|
var info = JSON.parse(req.requestBody);
|
|
installApp(req, res, "EMPTY", info);
|
|
})
|
|
.installer();
|
|
|
|
/** Install a Foxx from temporary zip file
|
|
*
|
|
* Install a Foxx from the given zip path.
|
|
* This path has to be created via _api/upload
|
|
*/
|
|
controller.put("/zip", function (req, res) {
|
|
var content = JSON.parse(req.requestBody),
|
|
file = content.zipFile;
|
|
installApp(req, res, file);
|
|
})
|
|
.installer();
|
|
|
|
|
|
/** Uninstall a Foxx
|
|
*
|
|
* Uninstall the Foxx at the given mount-point.
|
|
*/
|
|
controller.delete("/", function (req, res) {
|
|
var mount = validateMount(req);
|
|
var runTeardown = req.parameters.teardown;
|
|
var app = FoxxManager.uninstall(mount, {
|
|
teardown: runTeardown
|
|
});
|
|
res.json({
|
|
error: false,
|
|
name: app.name,
|
|
version: app.version
|
|
});
|
|
})
|
|
.queryParam("mount", mountPoint)
|
|
.queryParam("teardown", joi.boolean().default(true));
|
|
|
|
// ------------------------------------------------------------
|
|
// SECTION information
|
|
// ------------------------------------------------------------
|
|
|
|
/** List all Foxxes
|
|
*
|
|
* Get a List of all running foxxes
|
|
*/
|
|
controller.get('/', function (req, res) {
|
|
var foxxes = FoxxManager.listJson();
|
|
foxxes.forEach(function (foxx) {
|
|
var readme = FoxxManager.readme(foxx.mount);
|
|
if (readme) {
|
|
foxx.readme = marked(readme, {
|
|
highlight(code) {
|
|
return highlightAuto(code).value;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
res.json(foxxes);
|
|
});
|
|
|
|
/** Get the thumbnail of a Foxx
|
|
*
|
|
* Used to request the thumbnail of the given Foxx in order to display it on the screen.
|
|
*/
|
|
controller.get("/thumbnail", function (req, res) {
|
|
res.transformations = [ "base64decode" ];
|
|
var mount = validateMount(req);
|
|
var app = FoxxManager.lookupApp(mount);
|
|
if (app.hasOwnProperty("_thumbnail")) {
|
|
res.body = app._thumbnail;
|
|
} else {
|
|
res.body = defaultThumb;
|
|
}
|
|
// evil mimetype detection attempt...
|
|
var start = require("internal").base64Decode(res.body.substr(0, 8));
|
|
if (start.indexOf("PNG") !== -1) {
|
|
res.contentType = "image/png";
|
|
}
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Get the configuration for an app
|
|
*
|
|
* Used to request the configuration options for apps
|
|
*/
|
|
controller.get("/config", function(req, res) {
|
|
var mount = validateMount(req);
|
|
res.json(FoxxManager.configuration(mount));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Set the configuration for an app
|
|
*
|
|
* Used to overwrite the configuration options for apps
|
|
*/
|
|
controller.patch("/config", function(req, res) {
|
|
var mount = validateMount(req);
|
|
var data = req.body();
|
|
res.json(FoxxManager.configure(mount, {configuration: data}));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Get the dependencies for an app
|
|
*
|
|
* Used to request the dependencies options for apps
|
|
*/
|
|
controller.get("/deps", function(req, res) {
|
|
var mount = validateMount(req);
|
|
res.json(FoxxManager.dependencies(mount));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Set the dependencies for an app
|
|
*
|
|
* Used to overwrite the dependencies options for apps
|
|
*/
|
|
controller.patch("/deps", function(req, res) {
|
|
var mount = validateMount(req);
|
|
var data = req.body();
|
|
res.json(FoxxManager.updateDeps(mount, {dependencies: data}));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Run tests for an app
|
|
*
|
|
* Used to run the tests of an app
|
|
*/
|
|
controller.post("/tests", function (req, res) {
|
|
var options = req.body();
|
|
var mount = validateMount(req);
|
|
res.json(FoxxManager.runTests(mount, options));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Run a script for an app
|
|
*
|
|
* Used to trigger any script of an app
|
|
*/
|
|
controller.post("/scripts/:name", function (req, res) {
|
|
var mount = validateMount(req);
|
|
var name = req.params("name");
|
|
var argv = req.params("argv");
|
|
try {
|
|
res.json(FoxxManager.runScript(name, mount, argv));
|
|
} catch (e) {
|
|
throw e.cause || e;
|
|
}
|
|
})
|
|
.queryParam("mount", mountPoint)
|
|
.pathParam("name", scriptName)
|
|
.bodyParam(
|
|
"argv",
|
|
joi.any().default(null)
|
|
.description('Options to pass to the script.')
|
|
);
|
|
|
|
/** Trigger setup script for an app
|
|
*
|
|
* Used to trigger the setup script of an app
|
|
*/
|
|
controller.patch("/setup", function(req, res) {
|
|
var mount = validateMount(req);
|
|
res.json(FoxxManager.runScript("setup", mount));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
|
|
/** Trigger teardown script for an app
|
|
*
|
|
* Used to trigger the teardown script of an app
|
|
*/
|
|
controller.patch("/teardown", function(req, res) {
|
|
var mount = validateMount(req);
|
|
res.json(FoxxManager.runScript("teardown", mount));
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
|
|
/** Activate/Deactivate development mode for an app
|
|
*
|
|
* Used to toggle between production and development mode
|
|
*/
|
|
controller.patch("/devel", function(req, res) {
|
|
var mount = validateMount(req);
|
|
var activate = Boolean(req.body());
|
|
if (activate) {
|
|
res.json(FoxxManager.development(mount));
|
|
} else {
|
|
res.json(FoxxManager.production(mount));
|
|
}
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
|
|
/** Download an app as zip archive
|
|
*
|
|
* Download a foxx app packed in a zip archive
|
|
*/
|
|
|
|
controller.get("/download/zip", function(req, res) {
|
|
var mount = validateMount(req);
|
|
var app = FoxxManager.lookupApp(mount);
|
|
var dir = fs.join(fs.makeAbsolute(app._root), app._path);
|
|
var zipPath = fmUtils.zipDirectory(dir);
|
|
res.set("Content-Type", "application/octet-stream");
|
|
res.set("Content-Disposition", "attachment; filename=app.zip");
|
|
res.body = fs.readFileSync(zipPath);
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
// SECTION store
|
|
// ------------------------------------------------------------
|
|
|
|
/** List all Foxxes in Fishbowl
|
|
*
|
|
* Get the information for all Apps availbale in the Fishbowl and ready for download
|
|
*
|
|
*/
|
|
controller.get('/fishbowl', function (req, res) {
|
|
FoxxManager.update();
|
|
res.json(FoxxManager.availableJson());
|
|
}).summary("List of all foxx apps submitted to the fishbowl store.")
|
|
.notes("This function contacts the fishbowl and reports which apps are available for install")
|
|
.errorResponse(ArangoError, 503, "Could not connect to store.");
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
// SECTION documentation
|
|
// ------------------------------------------------------------
|
|
|
|
controller.apiDocumentation('/docs/standalone', function (req, res) {
|
|
return {
|
|
appPath: req.parameters.mount
|
|
};
|
|
});
|
|
|
|
controller.apiDocumentation('/docs', function (req, res) {
|
|
return {
|
|
indexFile: 'index-alt.html',
|
|
appPath: req.parameters.mount
|
|
};
|
|
});
|
|
|
|
/** Returns the billboard URL for swagger
|
|
*
|
|
* Returns the billboard URL for the application mounted
|
|
* at the given mountpoint
|
|
*/
|
|
controller.get('/billboard', function(req, res) {
|
|
var mount = decodeURIComponent(decodeURIComponent(req.params("mount")));
|
|
var path = req.protocol + "://" + req.headers.host +
|
|
"/_db/" + encodeURIComponent(req.database) +
|
|
"/_admin/aardvark/foxxes/docu";
|
|
res.json({
|
|
swaggerVersion: "1.1",
|
|
basePath: path,
|
|
apis: [
|
|
{path: mount}
|
|
]
|
|
});
|
|
})
|
|
.queryParam("mount", mountPoint);
|
|
|
|
/** Returns the generated Swagger JSON description for one foxx
|
|
*
|
|
* This function returns the Swagger JSON API description of the foxx
|
|
* installed under the given mount point.
|
|
*/
|
|
controller.get('/docu/*', function(req, res) {
|
|
var mount = "";
|
|
underscore.each(req.suffix, function(part) {
|
|
mount += "/" + part;
|
|
});
|
|
res.json(docu(mount));
|
|
});
|
|
|
|
}());
|